diff --git a/.github/config-allowlist.txt b/.github/config-allowlist.txt
index 2ec5891a14..d6a43a5140 100644
--- a/.github/config-allowlist.txt
+++ b/.github/config-allowlist.txt
@@ -87,6 +87,7 @@ packages/a2ui-renderer/tsdown.config.ts
packages/agentcore-runner/tsdown.config.ts
packages/core/tsdown.config.ts
packages/demo-agents/tsdown.config.ts
+packages/mcp-apps-renderer/tsdown.config.ts
packages/react-core/tsdown.config.ts
packages/react-native/tsdown.config.ts
packages/react-textarea/tsdown.config.ts
diff --git a/.github/workflows/static_bundle_size.yml b/.github/workflows/static_bundle_size.yml
index 6673b61642..2d9add37cf 100644
--- a/.github/workflows/static_bundle_size.yml
+++ b/.github/workflows/static_bundle_size.yml
@@ -19,7 +19,7 @@ env:
NX_VERBOSE_LOGGING: true
jobs:
- # Posts a per-PR comment with per-file gzip diffs for the 10 in-scope packages.
+ # Posts a per-PR comment with per-file gzip diffs for the 11 in-scope packages.
# Runs preactjs/compressed-size-action, which builds the PR head and the base
# branch, scans the `pattern` glob in each, and diffs the gzip sizes; the
# comment updates in place on subsequent pushes. No hard-fail (Phase 1) — see
@@ -64,9 +64,9 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Use the root `build` script (present on both this branch and the base
# branch) so compressed-size-action can build both sides for comparison.
- # The `pattern` below restricts measurement to the 10 in-scope packages.
+ # The `pattern` below restricts measurement to the 11 in-scope packages.
build-script: build
- pattern: "packages/{core,shared,react-core,react-ui,react-textarea,runtime-client-gql,web-inspector,voice,a2ui-renderer,react-native}/dist/**/*.{mjs,js,cjs}"
+ pattern: "packages/{core,shared,react-core,react-ui,react-textarea,runtime-client-gql,web-inspector,voice,a2ui-renderer,react-native,mcp-apps-renderer}/dist/**/*.{mjs,js,cjs}"
# Measures what an app importing { CopilotChat } from
# @copilotkit/react-core/v2 bundles, by driving esbuild over a synthetic entry
diff --git a/.github/workflows/static_compat.yml b/.github/workflows/static_compat.yml
index 6a86bb9e8e..928b475bde 100644
--- a/.github/workflows/static_compat.yml
+++ b/.github/workflows/static_compat.yml
@@ -49,9 +49,9 @@ jobs:
- name: Build packages
run: >
npx nx run-many -t build
- --projects=@copilotkit/core,@copilotkit/shared,@copilotkit/react-core,@copilotkit/react-ui,@copilotkit/react-textarea,@copilotkit/runtime-client-gql,@copilotkit/web-inspector,@copilotkit/voice,@copilotkit/a2ui-renderer
+ --projects=@copilotkit/core,@copilotkit/shared,@copilotkit/react-core,@copilotkit/react-ui,@copilotkit/react-textarea,@copilotkit/runtime-client-gql,@copilotkit/web-inspector,@copilotkit/voice,@copilotkit/a2ui-renderer,@copilotkit/mcp-apps-renderer
- name: Run compat-check
run: >
npx nx run-many -t compat-check
- --projects=@copilotkit/core,@copilotkit/shared,@copilotkit/react-core,@copilotkit/react-ui,@copilotkit/react-textarea,@copilotkit/runtime-client-gql,@copilotkit/web-inspector,@copilotkit/voice,@copilotkit/a2ui-renderer
+ --projects=@copilotkit/core,@copilotkit/shared,@copilotkit/react-core,@copilotkit/react-ui,@copilotkit/react-textarea,@copilotkit/runtime-client-gql,@copilotkit/web-inspector,@copilotkit/voice,@copilotkit/a2ui-renderer,@copilotkit/mcp-apps-renderer
diff --git a/examples/v1/next-pages-router/next.config.mjs b/examples/v1/next-pages-router/next.config.mjs
index d5456a15d4..8d688f7fa8 100644
--- a/examples/v1/next-pages-router/next.config.mjs
+++ b/examples/v1/next-pages-router/next.config.mjs
@@ -1,6 +1,12 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
+ // Bundle the SDK's global KaTeX CSS for the Pages Router.
+ transpilePackages: ["@copilotkit/react-core"],
+ experimental: {
+ // react-syntax-highlighter's CommonJS entry loads ESM refractor languages.
+ esmExternals: "loose",
+ },
};
export default nextConfig;
diff --git a/examples/v1/next-pages-router/package.json b/examples/v1/next-pages-router/package.json
index 4dac686e68..8d2a39535c 100644
--- a/examples/v1/next-pages-router/package.json
+++ b/examples/v1/next-pages-router/package.json
@@ -18,7 +18,7 @@
"@google/generative-ai": "^0.11.2",
"@heroicons/react": "^2.0.18",
"clsx": "^1.2.1",
- "next": "14.2.35",
+ "next": "15.5.24",
"openai": "^4.85.1",
"react": "^18",
"react-dom": "^18"
diff --git a/examples/v1/next-pages-router/pages/api/copilotkit.ts b/examples/v1/next-pages-router/pages/api/copilotkit.ts
index b0add0eeb6..ff4771d0e3 100644
--- a/examples/v1/next-pages-router/pages/api/copilotkit.ts
+++ b/examples/v1/next-pages-router/pages/api/copilotkit.ts
@@ -3,11 +3,9 @@ import {
OpenAIAdapter,
copilotRuntimeNextJSPagesRouterEndpoint,
} from "@copilotkit/runtime";
-import { NextApiRequest, NextApiResponse } from "next";
-import OpenAI from "openai";
+import type { NextApiRequest, NextApiResponse } from "next";
-const openai = new OpenAI();
-const serviceAdapter = new OpenAIAdapter({ openai });
+const serviceAdapter = new OpenAIAdapter();
const runtime = new CopilotRuntime({
actions: [
diff --git a/examples/v1/state-machine/package.json b/examples/v1/state-machine/package.json
index 522803c338..52732549ba 100644
--- a/examples/v1/state-machine/package.json
+++ b/examples/v1/state-machine/package.json
@@ -15,7 +15,7 @@
"@copilotkit/runtime-client-gql": "workspace:*",
"clsx": "^1.2.1",
"motion": "^11.18.1",
- "next": "14.2.35",
+ "next": "15.5.24",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"reactflow": "^11.11.4",
diff --git a/examples/v1/travel/package.json b/examples/v1/travel/package.json
index abb214e380..cb1937ca93 100644
--- a/examples/v1/travel/package.json
+++ b/examples/v1/travel/package.json
@@ -33,7 +33,7 @@
"groq-sdk": "^0.5.0",
"leaflet": "^1.9.4",
"lucide-react": "^0.414.0",
- "next": "14.2.35",
+ "next": "15.5.24",
"openai": "^4.85.1",
"react": "18.3.1",
"react-dom": "18.3.1",
diff --git a/package.json b/package.json
index 730fab57aa..ffdc56aa9c 100644
--- a/package.json
+++ b/package.json
@@ -92,7 +92,7 @@
"vitest": "^4.1.3"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"packageManager": "pnpm@10.33.4",
"pnpm": {
@@ -106,21 +106,20 @@
"react-dom": "*"
}
},
+ "//": "Next.js overrides keep each supported major on its security floor (GHSA-2xp9-vwfh-vxw4, GHSA-p293-qw3h-jr36). Next 14 examples declare Next 15 explicitly because neither advisory has a Next 14 fix.",
"overrides": {
"streamdown>react": "^19.0.0",
"@types/react": "19.1.8",
"@types/react-dom": "^19.0.2",
"react": "19.2.3",
"react-dom": "19.2.3",
- "next@<=15.4.11": "15.4.11",
- "next@>=15.5.0 <15.5.15": "15.5.15",
+ "next@>=15.0.0 <15.5.24": "15.5.24",
+ "next@>=16.0.0 <16.3.3": "16.3.3",
"send@<=0.19.0": "0.19.0",
"path-to-regexp@<=0.1.12": "0.1.13",
"serve-static@<=1.16.0": "1.16.0",
"prismjs@<=1.30.0": "1.30.0",
- "pino@<=10.1.1": "10.1.1",
"@copilotkit/license-verifier": "~0.5.0",
- "next": "^16.0.10",
"defu@<=6.1.4": ">=6.1.5",
"minimatch": ">=9.0.6",
"minimatch@>=10.0.0 <10.2.1": ">=10.2.1",
@@ -169,7 +168,6 @@
"file-type": ">=21.3.1",
"@langchain/community": ">=1.1.14",
"langsmith": ">=0.5.18",
- "next@>=16.0.0 <16.2.3": "16.2.3",
"validator": ">=13.15.20",
"markdown-it": ">=14.1.1",
"mdast-util-to-hast@>=13.0.0 <13.2.1": ">=13.2.1",
diff --git a/packages/agentcore-runner/package.json b/packages/agentcore-runner/package.json
index 8aff2681a6..053239916a 100644
--- a/packages/agentcore-runner/package.json
+++ b/packages/agentcore-runner/package.json
@@ -44,6 +44,6 @@
"vitest": "^3.0.5"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/core/package.json b/packages/core/package.json
index 63e64f9b2e..39fbdf8776 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -58,6 +58,6 @@
"zod": "^3.25.75"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/mcp-apps-renderer/README.md b/packages/mcp-apps-renderer/README.md
new file mode 100644
index 0000000000..31a47cc930
--- /dev/null
+++ b/packages/mcp-apps-renderer/README.md
@@ -0,0 +1,45 @@
+# @copilotkit/mcp-apps-renderer
+
+Framework-agnostic MCP Apps host for CopilotKit: the app↔host protocol on top of
+[`@modelcontextprotocol/ext-apps`](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps)
+(AppBridge + PostMessage transport, sandbox proxy, per-thread request queue,
+`ui/message` / `ui/open-link` / `tools/call` proxy, tool input/result forwarding,
+`ui/request-display-mode`). The React / Vue / Angular renderers consume it as thin
+adapters: they create the sandbox iframe and wire reactive state, while all
+protocol logic lives in `bindMcpApp`.
+
+## Entry points
+
+| Import | Contents | Bundle |
+| ---------------------------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
+| `@copilotkit/mcp-apps-renderer` | `bindMcpApp` + the full session API | **ESM only** — it wraps the ESM-only ext-apps bridge, and is meant to be loaded lazily via a dynamic `import()`. |
+| `@copilotkit/mcp-apps-renderer/activity` | `MCPAppsActivityType`, `MCPAppsActivityContentSchema`, `ɵrunMcpFollowUp` | ESM + CJS. Bridge-free: importing it to register the activity does **not** pull the ext-apps bundle. |
+
+The root is ESM-only on purpose: `@modelcontextprotocol/ext-apps` ships ESM only,
+so a CommonJS root would emit a `require()` of an ES module and fail with
+`ERR_REQUIRE_ESM`. Consume `bindMcpApp` via a dynamic `import()` (which resolves
+ESM from any module system), and import the bridge-free `/activity` surface for
+synchronous activity registration.
+
+## Script-tag / UMD usage
+
+This package also ships a UMD build of the bridge-free `/activity` entry:
+`dist/activity.umd.js`, which defines the global
+`CopilotKitMcpAppsRendererActivity`.
+
+`@copilotkit/react-core`'s UMD build references that global (it externalizes
+`@copilotkit/mcp-apps-renderer/activity` to register the built-in MCP Apps
+activity). **Script-tag consumers of react-core's UMD must therefore load
+`activity.umd.js` before `@copilotkit/react-core`'s UMD bundle**, alongside the
+other UMD globals it depends on (React, `CopilotKitCore`,
+`CopilotKitA2UIRenderer`, …):
+
+```html
+
+
+
+```
+
+Only the bridge-free `/activity` surface has a UMD build; the ext-apps bridge
+itself (`bindMcpApp`) is loaded lazily via `import()` and is not part of the UMD
+graph, so it only loads when an MCP App is actually rendered.
diff --git a/packages/mcp-apps-renderer/package.json b/packages/mcp-apps-renderer/package.json
new file mode 100644
index 0000000000..0c7754517c
--- /dev/null
+++ b/packages/mcp-apps-renderer/package.json
@@ -0,0 +1,77 @@
+{
+ "name": "@copilotkit/mcp-apps-renderer",
+ "version": "1.71.0",
+ "private": false,
+ "description": "Framework-agnostic MCP Apps host for CopilotKit - the app<->host protocol (ext-apps AppBridge), sandbox proxy, and shared renderer consumed by the React, Vue, and Angular frontends",
+ "keywords": [
+ "ai",
+ "copilotkit",
+ "mcp",
+ "mcp-apps",
+ "ext-apps",
+ "renderer",
+ "ui"
+ ],
+ "homepage": "https://github.com/CopilotKit/CopilotKit",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/CopilotKit/CopilotKit.git",
+ "directory": "packages/mcp-apps-renderer"
+ },
+ "files": [
+ "dist"
+ ],
+ "type": "module",
+ "module": "./dist/index.mjs",
+ "types": "./dist/index.d.mts",
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./dist/index.d.mts",
+ "default": "./dist/index.mjs"
+ }
+ },
+ "./activity": {
+ "import": {
+ "types": "./dist/activity.d.mts",
+ "default": "./dist/activity.mjs"
+ },
+ "require": {
+ "types": "./dist/activity.d.cts",
+ "default": "./dist/activity.cjs"
+ }
+ },
+ "./package.json": "./package.json"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "build": "tsdown",
+ "compat-check": "es-check es2022 --module 'dist/**/!(*.umd).{mjs,cjs,js}' && es-check es2018 'dist/**/*.umd.js'",
+ "check-types": "tsc --noEmit -p tsconfig.json",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "publint": "publint .",
+ "attw": "attw --pack . --profile esm-only --entrypoints . && attw --pack . --profile node16 --exclude-entrypoints ."
+ },
+ "dependencies": {
+ "@copilotkit/shared": "workspace:*",
+ "@modelcontextprotocol/ext-apps": "^1.7.5",
+ "@modelcontextprotocol/sdk": "^1.29.0"
+ },
+ "peerDependencies": {
+ "@ag-ui/client": "0.0.59",
+ "zod": ">=3.25"
+ },
+ "devDependencies": {
+ "@ag-ui/client": "0.0.59",
+ "@modelcontextprotocol/sdk": "^1.29.0",
+ "jsdom": "^26.1.0",
+ "tsdown": "^0.20.3",
+ "typescript": "5.9.2",
+ "vitest": "^3.2.4",
+ "zod": "^3.25.76"
+ }
+}
diff --git a/packages/mcp-apps-renderer/src/__tests__/sandbox.test.ts b/packages/mcp-apps-renderer/src/__tests__/sandbox.test.ts
new file mode 100644
index 0000000000..51fb0f1a5a
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/__tests__/sandbox.test.ts
@@ -0,0 +1,77 @@
+import { describe, expect, it } from "vitest";
+import { LATEST_PROTOCOL_VERSION } from "@modelcontextprotocol/ext-apps";
+import { buildSandboxHTML } from "../sandbox";
+import {
+ MCP_OPEN_LINK_BLOCKED_SCHEMES,
+ MCPAppsActivityType,
+} from "../constants";
+// MCP_APPS_PROTOCOL_VERSION lives on the bridge side (session) so the bridge-free
+// `./constants` / `./activity` entry never pulls the ext-apps bundle.
+import { MCP_APPS_PROTOCOL_VERSION } from "../session";
+import { MCPAppsActivityContentSchema } from "../content-schema";
+
+describe("buildSandboxHTML", () => {
+ it("produces a sandbox proxy document that announces sandbox-proxy-ready", () => {
+ const html = buildSandboxHTML();
+ expect(html).toContain("");
+ expect(html).toContain("ui/notifications/sandbox-proxy-ready");
+ expect(html).toContain("Content-Security-Policy");
+ // relays the widget HTML on sandbox-resource-ready
+ expect(html).toContain("ui/notifications/sandbox-resource-ready");
+ });
+
+ it("appends extra CSP domains to script-src and frame-src", () => {
+ const html = buildSandboxHTML(["https://example.com"]);
+ expect(html).toContain("https://example.com");
+ });
+});
+
+describe("constants", () => {
+ it("exposes the mcp-apps activity type", () => {
+ expect(MCPAppsActivityType).toBe("mcp-apps");
+ });
+
+ it("sources the protocol version from ext-apps (no hand-maintained literal)", () => {
+ // MCP_APPS_PROTOCOL_VERSION is a re-export of the bridge's own
+ // LATEST_PROTOCOL_VERSION, so it can never drift from the spec version.
+ expect(MCP_APPS_PROTOCOL_VERSION).toBe(LATEST_PROTOCOL_VERSION);
+ });
+
+ it("negotiates the expected current protocol version (2026-01-26 canary)", () => {
+ // Canary: if ext-apps bumps the version, this fails so we review the change.
+ expect(MCP_APPS_PROTOCOL_VERSION).toBe("2026-01-26");
+ });
+
+ it("blocks script/HTML-executing schemes for ui/open-link", () => {
+ for (const scheme of [
+ "javascript:",
+ "data:",
+ "vbscript:",
+ "blob:",
+ "file:",
+ ]) {
+ expect(MCP_OPEN_LINK_BLOCKED_SCHEMES.has(scheme)).toBe(true);
+ }
+ expect(MCP_OPEN_LINK_BLOCKED_SCHEMES.has("https:")).toBe(false);
+ });
+});
+
+describe("content schema", () => {
+ it("validates a well-formed activity content", () => {
+ const parsed = MCPAppsActivityContentSchema.safeParse({
+ result: { content: [{ type: "text", text: "ok" }], isError: false },
+ resourceUri: "ui://server/dashboard",
+ serverHash: "abc123",
+ toolInput: { q: "hi" },
+ });
+ expect(parsed.success).toBe(true);
+ });
+
+ it("rejects content missing resourceUri", () => {
+ const parsed = MCPAppsActivityContentSchema.safeParse({
+ result: {},
+ serverHash: "abc123",
+ });
+ expect(parsed.success).toBe(false);
+ });
+});
diff --git a/packages/mcp-apps-renderer/src/__tests__/session.e2e.test.ts b/packages/mcp-apps-renderer/src/__tests__/session.e2e.test.ts
new file mode 100644
index 0000000000..67bd0dcacc
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/__tests__/session.e2e.test.ts
@@ -0,0 +1,358 @@
+import { afterEach, describe, expect, it, vi } from "vitest";
+import type { AbstractAgent } from "@ag-ui/client";
+import { bindMcpApp } from "../session";
+import type { McpAppSession } from "../session";
+import type { MCPAppsActivityContent } from "../content-schema";
+
+// ---------------------------------------------------------------------------
+// Minimal agent mock: only what bindMcpApp + the request queue touch.
+// ---------------------------------------------------------------------------
+function makeAgent(overrides?: Partial>) {
+ const addMessageCalls: Array<{ id: string; role: string; content: string }> =
+ [];
+ const runAgentCalls: Array = [];
+ const agent = {
+ agentId: "test-agent",
+ threadId: "thread-1",
+ isRunning: false,
+ addMessageCalls,
+ runAgentCalls,
+ addMessage(msg: { id: string; role: string; content: string }) {
+ addMessageCalls.push(msg);
+ },
+ subscribe() {
+ return { unsubscribe() {} };
+ },
+ async runAgent(input?: any) {
+ runAgentCalls.push(input);
+ const req = input?.forwardedProps?.__proxiedMCPRequest;
+ if (req?.method === "resources/read") {
+ return {
+ result: {
+ contents: [
+ {
+ uri: req.params?.uri,
+ mimeType: "text/html",
+ text: "Widget",
+ },
+ ],
+ },
+ newMessages: [],
+ };
+ }
+ if (req?.method === "tools/call") {
+ return {
+ result: {
+ content: [{ type: "text", text: "tool ok" }],
+ isError: false,
+ },
+ newMessages: [],
+ };
+ }
+ return { result: {}, newMessages: [] };
+ },
+ ...overrides,
+ };
+ return agent as unknown as AbstractAgent & {
+ addMessageCalls: typeof addMessageCalls;
+ runAgentCalls: typeof runAgentCalls;
+ };
+}
+
+function makeContent(
+ over?: Partial,
+): MCPAppsActivityContent {
+ return {
+ resourceUri: "ui://test/app",
+ serverHash: "hash-123",
+ result: { content: [], isError: false },
+ toolInput: {},
+ ...over,
+ } as MCPAppsActivityContent;
+}
+
+const tick = (ms = 30) => new Promise((r) => setTimeout(r, ms));
+
+/** Dispatch a JSON-RPC message from the iframe (source = its contentWindow). */
+function fromIframe(iframe: HTMLIFrameElement, data: unknown) {
+ window.dispatchEvent(
+ new MessageEvent("message", {
+ data,
+ source: iframe.contentWindow,
+ origin: "",
+ }),
+ );
+}
+
+/** Capture messages the host posts back to the iframe. */
+function captureOutgoing(iframe: HTMLIFrameElement) {
+ const captured: any[] = [];
+ const cw = iframe.contentWindow as Window;
+ const orig = cw.postMessage.bind(cw);
+ cw.postMessage = ((message: unknown, ...args: unknown[]) => {
+ captured.push(message);
+ return (orig as any)(message, ...args);
+ }) as typeof cw.postMessage;
+ return captured;
+}
+
+let sessions: McpAppSession[] = [];
+let iframes: HTMLIFrameElement[] = [];
+
+function mount() {
+ const iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ iframes.push(iframe);
+ return iframe;
+}
+
+/**
+ * Bind + wait for setup (resource fetch + connect) + simulate the sandbox proxy
+ * ready handshake, mirroring the react-core MCP e2e harness.
+ */
+async function bindAndConnect(
+ iframe: HTMLIFrameElement,
+ agent: AbstractAgent,
+ content = makeContent(),
+ hooks?: Parameters[0]["hooks"],
+) {
+ const session = bindMcpApp({
+ iframe,
+ getContent: () => content,
+ getAgent: () => agent,
+ host: { runAgent: async () => ({ result: undefined, newMessages: [] }) },
+ hooks,
+ });
+ sessions.push(session);
+ await tick(60); // let fetchResource + bridge.connect settle
+ const captured = captureOutgoing(iframe);
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ method: "ui/notifications/sandbox-proxy-ready",
+ });
+ await tick(30);
+ return { session, captured };
+}
+
+afterEach(() => {
+ sessions.forEach((s) => s.teardown());
+ sessions = [];
+ iframes.forEach((f) => f.remove());
+ iframes = [];
+ vi.restoreAllMocks();
+});
+
+describe("bindMcpApp", () => {
+ it("fetches the resource through the agent and loads the sandbox", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ await bindAndConnect(iframe, agent);
+
+ const readCall = agent.runAgentCalls.find(
+ (c) =>
+ c?.forwardedProps?.__proxiedMCPRequest?.method === "resources/read",
+ );
+ expect(readCall).toBeDefined();
+ expect(iframe.getAttribute("data-testid")).toBe("mcp-app-iframe");
+ expect(iframe.srcdoc).toContain("sandbox-proxy-ready");
+ });
+
+ it("proxies tools/call through the agent and returns the result to the iframe", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const { captured } = await bindAndConnect(iframe, agent);
+
+ const id = "call-1";
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id,
+ method: "tools/call",
+ params: { name: "do_thing", arguments: { a: 1 } },
+ });
+ await tick(40);
+
+ const toolCall = agent.runAgentCalls.find(
+ (c) => c?.forwardedProps?.__proxiedMCPRequest?.method === "tools/call",
+ );
+ expect(toolCall).toBeDefined();
+ const response = captured.find((m) => m && m.id === id && "result" in m);
+ expect(response?.result?.content?.[0]?.text).toBe("tool ok");
+ });
+
+ it("opens https links and blocks javascript: links (ui/open-link)", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const { captured } = await bindAndConnect(iframe, agent);
+ const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
+
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: "ok",
+ method: "ui/open-link",
+ params: { url: "https://example.com" },
+ });
+ await tick(20);
+ expect(openSpy).toHaveBeenCalledWith(
+ "https://example.com",
+ "_blank",
+ "noopener,noreferrer",
+ );
+
+ openSpy.mockClear();
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: "bad",
+ // eslint-disable-next-line no-script-url
+ method: "ui/open-link",
+ params: { url: "javascript:alert(1)" },
+ });
+ await tick(20);
+ expect(openSpy).not.toHaveBeenCalled();
+ const badResp = captured.find((m) => m && m.id === "bad" && "result" in m);
+ expect(badResp?.result).toMatchObject({ isError: true });
+ });
+
+ it("adds a ui/message to the agent (role from _meta.copilotkit)", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ await bindAndConnect(iframe, agent);
+
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: "msg-1",
+ method: "ui/message",
+ params: {
+ content: [{ type: "text", text: "hello from widget" }],
+ _meta: { copilotkit: { role: "assistant", followUp: false } },
+ },
+ });
+ await tick(30);
+
+ const call = agent.addMessageCalls.find(
+ (c) => c.content === "hello from widget",
+ );
+ expect(call).toBeDefined();
+ expect(call?.role).toBe("assistant");
+ });
+
+ it("fires onInitialized when the widget reports initialized", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const onInitialized = vi.fn();
+ const { session } = await bindAndConnect(iframe, agent, makeContent(), {
+ onInitialized,
+ });
+
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ method: "ui/notifications/initialized",
+ });
+ await tick(20);
+ expect(onInitialized).toHaveBeenCalled();
+
+ // tool input pushed after initialize reaches the iframe
+ session.sendToolInput({ a: 1 });
+ await tick(10);
+ });
+});
+
+// ---------------------------------------------------------------------------
+// ui/initialize is handled entirely by the ext-apps AppBridge that bindMcpApp
+// constructs. These tests pin the negotiation contract at the package level (the
+// compile-time tie to the spec the extraction argues for), because the host
+// setup lives here now:
+// - the bridge validates params against the spec schema, so a widget that omits
+// the required fields (e.g. appCapabilities) fails initialize with -32603;
+// - the host advertises only the latest MCP Apps protocol version, so a widget
+// declaring a different version string gets the host version back;
+// - the host context seeded at AppBridge construction is advertised at
+// initialize (deterministic, not a post-connect race).
+// ---------------------------------------------------------------------------
+describe("bindMcpApp ui/initialize negotiation", () => {
+ const LATEST_PROTOCOL_VERSION = "2026-01-26";
+
+ it("negotiates and returns the host context for a well-formed initialize", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const { captured } = await bindAndConnect(iframe, agent);
+
+ const reqId = "init-ok";
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: reqId,
+ method: "ui/initialize",
+ params: {
+ appInfo: { name: "test-widget", version: "1.0.0" },
+ appCapabilities: {},
+ protocolVersion: LATEST_PROTOCOL_VERSION,
+ },
+ });
+ await tick(30);
+
+ const response = captured.find(
+ (m) => m && m.jsonrpc === "2.0" && m.id === reqId && m.result,
+ );
+ expect(response).toBeDefined();
+ expect(response).not.toHaveProperty("error");
+ // Protocol version is negotiated to the host's latest.
+ expect(response.result.protocolVersion).toBe(LATEST_PROTOCOL_VERSION);
+ // Host context seeded at construction is advertised at initialize.
+ expect(response.result.hostContext).toMatchObject({
+ theme: "light",
+ platform: "web",
+ });
+ });
+
+ it("rejects an initialize that omits required fields with -32603", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const { captured } = await bindAndConnect(iframe, agent);
+
+ // Empty params: no appInfo / appCapabilities / protocolVersion. The bridge
+ // validates against the spec schema and rejects before any host handler.
+ const reqId = "init-bad";
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: reqId,
+ method: "ui/initialize",
+ params: {},
+ });
+ await tick(30);
+
+ const errorResponse = captured.find(
+ (m) => m && m.jsonrpc === "2.0" && m.id === reqId && m.error,
+ );
+ expect(errorResponse).toBeDefined();
+ expect(errorResponse.error.code).toBe(-32603);
+ expect(typeof errorResponse.error.message).toBe("string");
+ expect(errorResponse.error.message.length).toBeGreaterThan(0);
+ });
+
+ it("returns the host protocol version, not the widget's, when they differ", async () => {
+ const agent = makeAgent();
+ const iframe = mount();
+ const { captured } = await bindAndConnect(iframe, agent);
+
+ // "2025-06-18" is a base-MCP-protocol version (and what the old hand-rolled
+ // Vue/Angular hosts hardcode). The bridge supports only its own MCP Apps
+ // version and returns that, rather than echoing the widget's.
+ const reqId = "init-version";
+ fromIframe(iframe, {
+ jsonrpc: "2.0",
+ id: reqId,
+ method: "ui/initialize",
+ params: {
+ appInfo: { name: "legacy-widget", version: "1.0.0" },
+ appCapabilities: {},
+ protocolVersion: "2025-06-18",
+ },
+ });
+ await tick(30);
+
+ const response = captured.find(
+ (m) => m && m.jsonrpc === "2.0" && m.id === reqId && m.result,
+ );
+ expect(response).toBeDefined();
+ expect(response.result.protocolVersion).toBe(LATEST_PROTOCOL_VERSION);
+ });
+});
diff --git a/packages/mcp-apps-renderer/src/activity.ts b/packages/mcp-apps-renderer/src/activity.ts
new file mode 100644
index 0000000000..307e565538
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/activity.ts
@@ -0,0 +1,11 @@
+// Lightweight, bridge-free surface for MCP Apps activity registration.
+//
+// This entry re-exports ONLY the pieces that have no dependency on the ext-apps
+// AppBridge (the ~40-50 kB gzipped MCP SDK + zod protocol bundle): the activity
+// type + content schema (for the host's activity registry) and the ui/message
+// follow-up runner. Frontends import these statically to register the MCP-apps
+// activity, then load `bindMcpApp` from the package root (`.`) lazily via a
+// dynamic import so a non-MCP app never pays for the bridge.
+export * from "./constants";
+export * from "./content-schema";
+export * from "./follow-up";
diff --git a/packages/mcp-apps-renderer/src/constants.ts b/packages/mcp-apps-renderer/src/constants.ts
new file mode 100644
index 0000000000..88c912381e
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/constants.ts
@@ -0,0 +1,26 @@
+/**
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
+ */
+export const MCPAppsActivityType = "mcp-apps";
+
+/**
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
+ *
+ * We use a denylist rather than an allowlist on purpose: deep links use
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
+ * just hands off to an OS handler - it does not execute script in the page, so
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
+ * that execute script or render attacker HTML in the page context; block those
+ * and allow everything else (including deep links).
+ */
+export const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
+ "javascript:",
+ "data:",
+ "vbscript:",
+ "blob:",
+ "file:",
+]);
diff --git a/packages/mcp-apps-renderer/src/content-schema.ts b/packages/mcp-apps-renderer/src/content-schema.ts
new file mode 100644
index 0000000000..b1471726f1
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/content-schema.ts
@@ -0,0 +1,26 @@
+import { z } from "zod";
+
+/**
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
+ * framework activity registries validate the activity content with this before
+ * handing it to the renderer/session.
+ */
+export const MCPAppsActivityContentSchema = z.object({
+ result: z.object({
+ content: z.array(z.any()).optional(),
+ structuredContent: z.any().optional(),
+ isError: z.boolean().optional(),
+ }),
+ // Resource URI to fetch (e.g., "ui://server/dashboard")
+ resourceUri: z.string(),
+ // MD5 hash of server config (renamed from serverId in 0.0.1)
+ serverHash: z.string(),
+ // Optional stable server ID from config (takes precedence over serverHash)
+ serverId: z.string().optional(),
+ // Original tool input arguments
+ toolInput: z.record(z.string(), z.unknown()).optional(),
+});
+
+export type MCPAppsActivityContent = z.infer<
+ typeof MCPAppsActivityContentSchema
+>;
diff --git a/packages/mcp-apps-renderer/src/follow-up.ts b/packages/mcp-apps-renderer/src/follow-up.ts
new file mode 100644
index 0000000000..22a6625e3b
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/follow-up.ts
@@ -0,0 +1,51 @@
+import type { AbstractAgent, RunAgentResult } from "@ag-ui/client";
+
+/**
+ * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.
+ * Declared structurally so the runner can be unit-tested without a full core.
+ */
+export interface ɵMcpFollowUpHost {
+ runAgent(params: { agent: AbstractAgent }): Promise;
+}
+
+/**
+ * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
+ * for (issue #5819).
+ *
+ * The MCP request queue delays follow-up work until the agent is idle. There is
+ * a single shared registry agent per id, and switching threads overwrites its
+ * `threadId`/`messages` in place. So if the host switches threads while a
+ * follow-up is queued, running it now would execute against — and stream into —
+ * the now-foreground thread.
+ *
+ * - **Same thread** (the common case): run on the shared agent, unchanged.
+ * - **Thread changed**: the shared agent has moved on, so the follow-up can no
+ * longer run in its originating thread's context. Drop it rather than leak it
+ * into the current thread. (The MCP app already received its `ui/message` ack
+ * at enqueue time; only the optional agent turn is skipped.)
+ *
+ * @internal exported for testing.
+ */
+export async function ɵrunMcpFollowUp({
+ host,
+ agent,
+ capturedThreadId,
+}: {
+ host: ɵMcpFollowUpHost;
+ agent: AbstractAgent;
+ capturedThreadId: string;
+}): Promise {
+ const currentThreadId = agent.threadId || "default";
+ const originThreadId = capturedThreadId || "default";
+
+ if (currentThreadId === originThreadId) {
+ return host.runAgent({ agent });
+ }
+
+ console.warn(
+ "[MCPAppsRenderer] ui/message follow-up dropped: the thread changed " +
+ `(${originThreadId} → ${currentThreadId}) between enqueue and execution, ` +
+ "so running it would leak into the now-foreground thread.",
+ );
+ return { result: undefined, newMessages: [] };
+}
diff --git a/packages/mcp-apps-renderer/src/index.ts b/packages/mcp-apps-renderer/src/index.ts
new file mode 100644
index 0000000000..5016520c20
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/index.ts
@@ -0,0 +1,14 @@
+// @copilotkit/mcp-apps-renderer - framework-agnostic MCP Apps host.
+//
+// This package owns the app<->host protocol (ext-apps AppBridge), the sandbox
+// proxy, the per-thread request queue, ui/message extensions, and the shared
+// content schema. The React/Vue/Angular renderers consume it as thin adapters
+// (they only mount the iframe and wire reactive state); ext-apps + the MCP SDK
+// are declared here and nowhere else.
+
+export * from "./constants";
+export * from "./content-schema";
+export * from "./sandbox";
+export * from "./request-queue";
+export * from "./follow-up";
+export * from "./session";
diff --git a/packages/mcp-apps-renderer/src/request-queue.ts b/packages/mcp-apps-renderer/src/request-queue.ts
new file mode 100644
index 0000000000..806e2183eb
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/request-queue.ts
@@ -0,0 +1,131 @@
+import type { AbstractAgent, RunAgentResult } from "@ag-ui/client";
+
+/**
+ * Queue for serializing MCP app requests to an agent.
+ * Ensures requests wait for the agent to stop running and are processed one at a time.
+ */
+export class MCPAppsRequestQueue {
+ private queues = new Map<
+ string,
+ Array<{
+ execute: () => Promise;
+ resolve: (result: RunAgentResult) => void;
+ reject: (error: Error) => void;
+ }>
+ >();
+ private processing = new Map();
+
+ /**
+ * Add a request to the queue for a specific agent thread.
+ * Returns a promise that resolves when the request completes.
+ */
+ async enqueue(
+ agent: AbstractAgent,
+ request: () => Promise,
+ ): Promise {
+ const threadId = agent.threadId || "default";
+
+ return new Promise((resolve, reject) => {
+ // Get or create queue for this thread
+ let queue = this.queues.get(threadId);
+ if (!queue) {
+ queue = [];
+ this.queues.set(threadId, queue);
+ }
+
+ // Add request to queue
+ queue.push({ execute: request, resolve, reject });
+
+ // Start processing if not already running
+ this.processQueue(threadId, agent);
+ });
+ }
+
+ /**
+ * Drain a thread's queue one request at a time, waiting for the agent to go
+ * idle before each. Re-entrant-safe (a single processor per thread) and drops
+ * the thread's map entries once fully drained to keep the shared queue bounded.
+ */
+ private async processQueue(
+ threadId: string,
+ agent: AbstractAgent,
+ ): Promise {
+ // If already processing this queue, return
+ if (this.processing.get(threadId)) {
+ return;
+ }
+
+ this.processing.set(threadId, true);
+
+ try {
+ const queue = this.queues.get(threadId);
+ if (!queue) return;
+
+ while (queue.length > 0) {
+ const item = queue[0]!;
+
+ try {
+ // Wait for any active run to complete before processing
+ await this.waitForAgentIdle(agent);
+
+ // Execute the request
+ const result = await item.execute();
+ item.resolve(result);
+ } catch (error) {
+ item.reject(
+ error instanceof Error ? error : new Error(String(error)),
+ );
+ }
+
+ // Remove processed item
+ queue.shift();
+ }
+ } finally {
+ // Drop the drained thread entries from both maps. `mcpAppsRequestQueue` is
+ // shared for the page lifetime, so retaining an entry per thread id would
+ // grow unbounded as threads come and go.
+ const queue = this.queues.get(threadId);
+ if (!queue || queue.length === 0) {
+ this.queues.delete(threadId);
+ this.processing.delete(threadId);
+ } else {
+ this.processing.set(threadId, false);
+ }
+ }
+ }
+
+ /**
+ * Resolve once the agent is not running. Subscribes to run-finalized/failed and
+ * also polls as a fallback for reconnect scenarios where events do not fire.
+ */
+ private waitForAgentIdle(agent: AbstractAgent): Promise {
+ return new Promise((resolve) => {
+ if (!agent.isRunning) {
+ resolve();
+ return;
+ }
+
+ let done = false;
+ const finish = () => {
+ if (done) return;
+ done = true;
+ clearInterval(checkInterval);
+ sub.unsubscribe();
+ resolve();
+ };
+
+ const sub = agent.subscribe({
+ onRunFinalized: finish,
+ onRunFailed: finish,
+ });
+
+ // Fallback for reconnect scenarios where events don't fire
+ const checkInterval = setInterval(() => {
+ if (!agent.isRunning) finish();
+ }, 500);
+ });
+ }
+}
+
+// Shared per-thread queue instance for all MCP app requests.
+export const mcpAppsRequestQueue = new MCPAppsRequestQueue();
diff --git a/packages/mcp-apps-renderer/src/sandbox.ts b/packages/mcp-apps-renderer/src/sandbox.ts
new file mode 100644
index 0000000000..19d492cc04
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/sandbox.ts
@@ -0,0 +1,51 @@
+/**
+ * Build the sandbox-proxy HTML document loaded into the outer iframe.
+ *
+ * The proxy relays postMessage between the host and the inner sandboxed widget
+ * and announces `ui/notifications/sandbox-proxy-ready` once ready. `extraCspDomains`
+ * (from the resource's `_meta.ui.csp`) are appended to the `script-src`/`frame-src`
+ * CSP directives so a widget can load its own approved origins.
+ *
+ * @param extraCspDomains Optional additional origins allowed by the sandbox CSP.
+ * @returns The complete sandbox-proxy HTML document as a string.
+ */
+export function buildSandboxHTML(extraCspDomains?: string[]): string {
+ const baseScriptSrc =
+ "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
+ const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
+ const extra = extraCspDomains?.length ? " " + extraCspDomains.join(" ") : "";
+ const scriptSrc = baseScriptSrc + extra;
+ const frameSrc = baseFrameSrc + extra;
+
+ return `
+
+
+
+
+
+
+
+
+
+`;
+}
diff --git a/packages/mcp-apps-renderer/src/session.ts b/packages/mcp-apps-renderer/src/session.ts
new file mode 100644
index 0000000000..7254fec9c5
--- /dev/null
+++ b/packages/mcp-apps-renderer/src/session.ts
@@ -0,0 +1,382 @@
+import {
+ AppBridge,
+ LATEST_PROTOCOL_VERSION,
+ PostMessageTransport,
+} from "@modelcontextprotocol/ext-apps/app-bridge";
+import type { AbstractAgent } from "@ag-ui/client";
+import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import { z } from "zod";
+import { randomUUID } from "@copilotkit/shared";
+import { buildSandboxHTML } from "./sandbox";
+import { mcpAppsRequestQueue } from "./request-queue";
+import { ɵrunMcpFollowUp } from "./follow-up";
+import type { ɵMcpFollowUpHost } from "./follow-up";
+import { MCP_OPEN_LINK_BLOCKED_SCHEMES } from "./constants";
+import type { MCPAppsActivityContent } from "./content-schema";
+
+/**
+ * The MCP Apps protocol version this host negotiates. Sourced directly from the
+ * ext-apps bridge (single source of truth, no hand-maintained literal). It lives
+ * here (a bridge-side module) rather than in the bridge-free `./constants` /
+ * `./activity` entry so the lightweight activity-registration surface stays free
+ * of the ext-apps bundle; consumers that need the version import it from the
+ * package root, which already loads the bridge.
+ */
+export const MCP_APPS_PROTOCOL_VERSION = LATEST_PROTOCOL_VERSION;
+
+/**
+ * Permissive `ui/message` schema. ext-apps restricts the request to
+ * `role: "user"` with no `followUp`, but CopilotKit intentionally extends
+ * `ui/message` with `role` ("user" | "assistant") and `followUp` (documented
+ * behavior with dedicated tests). We register our own handler (instead of the
+ * bridge's strict `onmessage`) so those extensions survive.
+ *
+ * Going forward, widgets SHOULD pass the extensions under
+ * `params._meta.copilotkit`; the top-level `role`/`followUp` fields are the
+ * legacy channel, kept for backward compatibility and slated for deprecation.
+ */
+const CopilotKitUiMessageSchema = z.object({
+ method: z.literal("ui/message"),
+ params: z
+ .object({
+ role: z.string().optional(),
+ content: z.array(z.any()).optional(),
+ followUp: z.boolean().optional(),
+ _meta: z.record(z.string(), z.any()).optional(),
+ })
+ .passthrough(),
+});
+
+/** A resource fetched from the MCP server via the agent proxy. */
+export interface FetchedResource {
+ uri: string;
+ mimeType?: string;
+ text?: string;
+ blob?: string;
+ _meta?: {
+ ui?: {
+ prefersBorder?: boolean;
+ csp?: {
+ connectDomains?: string[];
+ resourceDomains?: string[];
+ };
+ };
+ };
+}
+
+/** Reactive callbacks the framework adapter wires to its own state. */
+export interface McpAppSessionHooks {
+ /** The widget reported a new content size (ui/notifications/size-changed). */
+ onSizeChanged?(size: { width?: number; height?: number }): void;
+ /** The widget finished initializing (safe to push tool input/result). */
+ onInitialized?(): void;
+ /** The fetched resource metadata (e.g. prefersBorder) is available. */
+ onResource?(resource: FetchedResource): void;
+ /** Setup failed (resource fetch, connect, ...). */
+ onError?(err: Error): void;
+}
+
+export interface BindMcpAppOptions {
+ /**
+ * The sandbox iframe. The adapter creates and OWNS this element (mounts it in
+ * its render model, sizes it, removes it on unmount). The session only
+ * configures the sandbox contract (sandbox attr, testid, srcdoc) and talks to
+ * it through the bridge - it never creates, moves, or removes the iframe.
+ */
+ iframe: HTMLIFrameElement;
+ /** Returns the current activity content (resourceUri, serverHash, tool input/result). */
+ getContent: () => MCPAppsActivityContent;
+ /** Returns the current agent (may change across renders). */
+ getAgent: () => AbstractAgent | undefined;
+ /** CopilotKit host, for ui/message follow-up runs (issue #5819). */
+ host: ɵMcpFollowUpHost;
+ hooks?: McpAppSessionHooks;
+}
+
+export interface McpAppSession {
+ /** Forward the tool call input to the widget (host -> app). Buffered until ready. */
+ sendToolInput(args: Record): void;
+ /** Forward the tool result to the widget (host -> app). Buffered until ready. */
+ sendToolResult(result: CallToolResult): void;
+ /** Disconnect the bridge and release listeners. Does NOT remove the iframe. */
+ teardown(): void;
+}
+
+/**
+ * Bind an MCP App to a host-provided sandbox iframe: fetch the widget resource
+ * through the agent, connect the ext-apps `AppBridge` over a PostMessage
+ * transport, and wire the app<->host protocol (ui/message, ui/open-link,
+ * tools/call + resources/read proxy, size, host context). Framework-agnostic:
+ * the React/Vue/Angular renderers create the iframe and wire reactive state via
+ * `hooks`, but all protocol logic lives here.
+ */
+export function bindMcpApp(opts: BindMcpAppOptions): McpAppSession {
+ const { iframe, getContent, getAgent, host, hooks } = opts;
+
+ let disposed = false;
+ let ready = false;
+ let bridge: AppBridge | null = null;
+ let pendingToolInput: Record | undefined;
+ let pendingToolResult: CallToolResult | undefined;
+
+ /** Flush any buffered tool input/result to the widget once it is initialized. */
+ const flushPending = () => {
+ if (!ready || !bridge) return;
+ if (pendingToolInput !== undefined) {
+ void bridge.sendToolInput({ arguments: pendingToolInput });
+ pendingToolInput = undefined;
+ }
+ if (pendingToolResult !== undefined) {
+ void bridge.sendToolResult(pendingToolResult);
+ pendingToolResult = undefined;
+ }
+ };
+
+ /** Fetch the widget resource (`resources/read`) through the agent proxy queue. */
+ const fetchResource = async (): Promise => {
+ const agent = getAgent();
+ if (!agent) {
+ throw new Error("No agent available to fetch resource");
+ }
+ const { resourceUri, serverHash, serverId } = getContent();
+ const runResult = await mcpAppsRequestQueue.enqueue(agent, () =>
+ agent.runAgent({
+ forwardedProps: {
+ __proxiedMCPRequest: {
+ serverHash,
+ serverId,
+ method: "resources/read",
+ params: { uri: resourceUri },
+ },
+ },
+ }),
+ );
+ const resultData = runResult.result as
+ | { contents?: FetchedResource[] }
+ | undefined;
+ const resource = resultData?.contents?.[0];
+ if (!resource) {
+ throw new Error("No resource content in response");
+ }
+ return resource;
+ };
+
+ /**
+ * Fetch the resource, configure + load the sandbox iframe, construct the
+ * AppBridge, wire the app->host handlers, and connect the transport.
+ */
+ const setup = async () => {
+ try {
+ const resource = await fetchResource();
+ if (disposed) return;
+ hooks?.onResource?.(resource);
+
+ // Configure the sandbox iframe (contract shared across frontends).
+ iframe.setAttribute(
+ "sandbox",
+ "allow-scripts allow-same-origin allow-forms",
+ );
+ // Cross-frontend MCP-apps surface contract: every frontend must expose the
+ // sandbox iframe under the SAME testid so one shared probe (harness
+ // `d5-mcp-apps`) and one shared e2e spec can assert the surface mounted
+ // without per-frontend selectors.
+ iframe.setAttribute("data-testid", "mcp-app-iframe");
+ iframe.setAttribute("title", "Interactive MCP application");
+
+ const cspDomains = resource._meta?.ui?.csp?.resourceDomains;
+ iframe.srcdoc = buildSandboxHTML(cspDomains);
+
+ const win = iframe.contentWindow;
+ if (!win) {
+ throw new Error("Sandbox iframe has no contentWindow");
+ }
+
+ let html: string;
+ if (resource.text) {
+ html = resource.text;
+ } else if (resource.blob) {
+ html = atob(resource.blob);
+ } else {
+ throw new Error("Resource has no text or blob content");
+ }
+
+ bridge = new AppBridge(
+ null,
+ { name: "CopilotKit MCP Apps Host", version: "1.0.0" },
+ { openLinks: {}, logging: {}, message: { text: {} } },
+ // Seed the host context at construction so it is already in place when
+ // the widget's ui/initialize is handled (deterministic, not a race).
+ { hostContext: { theme: "light", platform: "web" } },
+ );
+
+ // Sandbox handshake: on proxy ready, load the widget HTML into the inner
+ // sandboxed iframe.
+ bridge.onsandboxready = () => {
+ void bridge?.sendSandboxResourceReady({ html });
+ };
+
+ // --- App -> host requests ---
+ // ui/message: custom handler preserving CopilotKit role/followUp extensions
+ // (via _meta.copilotkit first, then legacy top-level fields).
+ bridge.setRequestHandler(CopilotKitUiMessageSchema, async (req) => {
+ const currentAgent = getAgent();
+ if (!currentAgent) {
+ console.warn("[MCPAppsRenderer] ui/message: No agent available");
+ return { isError: false };
+ }
+ try {
+ const params = req.params;
+ const ck = (params._meta?.copilotkit ?? {}) as {
+ role?: string;
+ followUp?: boolean;
+ };
+ const role =
+ (ck.role as "user" | "assistant") ||
+ (params.role as "user" | "assistant") ||
+ "user";
+ const textContent =
+ (
+ params.content as
+ | Array<{ type: string; text?: string }>
+ | undefined
+ )
+ ?.filter((c) => c.type === "text" && c.text)
+ .map((c) => c.text)
+ .join("\n") || "";
+ if (textContent) {
+ currentAgent.addMessage({
+ id: randomUUID(),
+ role,
+ content: textContent,
+ });
+ }
+ const followUp = ck.followUp ?? params.followUp;
+ const shouldFollowUp = followUp ?? role === "user";
+ if (shouldFollowUp && textContent) {
+ const capturedThreadId = currentAgent.threadId || "default";
+ mcpAppsRequestQueue
+ .enqueue(currentAgent, () =>
+ ɵrunMcpFollowUp({
+ host,
+ agent: currentAgent,
+ capturedThreadId,
+ }),
+ )
+ .catch((err) =>
+ console.error(
+ "[MCPAppsRenderer] ui/message agent run failed:",
+ err,
+ ),
+ );
+ }
+ return { isError: false };
+ } catch (err) {
+ console.error("[MCPAppsRenderer] ui/message error:", err);
+ return { isError: true };
+ }
+ });
+
+ bridge.onopenlink = async ({ url }) => {
+ // The bridge validates `url` as a string but not the scheme. Block only
+ // the script-executing / attacker-HTML schemes; everything else
+ // (https universal links, custom-scheme deep links) is allowed.
+ let parsed: URL;
+ try {
+ parsed = new URL(url);
+ } catch {
+ console.warn(
+ "[MCPAppsRenderer] ui/open-link rejected: unparseable url",
+ );
+ return { isError: true };
+ }
+ if (MCP_OPEN_LINK_BLOCKED_SCHEMES.has(parsed.protocol)) {
+ console.warn(
+ "[MCPAppsRenderer] ui/open-link rejected: blocked scheme",
+ parsed.protocol,
+ );
+ return { isError: true };
+ }
+ window.open(url, "_blank", "noopener,noreferrer");
+ return { isError: false };
+ };
+
+ bridge.oncalltool = async (params) => {
+ const { serverHash, serverId } = getContent();
+ const currentAgent = getAgent();
+ if (!serverHash) {
+ throw new Error("No server hash available for proxying");
+ }
+ if (!currentAgent) {
+ throw new Error("No agent available for proxying");
+ }
+ const runResult = await mcpAppsRequestQueue.enqueue(currentAgent, () =>
+ currentAgent.runAgent({
+ forwardedProps: {
+ __proxiedMCPRequest: {
+ serverHash,
+ serverId,
+ method: "tools/call",
+ params,
+ },
+ },
+ }),
+ );
+ return (runResult.result as CallToolResult) || { content: [] };
+ };
+
+ // --- App -> host notifications ---
+ bridge.onsizechange = (p) => {
+ if (disposed) return;
+ const { width, height } = (p || {}) as {
+ width?: number;
+ height?: number;
+ };
+ hooks?.onSizeChanged?.({
+ width: typeof width === "number" ? width : undefined,
+ height: typeof height === "number" ? height : undefined,
+ });
+ };
+ bridge.oninitialized = () => {
+ if (disposed) return;
+ ready = true;
+ hooks?.onInitialized?.();
+ flushPending();
+ };
+ bridge.onloggingmessage = (p) => {
+ console.log("[MCPAppsRenderer] App log:", p);
+ };
+
+ const transport = new PostMessageTransport(win, win);
+ await bridge.connect(transport);
+ if (disposed) {
+ await bridge.close();
+ bridge = null;
+ return;
+ }
+ } catch (err) {
+ console.error("[MCPAppsRenderer] Setup error:", err);
+ if (!disposed) {
+ hooks?.onError?.(err instanceof Error ? err : new Error(String(err)));
+ }
+ }
+ };
+
+ void setup();
+
+ return {
+ sendToolInput(args) {
+ pendingToolInput = args;
+ flushPending();
+ },
+ sendToolResult(result) {
+ pendingToolResult = result;
+ flushPending();
+ },
+ teardown() {
+ disposed = true;
+ const b = bridge;
+ bridge = null;
+ void b?.close();
+ },
+ };
+}
diff --git a/packages/mcp-apps-renderer/tsconfig.json b/packages/mcp-apps-renderer/tsconfig.json
new file mode 100644
index 0000000000..67fe5a5ca6
--- /dev/null
+++ b/packages/mcp-apps-renderer/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "composite": false,
+ "declaration": true,
+ "declarationMap": true,
+ "incremental": true,
+ "forceConsistentCasingInFileNames": true,
+ "inlineSources": false,
+ "preserveWatchOutput": true,
+ "sourceMap": true,
+ "target": "es2022",
+ "module": "esnext",
+ "lib": ["es2023", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+ "useDefineForClassFields": false,
+ "rootDir": "src",
+ "outDir": "dist",
+ "tsBuildInfoFile": "dist/.tsbuildinfo",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "strict": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "types": ["vitest/globals"]
+ },
+ "include": ["src/**/*.ts"]
+}
diff --git a/packages/mcp-apps-renderer/tsdown.config.ts b/packages/mcp-apps-renderer/tsdown.config.ts
new file mode 100644
index 0000000000..5d4008ccc0
--- /dev/null
+++ b/packages/mcp-apps-renderer/tsdown.config.ts
@@ -0,0 +1,69 @@
+import { defineConfig } from "tsdown";
+
+const externalPkgs = [
+ "@modelcontextprotocol/ext-apps",
+ "@modelcontextprotocol/sdk",
+ "@ag-ui/client",
+ "@copilotkit/shared",
+ "zod",
+];
+
+const isExternal = (id: string) =>
+ externalPkgs.some((pkg) => id === pkg || id.startsWith(pkg + "/"));
+
+export default defineConfig([
+ // Root entry: ESM only. It re-exports the session, which imports the ext-apps
+ // AppBridge - and ext-apps 1.7.5 is ESM-only. A CJS root would emit a
+ // `require()` of that ESM module and fail with ERR_REQUIRE_ESM, so we do not
+ // advertise a CJS root. Consumers load the bridge via a dynamic `import()`
+ // (react-core does), which resolves ESM from any context.
+ {
+ entry: ["src/index.ts"],
+ format: ["esm"],
+ dts: true,
+ sourcemap: true,
+ target: "es2022",
+ outDir: "dist",
+ unbundle: true,
+ external: isExternal,
+ exports: false,
+ },
+ // Activity entry: the bridge-free registration surface (activity type, content
+ // schema, follow-up runner). It has no ext-apps edge, so it is safe as dual
+ // ESM + CJS - frontends register the activity synchronously from either module
+ // system without pulling the bridge.
+ {
+ entry: ["src/activity.ts"],
+ format: ["esm", "cjs"],
+ dts: true,
+ sourcemap: true,
+ target: "es2022",
+ outDir: "dist",
+ unbundle: true,
+ external: isExternal,
+ exports: false,
+ },
+ // Activity UMD: a self-contained global for script-tag consumers of
+ // @copilotkit/react-core's UMD build, which externalizes this entry and maps
+ // it to `CopilotKitMcpAppsRendererActivity`. Bridge-free, so only zod is
+ // external (mapped to the shared `Zod` global, matching react-core's UMD).
+ {
+ entry: ["src/activity.ts"],
+ format: ["umd"],
+ globalName: "CopilotKitMcpAppsRendererActivity",
+ sourcemap: true,
+ // es2018 for the script-tag UMD (broad browser reach), matching a2ui-renderer.
+ target: "es2018",
+ outDir: "dist",
+ external: (id: string) => id === "zod" || id.startsWith("zod/"),
+ // Force a single self-contained bundle (matches a2ui-renderer): without this,
+ // a sibling chunk emitted next to activity.umd.js would leave the global
+ // incomplete, and es-check (syntax-only) would not catch it.
+ codeSplitting: false,
+ outputOptions(options) {
+ options.entryFileNames = "[name].umd.js";
+ options.globals = { zod: "Zod" };
+ return options;
+ },
+ },
+]);
diff --git a/packages/mcp-apps-renderer/vitest.config.mjs b/packages/mcp-apps-renderer/vitest.config.mjs
new file mode 100644
index 0000000000..9f49708495
--- /dev/null
+++ b/packages/mcp-apps-renderer/vitest.config.mjs
@@ -0,0 +1,15 @@
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ test: {
+ environment: "jsdom",
+ include: ["**/__tests__/**/*.{test,spec}.ts"],
+ passWithNoTests: true,
+ globals: true,
+ server: {
+ deps: {
+ inline: ["@modelcontextprotocol/ext-apps", "zod"],
+ },
+ },
+ },
+});
diff --git a/packages/react-core/package.json b/packages/react-core/package.json
index 754149dc6c..d5831d9801 100644
--- a/packages/react-core/package.json
+++ b/packages/react-core/package.json
@@ -78,12 +78,12 @@
"@ag-ui/core": "0.0.59",
"@copilotkit/a2ui-renderer": "workspace:*",
"@copilotkit/core": "workspace:*",
+ "@copilotkit/mcp-apps-renderer": "workspace:*",
"@copilotkit/runtime-client-gql": "workspace:*",
"@copilotkit/shared": "workspace:*",
"@copilotkit/web-components": "workspace:*",
"@copilotkit/web-inspector": "workspace:*",
"@jetbrains/websandbox": "^1.1.3",
- "@modelcontextprotocol/ext-apps": "^1.7.5",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.7",
@@ -108,7 +108,6 @@
"esbuild": "^0.27.0",
"@tailwindcss/postcss": "^4.1.11",
"@tailwindcss/typography": "^0.5.16",
- "@modelcontextprotocol/sdk": "^1.29.0",
"@tanstack/intent": "^0.0.29",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^16.3.0",
@@ -135,7 +134,6 @@
"zod": ">=3.0.0"
},
"peerDependencies": {
- "@modelcontextprotocol/sdk": "^1.29.0",
"react": "^18 || ^19 || ^19.0.0-rc",
"react-dom": "^18 || ^19 || ^19.0.0-rc",
"zod": ">=3.25"
diff --git a/packages/react-core/src/v2/components/MCPAppsActivityRenderer.tsx b/packages/react-core/src/v2/components/MCPAppsActivityRenderer.tsx
index 2b6b9f44df..f603344974 100644
--- a/packages/react-core/src/v2/components/MCPAppsActivityRenderer.tsx
+++ b/packages/react-core/src/v2/components/MCPAppsActivityRenderer.tsx
@@ -1,282 +1,38 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
-import { z } from "zod";
-import type { AbstractAgent, RunAgentResult } from "@ag-ui/client";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
-// Type-only import: the ext-apps bridge is a heavy dependency (it pulls the MCP
-// SDK Protocol + zod schemas, ~40-50 kB gzipped). It is loaded lazily via a
-// dynamic import() inside Effect 1 so that a `` app only pays for it
-// when it actually renders an MCP App, not on every mount.
-import type { AppBridge } from "@modelcontextprotocol/ext-apps/app-bridge";
+import type { AbstractAgent } from "@ag-ui/client";
import { useCopilotKit } from "../providers/CopilotKitProvider";
-/**
- * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.
- * Declared structurally so the runner can be unit-tested without a full core.
- */
-export interface ɵMcpFollowUpHost {
- runAgent(params: { agent: AbstractAgent }): Promise;
-}
-
-/**
- * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
- * for (issue #5819).
- *
- * The MCP request queue delays follow-up work until the agent is idle. There is
- * a single shared registry agent per id, and switching threads overwrites its
- * `threadId`/`messages` in place. So if the host switches threads while a
- * follow-up is queued, running it now would execute against — and stream into —
- * the now-foreground thread.
- *
- * - **Same thread** (the common case): run on the shared agent, unchanged.
- * - **Thread changed**: the shared agent has moved on, so the follow-up can no
- * longer run in its originating thread's context. Drop it rather than leak it
- * into the current thread. (The MCP app already received its `ui/message` ack
- * at enqueue time; only the optional agent turn is skipped.)
- *
- * @internal exported for testing.
- */
-export async function ɵrunMcpFollowUp({
- host,
- agent,
- capturedThreadId,
-}: {
- host: ɵMcpFollowUpHost;
- agent: AbstractAgent;
- capturedThreadId: string;
-}): Promise {
- const currentThreadId = agent.threadId || "default";
- const originThreadId = capturedThreadId || "default";
-
- if (currentThreadId === originThreadId) {
- return host.runAgent({ agent });
- }
-
- console.warn(
- "[MCPAppsRenderer] ui/message follow-up dropped: the thread changed " +
- `(${originThreadId} → ${currentThreadId}) between enqueue and execution, ` +
- "so running it would leak into the now-foreground thread.",
- );
- return { result: undefined, newMessages: [] };
-}
-
-// Build sandbox proxy HTML with optional extra CSP domains from resource metadata
-function buildSandboxHTML(extraCspDomains?: string[]): string {
- const baseScriptSrc =
- "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
- const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
- const extra = extraCspDomains?.length ? " " + extraCspDomains.join(" ") : "";
- const scriptSrc = baseScriptSrc + extra;
- const frameSrc = baseFrameSrc + extra;
-
- return `
-
-
-
-
-
-
-
-
-
-`;
-}
-
-/**
- * Queue for serializing MCP app requests to an agent.
- * Ensures requests wait for the agent to stop running and are processed one at a time.
- */
-class MCPAppsRequestQueue {
- private queues = new Map<
- string,
- Array<{
- execute: () => Promise;
- resolve: (result: RunAgentResult) => void;
- reject: (error: Error) => void;
- }>
- >();
- private processing = new Map();
-
- /**
- * Add a request to the queue for a specific agent thread.
- * Returns a promise that resolves when the request completes.
- */
- async enqueue(
- agent: AbstractAgent,
- request: () => Promise,
- ): Promise {
- const threadId = agent.threadId || "default";
-
- return new Promise((resolve, reject) => {
- // Get or create queue for this thread
- let queue = this.queues.get(threadId);
- if (!queue) {
- queue = [];
- this.queues.set(threadId, queue);
- }
-
- // Add request to queue
- queue.push({ execute: request, resolve, reject });
-
- // Start processing if not already running
- this.processQueue(threadId, agent);
- });
- }
-
- private async processQueue(
- threadId: string,
- agent: AbstractAgent,
- ): Promise {
- // If already processing this queue, return
- if (this.processing.get(threadId)) {
- return;
- }
-
- this.processing.set(threadId, true);
-
- try {
- const queue = this.queues.get(threadId);
- if (!queue) return;
-
- while (queue.length > 0) {
- const item = queue[0]!;
-
- try {
- // Wait for any active run to complete before processing
- await this.waitForAgentIdle(agent);
-
- // Execute the request
- const result = await item.execute();
- item.resolve(result);
- } catch (error) {
- item.reject(
- error instanceof Error ? error : new Error(String(error)),
- );
- }
-
- // Remove processed item
- queue.shift();
- }
- } finally {
- this.processing.set(threadId, false);
- }
- }
-
- private waitForAgentIdle(agent: AbstractAgent): Promise {
- return new Promise((resolve) => {
- if (!agent.isRunning) {
- resolve();
- return;
- }
-
- let done = false;
- const finish = () => {
- if (done) return;
- done = true;
- clearInterval(checkInterval);
- sub.unsubscribe();
- resolve();
- };
-
- const sub = agent.subscribe({
- onRunFinalized: finish,
- onRunFailed: finish,
- });
-
- // Fallback for reconnect scenarios where events don't fire
- const checkInterval = setInterval(() => {
- if (!agent.isRunning) finish();
- }, 500);
- });
- }
-}
-
-// Global queue instance for all MCP app requests
-const mcpAppsRequestQueue = new MCPAppsRequestQueue();
-
-// URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
-// validates `url` as a plain string only (noopener/noreferrer does not restrict
-// the scheme), so ui/open-link could otherwise become an XSS vector.
+// The app<->host protocol (ext-apps AppBridge, sandbox proxy, request queue,
+// ui/message + open-link handlers, tool input/result) lives in the shared,
+// framework-agnostic package. This file is now a THIN React adapter over it: it
+// owns the iframe (create/mount/size/remove) and wires the session's reactive
+// hooks to React state; all protocol logic is `bindMcpApp`.
//
-// We use a denylist rather than an allowlist on purpose: deep links use
-// arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
-// `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
-// just hands off to an OS handler — it does not execute script in the page, so
-// it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
-// pass regardless. What IS dangerous is the small, well-known set of schemes
-// that execute script or render attacker HTML in the page context; block those
-// and allow everything else (including deep links).
-const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
- "javascript:",
- "data:",
- "vbscript:",
- "blob:",
- "file:",
-]);
+// The lightweight activity surface (type + content schema + follow-up runner)
+// is re-exported from the package's bridge-free `/activity` entry, so importing
+// it (for the activity registry) does NOT pull the ext-apps bundle. The bridge
+// itself is loaded lazily via a dynamic `import("@copilotkit/mcp-apps-renderer")`
+// inside the effect, so a `` app only pays for it when it actually
+// renders an MCP App.
+export {
+ MCPAppsActivityType,
+ MCPAppsActivityContentSchema,
+ ɵrunMcpFollowUp,
+} from "@copilotkit/mcp-apps-renderer/activity";
+export type {
+ MCPAppsActivityContent,
+ ɵMcpFollowUpHost,
+} from "@copilotkit/mcp-apps-renderer/activity";
-/**
- * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
- */
-export const MCPAppsActivityType = "mcp-apps";
-
-// Zod schema for activity content validation (middleware 0.0.2 format)
-export const MCPAppsActivityContentSchema = z.object({
- result: z.object({
- content: z.array(z.any()).optional(),
- structuredContent: z.any().optional(),
- isError: z.boolean().optional(),
- }),
- // Resource URI to fetch (e.g., "ui://server/dashboard")
- resourceUri: z.string(),
- // MD5 hash of server config (renamed from serverId in 0.0.1)
- serverHash: z.string(),
- // Optional stable server ID from config (takes precedence over serverHash)
- serverId: z.string().optional(),
- // Original tool input arguments
- toolInput: z.record(z.string(), z.unknown()).optional(),
-});
-
-export type MCPAppsActivityContent = z.infer<
- typeof MCPAppsActivityContentSchema
->;
-
-// Type for the resource fetched from the server
-interface FetchedResource {
- uri: string;
- mimeType?: string;
- text?: string;
- blob?: string;
- _meta?: {
- ui?: {
- prefersBorder?: boolean;
- csp?: {
- connectDomains?: string[];
- resourceDomains?: string[];
- };
- };
- };
-}
+import type { MCPAppsActivityContent } from "@copilotkit/mcp-apps-renderer/activity";
+// Type-only imports: erased at build, so they never pull the ext-apps bridge
+// into the bundle. Only the dynamic import() below does, and only lazily.
+import type {
+ McpAppSession,
+ FetchedResource,
+} from "@copilotkit/mcp-apps-renderer";
/**
* Props for the activity renderer component
@@ -292,37 +48,15 @@ interface MCPAppsActivityRendererProps {
* MCP Apps Extension Activity Renderer
*
* Renders MCP Apps UI in a sandboxed iframe with full protocol support.
- * Fetches resource content on-demand via proxied MCP requests.
+ * Fetches resource content on-demand via proxied MCP requests. The React shell
+ * owns the iframe; `bindMcpApp` owns the protocol.
*/
-/**
- * Permissive `ui/message` schema. ext-apps restricts the request to
- * `role: "user"` with no `followUp`, but CopilotKit intentionally extends
- * `ui/message` with `role` ("user" | "assistant") and `followUp` (documented
- * behavior with dedicated tests). We register our own handler (instead of the
- * bridge's strict `onmessage`) so those extensions survive the migration.
- *
- * Going forward, widgets SHOULD pass the extensions under
- * `params._meta.copilotkit`; the top-level `role`/`followUp` fields are the
- * legacy channel, kept for backward compatibility and slated for deprecation.
- */
-const CopilotKitUiMessageSchema = z.object({
- method: z.literal("ui/message"),
- params: z
- .object({
- role: z.string().optional(),
- content: z.array(z.any()).optional(),
- followUp: z.boolean().optional(),
- _meta: z.record(z.string(), z.any()).optional(),
- })
- .passthrough(),
-});
-
export const MCPAppsActivityRenderer: React.FC =
function MCPAppsActivityRenderer({ content, agent }) {
const { copilotkit } = useCopilotKit();
const containerRef = useRef(null);
const iframeRef = useRef(null);
- const [iframeReady, setIframeReady] = useState(false);
+ const sessionRef = useRef(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [iframeSize, setIframeSize] = useState<{
@@ -332,392 +66,127 @@ export const MCPAppsActivityRenderer: React.FC =
const [fetchedResource, setFetchedResource] =
useState(null);
- // Use refs for values that shouldn't trigger re-renders but need latest values
+ // Latest content/agent for the session's live getters (they must read the
+ // current values on every proxied request, not the values at bind time).
const contentRef = useRef(content);
contentRef.current = content;
-
- // Store agent in a ref for use in async handlers
const agentRef = useRef(agent);
agentRef.current = agent;
- // ext-apps host bridge for this widget instance (owns the app<->host protocol).
- const bridgeRef = useRef(null);
-
- // Ref to track fetch state - survives StrictMode remounts
- const fetchStateRef = useRef<{
- inProgress: boolean;
- promise: Promise | null;
- resourceUri: string | null;
- }>({ inProgress: false, promise: null, resourceUri: null });
-
- // Effect 0: Fetch the resource content on mount
- // Uses ref-based deduplication to handle React StrictMode double-mounting
+ // Effect 1: create the sandbox iframe and bind the MCP session. Re-binds
+ // only when the widget identity (resourceUri/serverHash/serverId) or the
+ // agent/host changes - NOT when tool input/result stream in (those are
+ // pushed by the effects below without recreating the iframe).
useEffect(() => {
- const { resourceUri, serverHash, serverId } = content;
-
- // Check if we already have a fetch in progress for this resource
- // This handles StrictMode double-mounting - second mount reuses first mount's promise
- if (
- fetchStateRef.current.inProgress &&
- fetchStateRef.current.resourceUri === resourceUri
- ) {
- // Reuse the existing promise
- fetchStateRef.current.promise
- ?.then((resource) => {
- if (resource) {
- setFetchedResource(resource);
- setIsLoading(false);
- }
- })
- .catch((err) => {
- setError(err instanceof Error ? err : new Error(String(err)));
- setIsLoading(false);
- });
+ const container = containerRef.current;
+ if (!container) {
return;
}
-
if (!agent) {
setError(new Error("No agent available to fetch resource"));
setIsLoading(false);
return;
}
- // Mark fetch as in progress
- fetchStateRef.current.inProgress = true;
- fetchStateRef.current.resourceUri = resourceUri;
-
- // Create the fetch promise using the queue to serialize requests
- const fetchPromise = (async (): Promise => {
- try {
- // Use queue to wait for agent to be idle and serialize requests
- const runResult = await mcpAppsRequestQueue.enqueue(agent, () =>
- agent.runAgent({
- forwardedProps: {
- __proxiedMCPRequest: {
- serverHash,
- serverId, // optional, takes precedence if provided
- method: "resources/read",
- params: { uri: resourceUri },
- },
- },
- }),
- );
-
- // Extract resource from result
- // The response format is: { contents: [{ uri, mimeType, text?, blob?, _meta? }] }
- const resultData = runResult.result as
- | { contents?: FetchedResource[] }
- | undefined;
- const resource = resultData?.contents?.[0];
-
- if (!resource) {
- throw new Error("No resource content in response");
- }
-
- return resource;
- } catch (err) {
- console.error("[MCPAppsRenderer] Failed to fetch resource:", err);
- throw err;
- } finally {
- // Mark fetch as complete
- fetchStateRef.current.inProgress = false;
- }
- })();
-
- // Store the promise for potential reuse
- fetchStateRef.current.promise = fetchPromise;
-
- // Handle the result
- fetchPromise
- .then((resource) => {
- if (resource) {
- setFetchedResource(resource);
- setIsLoading(false);
- }
- })
- .catch((err) => {
- setError(err instanceof Error ? err : new Error(String(err)));
- setIsLoading(false);
- });
-
- // No cleanup needed - we want the fetch to complete even if StrictMode unmounts
- }, [agent, content]);
-
- // Effect 1: connect the ext-apps AppBridge to the sandboxed iframe.
- // The bridge owns the app<->host protocol (initialize/capabilities/context,
- // requests, notifications, tool input/result) over a PostMessage transport.
- useEffect(() => {
- if (isLoading || !fetchedResource) {
- return;
- }
- const container = containerRef.current;
- if (!container) {
- return;
- }
-
let mounted = true;
- let bridge: AppBridge | null = null;
- let createdIframe: HTMLIFrameElement | null = null;
+ setIsLoading(true);
+ setError(null);
+
+ // The host owns the iframe: create + mount it here (bindMcpApp only
+ // configures the sandbox contract + talks to it through the bridge).
+ const iframe = document.createElement("iframe");
+ iframe.style.width = "100%";
+ iframe.style.height = "100px";
+ iframe.style.border = "none";
+ iframe.style.backgroundColor = "transparent";
+ iframe.style.display = "block";
+ container.appendChild(iframe);
+ iframeRef.current = iframe;
const setup = async () => {
try {
- // Load the ext-apps bridge FIRST, before creating/attaching the iframe.
- // The sandbox proxy posts `sandbox-proxy-ready` once, during srcdoc
- // execution, and the PostMessageTransport must already be listening
- // (via connect()) when that fires. Awaiting the dynamic import after
- // the iframe is attached would let a slow import miss that
- // notification, leaving the widget blank; doing it here means there is
- // no event-loop yield between attaching the iframe and connecting.
- // The type-only import at the top of the file keeps this lazy (see that
- // note); the try/catch rethrows with an actionable message if the peer
- // is missing or version-skewed.
- const bridgeModule =
- await import("@modelcontextprotocol/ext-apps/app-bridge").catch(
- (importErr) => {
- throw new Error(
- "MCP Apps require '@modelcontextprotocol/ext-apps' and its peer " +
- "'@modelcontextprotocol/sdk'. Install them with: npm install " +
- "@modelcontextprotocol/ext-apps @modelcontextprotocol/sdk",
- { cause: importErr },
- );
+ // Load the bridge package lazily. The bridge is heavy (it pulls the
+ // MCP SDK Protocol + zod schemas, ~40-50 kB gzipped); keeping it behind
+ // a dynamic import() means a non-MCP `` app never pays for
+ // it. The try/catch rethrows with an actionable message if the package
+ // (or its ext-apps dependency) is missing.
+ const mod = await import("@copilotkit/mcp-apps-renderer").catch(
+ (importErr) => {
+ throw new Error(
+ "MCP Apps require '@copilotkit/mcp-apps-renderer' and its " +
+ "'@modelcontextprotocol/ext-apps' dependency. Reinstall your " +
+ "dependencies if this package is missing.",
+ { cause: importErr },
+ );
+ },
+ );
+ if (!mounted) {
+ iframe.remove();
+ return;
+ }
+
+ const session = mod.bindMcpApp({
+ iframe,
+ getContent: () => contentRef.current,
+ getAgent: () => agentRef.current,
+ host: copilotkit,
+ hooks: {
+ onResource: (resource) => {
+ if (!mounted) return;
+ setFetchedResource(resource);
+ setIsLoading(false);
},
- );
- if (!mounted) {
- return;
- }
- const { AppBridge, PostMessageTransport } = bridgeModule;
-
- // Create the sandbox proxy iframe (the proxy relays postMessage between
- // the host and the inner sandboxed widget).
- const iframe = document.createElement("iframe");
- createdIframe = iframe;
- iframe.style.width = "100%";
- iframe.style.height = "100px";
- iframe.style.border = "none";
- iframe.style.backgroundColor = "transparent";
- iframe.style.display = "block";
- iframe.setAttribute(
- "sandbox",
- "allow-scripts allow-same-origin allow-forms",
- );
- // Cross-frontend MCP-apps surface contract: the host-created sandbox
- // iframe is the addressable render surface for the MCP app, and every
- // frontend must expose it under the SAME testid so one shared probe
- // (harness `d5-mcp-apps`) and one shared e2e spec can assert the
- // surface mounted without per-frontend selectors. Angular declares
- // the same pair on its `copilot-mcp-apps-widget` template iframe;
- // Vue's renderer mirrors this block.
- iframe.setAttribute("data-testid", "mcp-app-iframe");
- iframe.setAttribute("title", "Interactive MCP application");
-
- const cspDomains = fetchedResource._meta?.ui?.csp?.resourceDomains;
- iframe.srcdoc = buildSandboxHTML(cspDomains);
- iframeRef.current = iframe;
- container.appendChild(iframe);
-
- const win = iframe.contentWindow;
- if (!win) {
- throw new Error("Sandbox iframe has no contentWindow");
- }
-
- // Extract the widget HTML from the fetched resource. Done after the
- // iframe is mounted so a resource missing text/blob still leaves the
- // sandbox surface present (it just never receives content).
- let html: string;
- if (fetchedResource.text) {
- html = fetchedResource.text;
- } else if (fetchedResource.blob) {
- html = atob(fetchedResource.blob);
- } else {
- throw new Error("Resource has no text or blob content");
- }
-
- bridge = new AppBridge(
- null,
- { name: "CopilotKit MCP Apps Host", version: "1.0.0" },
- { openLinks: {}, logging: {}, message: { text: {} } },
- // Seed the host context at construction (before connect) so it is
- // already in place when the widget's ui/initialize is handled. Doing
- // this via setHostContext after connect would only win the race by
- // luck (it depends on the notification landing before initialize),
- // and #6689 relies on this seam to advertise displayMode /
- // availableDisplayModes at initialize.
- { hostContext: { theme: "light", platform: "web" } },
- );
-
- // Sandbox handshake: when the proxy is ready, load the widget HTML into
- // the inner sandboxed iframe.
- bridge.onsandboxready = () => {
- void bridge?.sendSandboxResourceReady({ html });
- };
-
- // --- App -> host requests ---
- // ui/message uses a custom handler (not the bridge's strict onmessage)
- // to preserve CopilotKit's role/followUp extensions. Extensions are read
- // from params._meta.copilotkit first (preferred), then from the legacy
- // top-level params.role / params.followUp (deprecated).
- bridge.setRequestHandler(CopilotKitUiMessageSchema, async (req) => {
- const currentAgent = agentRef.current;
- if (!currentAgent) {
- console.warn("[MCPAppsRenderer] ui/message: No agent available");
- return { isError: false };
- }
- try {
- const params = req.params;
- const ck = (params._meta?.copilotkit ?? {}) as {
- role?: string;
- followUp?: boolean;
- };
- const role =
- (ck.role as "user" | "assistant") ||
- (params.role as "user" | "assistant") ||
- "user";
- const textContent =
- (
- params.content as
- | Array<{ type: string; text?: string }>
- | undefined
- )
- ?.filter((c) => c.type === "text" && c.text)
- .map((c) => c.text)
- .join("\n") || "";
- if (textContent) {
- currentAgent.addMessage({
- id: crypto.randomUUID(),
- role,
- content: textContent,
- });
- }
- const followUp = ck.followUp ?? params.followUp;
- const shouldFollowUp = followUp ?? role === "user";
- if (shouldFollowUp && textContent) {
- const capturedThreadId = currentAgent.threadId || "default";
- mcpAppsRequestQueue
- .enqueue(currentAgent, () =>
- ɵrunMcpFollowUp({
- host: copilotkit,
- agent: currentAgent,
- capturedThreadId,
- }),
- )
- .catch((err) =>
- console.error(
- "[MCPAppsRenderer] ui/message agent run failed:",
- err,
- ),
- );
- }
- return { isError: false };
- } catch (err) {
- console.error("[MCPAppsRenderer] ui/message error:", err);
- return { isError: true };
- }
+ onSizeChanged: (size) => {
+ if (mounted) setIframeSize(size);
+ },
+ onError: (err) => {
+ if (!mounted) return;
+ setError(err);
+ setIsLoading(false);
+ },
+ },
});
+ sessionRef.current = session;
- bridge.onopenlink = async ({ url }) => {
- // `url` is guaranteed to be a string by the bridge's ui/open-link
- // schema, but the schema does not restrict the scheme. Parse it and
- // block only the script-executing / attacker-HTML schemes (see
- // MCP_OPEN_LINK_BLOCKED_SCHEMES). Everything else is allowed,
- // including custom-scheme deep links (`myapp:`, `whatsapp:`, ...) and
- // https universal links, which hand off to an OS handler rather than
- // executing in the page.
- let parsed: URL;
- try {
- parsed = new URL(url);
- } catch {
- console.warn(
- "[MCPAppsRenderer] ui/open-link rejected: unparseable url",
- );
- return { isError: true };
- }
- if (MCP_OPEN_LINK_BLOCKED_SCHEMES.has(parsed.protocol)) {
- console.warn(
- "[MCPAppsRenderer] ui/open-link rejected: blocked scheme",
- parsed.protocol,
- );
- return { isError: true };
- }
- window.open(url, "_blank", "noopener,noreferrer");
- return { isError: false };
- };
-
- bridge.oncalltool = async (params) => {
- const { serverHash, serverId } = contentRef.current;
- const currentAgent = agentRef.current;
- // Keep these two failures distinct: they point at different setup
- // problems when debugging the proxy wiring.
- if (!serverHash) {
- throw new Error("No server hash available for proxying");
- }
- if (!currentAgent) {
- throw new Error("No agent available for proxying");
- }
- const runResult = await mcpAppsRequestQueue.enqueue(
- currentAgent,
- () =>
- currentAgent.runAgent({
- forwardedProps: {
- __proxiedMCPRequest: {
- serverHash,
- serverId,
- method: "tools/call",
- params,
- },
- },
- }),
- );
- return (runResult.result as CallToolResult) || { content: [] };
- };
-
- // --- App -> host notifications ---
- bridge.onsizechange = (p) => {
- if (!mounted) return;
- const { width, height } = p || {};
- setIframeSize({
- width: typeof width === "number" ? width : undefined,
- height: typeof height === "number" ? height : undefined,
- });
- };
- bridge.oninitialized = () => {
- if (mounted) setIframeReady(true);
- };
- bridge.onloggingmessage = (p) => {
- console.log("[MCPAppsRenderer] App log:", p);
- };
-
- const transport = new PostMessageTransport(win, win);
- await bridge.connect(transport);
- if (!mounted) {
- await bridge.close();
- return;
+ // Push any tool input/result already present at bind time (the session
+ // buffers until the widget reports initialized).
+ const current = contentRef.current;
+ if (current.toolInput) {
+ session.sendToolInput(current.toolInput as Record);
+ }
+ if (current.result) {
+ session.sendToolResult(
+ current.result as Parameters[0],
+ );
}
- // Host context was seeded at construction (see the AppBridge options
- // above), so it is already advertised by the time ui/initialize runs.
- bridgeRef.current = bridge;
} catch (err) {
console.error("[MCPAppsRenderer] Setup error:", err);
if (mounted) {
setError(err instanceof Error ? err : new Error(String(err)));
+ setIsLoading(false);
}
}
};
- setup();
+ void setup();
return () => {
mounted = false;
- bridgeRef.current = null;
- void bridge?.close();
- if (createdIframe) {
- createdIframe.remove();
- createdIframe = null;
- }
+ sessionRef.current?.teardown();
+ sessionRef.current = null;
+ iframe.remove();
iframeRef.current = null;
};
- }, [isLoading, fetchedResource, copilotkit]);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [
+ agent,
+ copilotkit,
+ content.resourceUri,
+ content.serverHash,
+ content.serverId,
+ ]);
- // Effect 2: Update iframe size when it changes
+ // Effect 2: size the iframe when the widget reports a new content size.
useEffect(() => {
if (iframeRef.current) {
if (iframeSize.width !== undefined) {
@@ -731,23 +200,24 @@ export const MCPAppsActivityRenderer: React.FC =
}
}, [iframeSize]);
- // Effect 3: Send tool input when iframe ready
+ // Effect 3: forward tool input to the widget (buffered by the session until
+ // the widget is ready).
useEffect(() => {
- if (iframeReady && content.toolInput) {
- void bridgeRef.current?.sendToolInput({
- arguments: content.toolInput as Record,
- });
- }
- }, [iframeReady, content.toolInput]);
-
- // Effect 4: Send tool result when iframe ready
- useEffect(() => {
- if (iframeReady && content.result) {
- void bridgeRef.current?.sendToolResult(
- content.result as CallToolResult,
+ if (content.toolInput) {
+ sessionRef.current?.sendToolInput(
+ content.toolInput as Record,
);
}
- }, [iframeReady, content.result]);
+ }, [content.toolInput]);
+
+ // Effect 4: forward tool result to the widget.
+ useEffect(() => {
+ if (content.result) {
+ sessionRef.current?.sendToolResult(
+ content.result as Parameters[0],
+ );
+ }
+ }, [content.result]);
// Determine border styling based on prefersBorder metadata from fetched resource
// true = show border/background, false = none, undefined = host decides (we default to none)
diff --git a/packages/react-core/tsdown.config.ts b/packages/react-core/tsdown.config.ts
index 41a04d22a7..f8580377e1 100644
--- a/packages/react-core/tsdown.config.ts
+++ b/packages/react-core/tsdown.config.ts
@@ -166,6 +166,13 @@ export default defineConfig([
"rxjs",
],
},
+ // UMD builds. Each externalized @copilotkit/* dep must be loaded as a global
+ // before this bundle. Note `@copilotkit/mcp-apps-renderer/activity` -> the
+ // global `CopilotKitMcpAppsRendererActivity`: the provider registers the MCP
+ // Apps activity from that (bridge-free) entry, so script-tag consumers must
+ // load `@copilotkit/mcp-apps-renderer/dist/activity.umd.js` before this bundle
+ // (see that package's README). The ext-apps bridge itself is NOT here; it is
+ // loaded lazily via dynamic import() only when an MCP App renders.
{
entry: {
index: "src/v1-deprecated-compatibility.ts",
@@ -183,6 +190,7 @@ export default defineConfig([
"@copilotkit/runtime-client-gql",
"@copilotkit/web-inspector",
"@copilotkit/a2ui-renderer",
+ "@copilotkit/mcp-apps-renderer/activity",
"@ag-ui/client",
"zod",
/\.css$/,
@@ -198,6 +206,8 @@ export default defineConfig([
"@copilotkit/runtime-client-gql": "CopilotKitRuntimeClientGQL",
"@copilotkit/web-inspector": "CopilotKitWebInspector",
"@copilotkit/a2ui-renderer": "CopilotKitA2UIRenderer",
+ "@copilotkit/mcp-apps-renderer/activity":
+ "CopilotKitMcpAppsRendererActivity",
"@ag-ui/client": "AgUIClient",
"react-markdown": "ReactMarkdown",
zod: "Zod",
@@ -220,6 +230,7 @@ export default defineConfig([
"@copilotkit/runtime-client-gql",
"@copilotkit/web-inspector",
"@copilotkit/a2ui-renderer",
+ "@copilotkit/mcp-apps-renderer/activity",
"@ag-ui/client",
"@ag-ui/core",
"zod",
@@ -236,6 +247,8 @@ export default defineConfig([
"@copilotkit/runtime-client-gql": "CopilotKitRuntimeClientGQL",
"@copilotkit/web-inspector": "CopilotKitWebInspector",
"@copilotkit/a2ui-renderer": "CopilotKitA2UIRenderer",
+ "@copilotkit/mcp-apps-renderer/activity":
+ "CopilotKitMcpAppsRendererActivity",
"@ag-ui/client": "AgUIClient",
"@ag-ui/core": "AgUICore",
"react-markdown": "ReactMarkdown",
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 1bf45db925..d5cd9e11c0 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -142,3 +142,25 @@ Or use the `DO_NOT_TRACK` standard:
```bash
export DO_NOT_TRACK=1
```
+
+## Stopping Intelligence runs
+
+Await Stop before sending another message on the same thread. With
+`IntelligenceAgentRunner`, `stopped: true` means the gateway acknowledged the
+run's terminal events and the runtime completed local cleanup. The gateway
+releases only the lock owned by that run.
+
+Stop requests agent cancellation and excludes late agent events from thread
+history. Agents that support `detachActiveRun()` also detach their local
+subscription. Older agents remain supported. An adapter must honor cancellation
+to stop external work; Stop cannot undo tool calls that already took effect.
+
+The HTTP request and response formats are unchanged. Empty-body Stop requests
+still stop the current run. Direct runner callers can pass the existing optional
+`runId` to stop only that run. A missing, mismatched, or already-requested Stop
+returns `false`. Failed terminal delivery rejects Stop; the HTTP handler returns
+its existing error response instead of reporting success. The wait is bounded by
+the existing 60-second durability window.
+
+No Intelligence upgrade is required. The runtime uses the existing terminal
+events and supports both single-event and batched gateway acknowledgments.
diff --git a/packages/runtime/package.json b/packages/runtime/package.json
index e7a9703877..5856379766 100644
--- a/packages/runtime/package.json
+++ b/packages/runtime/package.json
@@ -115,7 +115,7 @@
"openai": "^4.85.1 || >=5.0.0",
"partial-json": "^0.1.7",
"phoenix": "^1.8.4",
- "pino": "^9.2.0",
+ "pino": "^10.1.1",
"pino-pretty": "^11.2.1",
"reflect-metadata": "^0.2.2",
"rxjs": "7.8.1",
@@ -196,5 +196,8 @@
]
}
}
+ },
+ "engines": {
+ "node": ">=20"
}
}
diff --git a/packages/runtime/src/v1-deprecated/lib/__tests__/logger.test.ts b/packages/runtime/src/v1-deprecated/lib/__tests__/logger.test.ts
index 626f4a1b13..37815e1992 100644
--- a/packages/runtime/src/v1-deprecated/lib/__tests__/logger.test.ts
+++ b/packages/runtime/src/v1-deprecated/lib/__tests__/logger.test.ts
@@ -38,10 +38,9 @@ describe("createLogger", () => {
// first path in the array ("invalid path (pid)"). Any redact path fails, not
// just `pid`, so the only safe configuration is to pass none.
//
- // This monorepo pins pino to 10 through a pnpm override, and pino 10 swapped
- // fast-redact for @pinojs/redact, which uses no code generation. That means
- // the failure cannot be reproduced by running a logger here; the assertion
- // has to be on the options we hand pino.
+ // The runtime now declares pino 10, which uses @pinojs/redact without code
+ // generation. Keep checking the options directly so this regression guard
+ // does not depend on the installed redaction implementation.
it("passes no redact option to pino, because redact paths need code generation", () => {
createLogger();
diff --git a/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts b/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts
index 3687cf4dc4..fd890bf40e 100644
--- a/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts
+++ b/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts
@@ -2061,7 +2061,9 @@ describe("IntelligenceAgentRunner", () => {
false,
);
expect(agent.aborted).toBe(false);
- expect(await runner.stop({ threadId, runId: "r-current" })).toBe(true);
+ const stopping = runner.stop({ threadId, runId: "r-current" });
+ mockChannels[0].triggerJoin("ok");
+ expect(await stopping).toBe(true);
expect(agent.aborted).toBe(true);
sub.unsubscribe();
});
@@ -2072,7 +2074,9 @@ describe("IntelligenceAgentRunner", () => {
const agent = new MockAgent();
const sub = runner.run({ threadId, agent, input }).subscribe();
- const result = await runner.stop({ threadId });
+ const stopping = runner.stop({ threadId });
+ mockChannels[0].triggerJoin("ok");
+ const result = await stopping;
expect(result).toBe(true);
expect(agent.aborted).toBe(true);
@@ -2093,8 +2097,10 @@ describe("IntelligenceAgentRunner", () => {
const agent = new MockAgent();
const sub = runner.run({ threadId, agent, input }).subscribe();
- expect(await runner.stop({ threadId })).toBe(true);
+ const stopping = runner.stop({ threadId });
expect(await runner.stop({ threadId })).toBe(false);
+ mockChannels[0].triggerJoin("ok");
+ expect(await stopping).toBe(true);
sub.unsubscribe();
});
});
diff --git a/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-stop-completion.test.ts b/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-stop-completion.test.ts
new file mode 100644
index 0000000000..34d12a254c
--- /dev/null
+++ b/packages/runtime/src/v2/runtime/runner/__tests__/intelligence-stop-completion.test.ts
@@ -0,0 +1,478 @@
+import { AbstractAgent, EventType } from "@ag-ui/client";
+import type { BaseEvent, RunAgentInput } from "@ag-ui/client";
+import { Observable, Subject } from "rxjs";
+import { WebSocket, WebSocketServer } from "ws";
+import { expect, test, vi } from "vitest";
+import { IntelligenceAgentRunner } from "../intelligence";
+import { CopilotRuntime } from "../../core/runtime";
+import { createCopilotRuntimeHandler } from "../../core/fetch-handler";
+
+type Frame = [string | null, string, string, string, Record];
+
+/** Keeps producing until the test ends it, like an adapter that ignores abort. */
+class ControlledAgent extends AbstractAgent {
+ readonly output = new Subject();
+ readonly abortRun = vi.fn();
+ runCount = 0;
+
+ run(input: RunAgentInput): Observable {
+ this.runCount++;
+ return new Observable((subscriber) => {
+ subscriber.next({
+ type: EventType.RUN_STARTED,
+ threadId: input.threadId,
+ runId: input.runId,
+ });
+ return this.output.subscribe(subscriber);
+ });
+ }
+}
+
+/** Acknowledges a Phoenix request using the same reference and topic. */
+function reply(
+ socket: WebSocket,
+ frame: Frame,
+ response: Record = {},
+) {
+ socket.send(
+ JSON.stringify([
+ frame[0],
+ frame[1],
+ frame[2],
+ "phx_reply",
+ { status: "ok", response },
+ ]),
+ );
+}
+
+/** Exercises the real Phoenix client against a controllable gateway transport. */
+async function setup(batch = false) {
+ // Node 20 does not expose a global WebSocket. Keep Node 22+ on its native
+ // transport and supply the same protocol transport for the older CI lane.
+ const needsWebSocket = typeof globalThis.WebSocket === "undefined";
+ if (needsWebSocket) vi.stubGlobal("WebSocket", WebSocket);
+ const server = new WebSocketServer({ port: 0 });
+ await new Promise((resolve) => server.once("listening", resolve));
+ const address = server.address();
+ if (typeof address !== "object" || address === null)
+ throw new Error("Missing test server address");
+ const events: BaseEvent[] = [];
+ const pending: Array<{
+ socket: WebSocket;
+ frame: Frame;
+ events: BaseEvent[];
+ }> = [];
+ const locks = new Map();
+ const errors: unknown[] = [];
+ const subscriptions: Array<{ unsubscribe(): void }> = [];
+ const agents: ControlledAgent[] = [];
+ const runner = new IntelligenceAgentRunner({
+ url: `ws://127.0.0.1:${address.port}/runner`,
+ });
+
+ server.on("connection", (socket) => {
+ socket.on("message", (data) => {
+ const frame: Frame = JSON.parse(data.toString());
+ if (frame[3] === "phx_join") {
+ reply(
+ socket,
+ frame,
+ batch ? { capabilities: ["runner_event_batch_v1"] } : {},
+ );
+ } else if (frame[3] === "event" || frame[3] === "events") {
+ const received = (
+ frame[3] === "events" ? frame[4].events : [frame[4]]
+ ) as BaseEvent[];
+ pending.push({ socket, frame, events: received });
+ } else {
+ reply(socket, frame);
+ }
+ });
+ });
+
+ /** Models atomic terminal acceptance: only the exact run can release its lock. */
+ function acceptPending() {
+ for (const item of pending.splice(0)) {
+ for (const event of item.events) {
+ events.push(event);
+ if (
+ event.type === EventType.RUN_FINISHED ||
+ event.type === EventType.RUN_ERROR
+ ) {
+ const owner = event as BaseEvent & {
+ threadId: string;
+ runId: string;
+ };
+ if (locks.get(owner.threadId) === owner.runId)
+ locks.delete(owner.threadId);
+ }
+ }
+ reply(item.socket, item.frame);
+ }
+ }
+
+ /** Starts a run only when the modeled hosted lock is available. */
+ function start(runId = "run-1") {
+ if (locks.has("thread-1")) throw new Error("THREAD_LOCK_FAILED");
+ const agent = new ControlledAgent();
+ agents.push(agent);
+ locks.set("thread-1", runId);
+ const input: RunAgentInput = {
+ threadId: "thread-1",
+ runId,
+ messages: [],
+ tools: [],
+ context: [],
+ state: {},
+ forwardedProps: {},
+ };
+ subscriptions.push(
+ runner
+ .run({ threadId: input.threadId, agent, input })
+ .subscribe({ error: (error) => errors.push(error) }),
+ );
+ return agent;
+ }
+
+ /** Closes test-owned streams, sockets, timers, and server listeners. */
+ async function teardown() {
+ subscriptions.forEach((subscription) => subscription.unsubscribe());
+ agents.forEach((agent) => agent.output.complete());
+ server.clients.forEach((socket) => socket.terminate());
+ await new Promise((resolve, reject) =>
+ server.close((error) => (error ? reject(error) : resolve())),
+ );
+ if (needsWebSocket) vi.unstubAllGlobals();
+ }
+
+ return {
+ runner,
+ start,
+ pending,
+ events,
+ locks,
+ errors,
+ acceptPending,
+ teardown,
+ };
+}
+
+for (const batch of [false, true]) {
+ test(`Stop waits for terminal acceptance and permits immediate resend (${batch ? "batch" : "legacy"})`, async () => {
+ const fixture = await setup(batch);
+ try {
+ const agent = fixture.start();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ await vi.waitFor(() => expect(agent.isRunning).toBe(true));
+ let stopResolved = false;
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .then((result) => {
+ stopResolved = true;
+ return result;
+ });
+ await vi.waitFor(() =>
+ expect(
+ fixture.pending.some((item) =>
+ item.events.some((event) => event.type === EventType.RUN_FINISHED),
+ ),
+ ).toBe(true),
+ );
+
+ expect(stopResolved).toBe(false);
+ expect(fixture.locks.get("thread-1")).toBe("run-1");
+ expect(agent.abortRun).toHaveBeenCalledOnce();
+ fixture.acceptPending();
+ expect(await stopping).toBe(true);
+ expect(await fixture.runner.isRunning({ threadId: "thread-1" })).toBe(
+ false,
+ );
+ expect(fixture.locks.has("thread-1")).toBe(false);
+ expect(() => fixture.start("run-2")).not.toThrow();
+ expect(fixture.errors).toEqual([]);
+ } finally {
+ await fixture.teardown();
+ }
+ });
+}
+
+test("Stop detaches the local AG-UI subscription when abort does nothing", async () => {
+ const fixture = await setup();
+ try {
+ const agent = fixture.start();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ expect(agent.output.observed).toBe(true);
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .catch((error) => error);
+ await vi.waitFor(() => expect(agent.output.observed).toBe(false));
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+
+ expect(await stopping).toBe(true);
+ } finally {
+ await fixture.teardown();
+ }
+});
+
+for (const abortThrows of [false, true]) {
+ test(`Stop fences late events from older agents without detachActiveRun (abort throws: ${abortThrows})`, async () => {
+ const fixture = await setup();
+ try {
+ const agent = fixture.start();
+ Object.defineProperty(agent, "detachActiveRun", { value: undefined });
+ if (abortThrows)
+ agent.abortRun.mockImplementation(() => {
+ throw new Error("Adapter cannot abort");
+ });
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1", runId: "run-1" })
+ .catch((error) => error);
+ agent.output.next({
+ type: EventType.CUSTOM,
+ name: "late",
+ value: "discard",
+ });
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ expect(await stopping).toBe(true);
+ const replacement = fixture.start("run-2");
+ await vi.waitFor(() => expect(replacement.runCount).toBe(1));
+ fixture.acceptPending();
+ agent.output.next({
+ type: EventType.CUSTOM,
+ name: "late",
+ value: "discard again",
+ });
+ agent.output.error(new Error("Late producer rejection"));
+
+ expect(
+ await fixture.runner.stop({ threadId: "thread-1", runId: "run-1" }),
+ ).toBe(false);
+ expect(replacement.abortRun).not.toHaveBeenCalled();
+ expect(fixture.locks.get("thread-1")).toBe("run-2");
+ expect(fixture.events.map((event) => event.type)).not.toContain(
+ EventType.CUSTOM,
+ );
+ expect(
+ fixture.events.filter((event) => event.type === EventType.RUN_FINISHED),
+ ).toHaveLength(1);
+ expect(fixture.errors).toEqual([]);
+ } finally {
+ await fixture.teardown();
+ }
+ });
+}
+
+test("Stop closes partial text and tool calls before its single terminal event", async () => {
+ const fixture = await setup(true);
+ try {
+ const agent = fixture.start();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ agent.output.next({
+ type: EventType.TEXT_MESSAGE_START,
+ messageId: "message-1",
+ role: "assistant",
+ });
+ agent.output.next({
+ type: EventType.TEXT_MESSAGE_CONTENT,
+ messageId: "message-1",
+ delta: "partial",
+ });
+ agent.output.next({
+ type: EventType.TOOL_CALL_START,
+ toolCallId: "tool-1",
+ toolCallName: "lookup",
+ });
+ agent.output.next({
+ type: EventType.TOOL_CALL_ARGS,
+ toolCallId: "tool-1",
+ delta: "{}",
+ });
+ await vi.waitFor(() =>
+ expect(
+ fixture.pending
+ .flatMap((item) => item.events)
+ .some((event) => event.type === EventType.TOOL_CALL_ARGS),
+ ).toBe(true),
+ );
+ fixture.acceptPending();
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .catch((error) => error);
+ expect(await fixture.runner.stop({ threadId: "thread-1" })).toBe(false);
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+
+ expect(await stopping).toBe(true);
+ expect(fixture.events.map((event) => event.type)).toEqual([
+ EventType.RUN_STARTED,
+ EventType.TEXT_MESSAGE_START,
+ EventType.TEXT_MESSAGE_CONTENT,
+ EventType.TOOL_CALL_START,
+ EventType.TOOL_CALL_ARGS,
+ EventType.TEXT_MESSAGE_END,
+ EventType.TOOL_CALL_END,
+ EventType.TOOL_CALL_RESULT,
+ EventType.RUN_FINISHED,
+ ]);
+ expect(fixture.events.at(-1)).toMatchObject({
+ threadId: "thread-1",
+ runId: "run-1",
+ });
+ } finally {
+ await fixture.teardown();
+ }
+});
+
+test("Stop before channel join never starts the agent and still delivers a terminal", async () => {
+ const fixture = await setup();
+ try {
+ const agent = fixture.start();
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .catch((error) => error);
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+
+ expect(await stopping).toBe(true);
+ expect(agent.runCount).toBe(0);
+ expect(fixture.events.map((event) => event.type)).toEqual([
+ EventType.RUN_STARTED,
+ EventType.RUN_FINISHED,
+ ]);
+ } finally {
+ await fixture.teardown();
+ }
+});
+
+test("Stop does not report success if terminal delivery is permanently rejected", async () => {
+ const fixture = await setup();
+ try {
+ fixture.start();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .catch((error) => error);
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ const item = fixture.pending.shift();
+ if (!item) throw new Error("Missing terminal request");
+ item.socket.send(
+ JSON.stringify([
+ item.frame[0],
+ item.frame[1],
+ item.frame[2],
+ "phx_reply",
+ {
+ status: "error",
+ response: { reason: "active_lock_mismatch", retryable: false },
+ },
+ ]),
+ );
+
+ expect(await stopping).toBeInstanceOf(Error);
+ expect(fixture.locks.get("thread-1")).toBe("run-1");
+ expect(fixture.errors).toHaveLength(1);
+ expect(fixture.events.map((event) => event.type)).toEqual([
+ EventType.RUN_STARTED,
+ ]);
+ } finally {
+ await fixture.teardown();
+ }
+});
+
+test("Stop rejects after the durability deadline instead of acknowledging an unreleased lock", async () => {
+ const fixture = await setup();
+ try {
+ fixture.start();
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
+
+ const stopping = fixture.runner
+ .stop({ threadId: "thread-1" })
+ .catch((error) => error);
+ await vi.advanceTimersByTimeAsync(60_000);
+
+ expect(await stopping).toBeInstanceOf(Error);
+ expect(fixture.locks.get("thread-1")).toBe("run-1");
+ expect(await fixture.runner.isRunning({ threadId: "thread-1" })).toBe(
+ false,
+ );
+ expect(fixture.errors).toHaveLength(1);
+ } finally {
+ vi.useRealTimers();
+ await fixture.teardown();
+ }
+});
+
+for (const mode of ["multi-route", "single-route"] as const) {
+ test(`The ${mode} Stop endpoint preserves its response and waits for lock release`, async () => {
+ const fixture = await setup();
+ try {
+ const agent = fixture.start();
+ const runtime = new CopilotRuntime({
+ agents: { test: agent },
+ runner: fixture.runner,
+ });
+ const handler = createCopilotRuntimeHandler({
+ runtime,
+ mode,
+ activateChannels: false,
+ });
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ fixture.acceptPending();
+ let responded = false;
+ const request =
+ mode === "multi-route"
+ ? new Request("http://runtime/agent/test/stop/thread-1", {
+ method: "POST",
+ })
+ : new Request("http://runtime", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ method: "agent/stop",
+ params: { agentId: "test", threadId: "thread-1" },
+ }),
+ });
+
+ const stopping = handler(request).then((response) => {
+ responded = true;
+ return response;
+ });
+ await vi.waitFor(() => expect(fixture.pending.length).toBeGreaterThan(0));
+ expect(responded).toBe(false);
+ fixture.acceptPending();
+ const response = await stopping;
+
+ expect(response.status).toBe(200);
+ expect(await response.json()).toEqual({
+ stopped: true,
+ interrupt: {
+ type: EventType.RUN_ERROR,
+ message: "Run stopped by user",
+ code: "STOPPED",
+ },
+ });
+ expect(fixture.locks.has("thread-1")).toBe(false);
+ expect(() => fixture.start("run-2")).not.toThrow();
+ } finally {
+ await fixture.teardown();
+ }
+ });
+}
diff --git a/packages/runtime/src/v2/runtime/runner/intelligence.ts b/packages/runtime/src/v2/runtime/runner/intelligence.ts
index 4df8bdc661..ab3e45e9c2 100644
--- a/packages/runtime/src/v2/runtime/runner/intelligence.ts
+++ b/packages/runtime/src/v2/runtime/runner/intelligence.ts
@@ -12,6 +12,7 @@ import {
finalizeRunEvents,
AG_UI_CHANNEL_EVENT,
phoenixExponentialBackoff,
+ logger,
} from "@copilotkit/shared";
import type { Channel } from "phoenix";
import { Socket } from "phoenix";
@@ -47,6 +48,11 @@ interface ThreadState {
hasJoined: boolean;
supportsRunnerEventBatch: boolean;
producerFinished: boolean;
+ cancellation: Promise;
+ cancelRun: () => void;
+ completion: Promise;
+ resolveCompletion: (completed: boolean) => void;
+ stopTimer: ReturnType | null;
pendingEvents: Map<
string,
{ payload: Record; queuedAt: number }
@@ -235,6 +241,14 @@ export class IntelligenceAgentRunner extends AgentRunner {
run_id: input.runId,
});
+ let cancelRun!: () => void;
+ const cancellation = new Promise((resolve) => {
+ cancelRun = resolve;
+ });
+ let resolveCompletion!: (completed: boolean) => void;
+ const completion = new Promise((resolve) => {
+ resolveCompletion = resolve;
+ });
const state: ThreadState = {
threadId,
runId: input.runId,
@@ -249,6 +263,11 @@ export class IntelligenceAgentRunner extends AgentRunner {
hasJoined: false,
supportsRunnerEventBatch: false,
producerFinished: false,
+ cancellation,
+ cancelRun,
+ completion,
+ resolveCompletion,
+ stopTimer: null,
pendingEvents: new Map(),
activeEventBatch: null,
nextEventPushAttempt: 0,
@@ -258,7 +277,10 @@ export class IntelligenceAgentRunner extends AgentRunner {
socketReconnectWatchdog: null,
eventRetryAttempt: 0,
completeRun: () => observer.complete(),
- failRun: (error) => observer.error(error),
+ failRun: (error) => {
+ startupBoundary?.rejectStartup(error);
+ observer.error(error);
+ },
};
this.threads.set(threadId, state);
@@ -324,7 +346,12 @@ export class IntelligenceAgentRunner extends AgentRunner {
payload.type === EventType.CUSTOM &&
(payload as BaseEvent & { name?: string }).name === "stop"
) {
- this.stop({ threadId, runId: state.runId });
+ this.stop({ threadId, runId: state.runId }).catch((error) => {
+ logger.error(
+ { err: error, threadId, runId: state.runId },
+ "Failed to stop Intelligence run",
+ );
+ });
}
});
@@ -472,6 +499,7 @@ export class IntelligenceAgentRunner extends AgentRunner {
return Promise.resolve(state?.isRunning ?? false);
}
+ /** Stops this run and waits until its terminal events have been acknowledged. */
stop(request: AgentRunnerStopRequest): Promise {
const state = this.threads.get(request.threadId);
if (!state || !state.isRunning || state.stopRequested) {
@@ -483,16 +511,51 @@ export class IntelligenceAgentRunner extends AgentRunner {
state.stopRequested = true;
+ // Fence output before abort: adapters may emit synchronously, throw, or
+ // ignore cancellation. Finalization must not depend on their cooperation.
+ state.cancelRun();
+ state.stopTimer = setTimeout(() => {
+ this.failThread(
+ state.threadId,
+ state,
+ new Error("Timed out stopping Intelligence run"),
+ );
+ }, EVENT_DURABILITY_DEADLINE_MS);
+
// Direct local abort — the runtime is the authority.
if (state.agent) {
try {
state.agent.abortRun();
} catch {
- // Ignore abort errors.
+ // The local run is still fenced and must deliver its terminal events.
+ }
+ // Older AG-UI agents may not expose detachActiveRun. The cancellation
+ // race still finalizes their run without waiting for the producer.
+ if (typeof state.agent.detachActiveRun === "function") {
+ try {
+ Promise.resolve(state.agent.detachActiveRun()).catch((error) => {
+ logger.warn(
+ { err: error, threadId: state.threadId, runId: state.runId },
+ "Failed to detach stopped agent",
+ );
+ });
+ } catch (error) {
+ logger.warn(
+ { err: error, threadId: state.threadId, runId: state.runId },
+ "Failed to detach stopped agent",
+ );
+ }
}
}
- return Promise.resolve(true);
+ return state.completion.then((completed) => {
+ if (!completed) {
+ throw new Error(
+ "Intelligence run stopped before terminal events were acknowledged",
+ );
+ }
+ return true;
+ });
}
private async executeAgentRun(
@@ -566,19 +629,26 @@ export class IntelligenceAgentRunner extends AgentRunner {
};
try {
- await request.agent.runAgent(request.input, {
- onEvent: ({ event }: { event: BaseEvent }) => {
- if (event.type === EventType.RUN_STARTED) {
- pushCanonicalEvent(buildRunStartedEvent(event as RunStartedEvent));
- return;
- }
+ if (state.stopRequested) return;
+ await Promise.race([
+ request.agent.runAgent(request.input, {
+ onEvent: ({ event }: { event: BaseEvent }) => {
+ if (state.stopRequested || state.producerFinished) return;
+ if (event.type === EventType.RUN_STARTED) {
+ pushCanonicalEvent(
+ buildRunStartedEvent(event as RunStartedEvent),
+ );
+ return;
+ }
- ensureRunStarted();
- pushCanonicalEvent(event);
- },
- });
+ ensureRunStarted();
+ pushCanonicalEvent(event);
+ },
+ }),
+ state.cancellation,
+ ]);
} catch (error) {
- if (!this.isCurrentThreadState(threadId, state)) {
+ if (state.stopRequested || !this.isCurrentThreadState(threadId, state)) {
return;
}
ensureRunStarted();
@@ -883,7 +953,7 @@ export class IntelligenceAgentRunner extends AgentRunner {
return;
}
- this.removeThread(threadId, state);
+ this.removeThread(threadId, state, true);
state.completeRun();
}
@@ -1000,7 +1070,11 @@ export class IntelligenceAgentRunner extends AgentRunner {
* Idempotent — safe to call multiple times for the same threadId
* (e.g. from join error handlers, finalize, and Observable teardown).
*/
- private removeThread(threadId: string, state: ThreadState): void {
+ private removeThread(
+ threadId: string,
+ state: ThreadState,
+ completed = false,
+ ): void {
if (this.threads.get(threadId) !== state) {
return;
}
@@ -1008,6 +1082,11 @@ export class IntelligenceAgentRunner extends AgentRunner {
// Delete first so concurrent calls see the entry as already removed.
this.threads.delete(threadId);
state.isRunning = false;
+ state.resolveCompletion(completed);
+ if (state.stopTimer !== null) {
+ clearTimeout(state.stopTimer);
+ state.stopTimer = null;
+ }
this.clearPendingEventRetry(state);
this.clearPendingEventFlush(state);
if (state.eventDeadlineTimer !== null) {
diff --git a/packages/sqlite-runner/package.json b/packages/sqlite-runner/package.json
index 2a63fef557..4ea4796d6c 100644
--- a/packages/sqlite-runner/package.json
+++ b/packages/sqlite-runner/package.json
@@ -54,6 +54,6 @@
}
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/voice/package.json b/packages/voice/package.json
index 8ef288ab3d..fe27708260 100644
--- a/packages/voice/package.json
+++ b/packages/voice/package.json
@@ -50,6 +50,6 @@
"@copilotkit/runtime": "workspace:*"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/vue/package.json b/packages/vue/package.json
index 51699a316f..d944b24501 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -126,6 +126,6 @@
"vue": ">=3.3.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/web-components/package.json b/packages/web-components/package.json
index b290e83431..aef87a74d0 100644
--- a/packages/web-components/package.json
+++ b/packages/web-components/package.json
@@ -80,6 +80,6 @@
"vitest": "^3.2.4"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/packages/web-inspector/package.json b/packages/web-inspector/package.json
index 9b5f2fb2a2..c252644942 100644
--- a/packages/web-inspector/package.json
+++ b/packages/web-inspector/package.json
@@ -61,6 +61,6 @@
"ws": "^8.19.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ba54748dfd..984bf35879 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,15 +10,13 @@ overrides:
'@types/react-dom': ^19.0.2
react: 19.2.3
react-dom: 19.2.3
- next@<=15.4.11: 15.4.11
- next@>=15.5.0 <15.5.15: 15.5.15
+ next@>=15.0.0 <15.5.24: 15.5.24
+ next@>=16.0.0 <16.3.3: 16.3.3
send@<=0.19.0: 0.19.0
path-to-regexp@<=0.1.12: 0.1.13
serve-static@<=1.16.0: 1.16.0
prismjs@<=1.30.0: 1.30.0
- pino@<=10.1.1: 10.1.1
'@copilotkit/license-verifier': ~0.5.0
- next: ^16.0.10
defu@<=6.1.4: '>=6.1.5'
minimatch: '>=9.0.6'
minimatch@>=10.0.0 <10.2.1: '>=10.2.1'
@@ -67,7 +65,6 @@ overrides:
file-type: '>=21.3.1'
'@langchain/community': '>=1.1.14'
langsmith: '>=0.5.18'
- next@>=16.0.0 <16.2.3: 16.2.3
validator: '>=13.15.20'
markdown-it: '>=14.1.1'
mdast-util-to-hast@>=13.0.0 <13.2.1: '>=13.2.1'
@@ -246,8 +243,8 @@ importers:
specifier: '>=4.11.7'
version: 4.12.15
next:
- specifier: 16.2.3
- version: 16.2.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 16.3.3
+ version: 16.3.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(@types/node@20.19.27)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
openai:
specifier: ^6.16.0
version: 6.24.0(ws@8.21.3)(zod@3.25.76)
@@ -411,8 +408,8 @@ importers:
specifier: ^0.476.0
version: 0.476.0(react@19.2.3)
next:
- specifier: 16.2.3
- version: 16.2.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 16.3.3
+ version: 16.3.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(@types/node@20.19.27)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -496,8 +493,8 @@ importers:
specifier: ^0.476.0
version: 0.476.0(react@19.2.3)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -587,11 +584,11 @@ importers:
specifier: ^0.3.3
version: 0.3.37(@langchain/anthropic@0.3.34(@langchain/core@1.1.42(@opentelemetry/api@1.9.0)(openai@4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76))(ws@8.21.3))(zod@3.25.76))(@langchain/aws@1.1.1(@langchain/core@1.1.42(@opentelemetry/api@1.9.0)(openai@4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76))(ws@8.21.3)))(@langchain/core@1.1.42(@opentelemetry/api@1.9.0)(openai@4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76))(ws@8.21.3))(@opentelemetry/api@1.9.0)(axios@1.15.2)(encoding@0.1.13)(handlebars@4.7.9)(openai@4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76))(ws@8.21.3)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
next-themes:
specifier: ^0.2.1
- version: 0.2.1(next@16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ version: 0.2.1(next@15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
openai:
specifier: ^4.85.1
version: 4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76)
@@ -669,8 +666,8 @@ importers:
specifier: ^1.2.1
version: 1.2.1
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
openai:
specifier: ^4.85.1
version: 4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76)
@@ -816,8 +813,8 @@ importers:
specifier: ^0.451.0
version: 0.451.0(react@19.2.3)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
openai:
specifier: ^4.85.1
version: 4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76)
@@ -877,8 +874,8 @@ importers:
specifier: ^11.18.1
version: 11.18.2(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -977,8 +974,8 @@ importers:
specifier: ^0.414.0
version: 0.414.0(react@19.2.3)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
openai:
specifier: ^4.85.1
version: 4.104.0(encoding@0.1.13)(ws@8.21.3)(zod@3.25.76)
@@ -1358,8 +1355,8 @@ importers:
specifier: workspace:*
version: link:../../../../../packages/runtime
next:
- specifier: 16.2.3
- version: 16.2.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 16.3.3
+ version: 16.3.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(@types/node@22.19.11)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -1407,8 +1404,8 @@ importers:
specifier: workspace:*
version: link:../../../packages/react-core
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -1670,8 +1667,8 @@ importers:
specifier: '>=4.11.7'
version: 4.12.15
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
openai:
specifier: ^5.9.0
version: 5.23.2(ws@8.21.3)(zod@3.25.76)
@@ -1723,13 +1720,13 @@ importers:
dependencies:
'@storybook/nextjs':
specifier: ^10.2.10
- version: 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(next@16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(type-fest@4.41.0)(typescript@5.8.2)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ version: 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(next@15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(type-fest@4.41.0)(typescript@5.8.2)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
'@storybook/react':
specifier: ^10.2.10
version: 10.3.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
next:
- specifier: ^16.0.10
- version: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ specifier: 15.5.24
+ version: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react:
specifier: 19.2.3
version: 19.2.3
@@ -2667,6 +2664,37 @@ importers:
specifier: ^4.1.3
version: 4.1.5(@opentelemetry/api@1.9.0)(@types/node@22.19.11)(@vitest/coverage-v8@4.1.5)(jsdom@29.1.0(@noble/hashes@1.8.0))(vite@7.3.2(@types/node@22.19.11)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.21.0)(yaml@2.9.0))
+ packages/mcp-apps-renderer:
+ dependencies:
+ '@copilotkit/shared':
+ specifier: workspace:*
+ version: link:../shared
+ '@modelcontextprotocol/ext-apps':
+ specifier: ^1.7.5
+ version: 1.7.5(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76)
+ '@modelcontextprotocol/sdk':
+ specifier: '>=1.26.0'
+ version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76)
+ devDependencies:
+ '@ag-ui/client':
+ specifier: 0.0.59
+ version: 0.0.59
+ jsdom:
+ specifier: ^26.1.0
+ version: 26.1.0
+ tsdown:
+ specifier: ^0.20.3
+ version: 0.20.3(@arethetypeswrong/core@0.18.2)(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(oxc-resolver@11.24.2)(publint@0.3.17)(synckit@0.11.12)(typescript@5.9.2)
+ typescript:
+ specifier: 5.9.2
+ version: 5.9.2
+ vitest:
+ specifier: ^3.2.4
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@25.6.0)(@vitest/ui@3.2.4)(jiti@2.7.0)(jsdom@26.1.0)(less@4.6.7)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.21.0)(yaml@2.9.0)
+ zod:
+ specifier: '>=3.22.3'
+ version: 3.25.76
+
packages/react-core:
dependencies:
'@ag-ui/client':
@@ -2681,6 +2709,9 @@ importers:
'@copilotkit/core':
specifier: workspace:*
version: link:../core
+ '@copilotkit/mcp-apps-renderer':
+ specifier: workspace:*
+ version: link:../mcp-apps-renderer
'@copilotkit/runtime-client-gql':
specifier: workspace:*
version: link:../runtime-client-gql
@@ -2696,9 +2727,6 @@ importers:
'@jetbrains/websandbox':
specifier: ^1.1.3
version: 1.1.3
- '@modelcontextprotocol/ext-apps':
- specifier: ^1.7.5
- version: 1.7.5(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76)
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.15
version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -2754,9 +2782,6 @@ importers:
specifier: ^3.24.5
version: 3.25.1(zod@3.25.76)
devDependencies:
- '@modelcontextprotocol/sdk':
- specifier: '>=1.26.0'
- version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76)
'@tailwindcss/cli':
specifier: ^4.1.11
version: 4.1.18
@@ -3244,7 +3269,7 @@ importers:
specifier: ^1.8.4
version: 1.8.4
pino:
- specifier: 10.1.1
+ specifier: ^10.1.1
version: 10.1.1
pino-pretty:
specifier: ^11.2.1
@@ -7138,6 +7163,9 @@ packages:
'@emnapi/runtime@1.11.2':
resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==}
+ '@emnapi/runtime@1.11.3':
+ resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+
'@emnapi/runtime@1.4.5':
resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==}
@@ -8070,6 +8098,10 @@ packages:
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
engines: {node: '>=18'}
+ '@img/colour@1.1.0':
+ resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
+ engines: {node: '>=18'}
+
'@img/sharp-darwin-arm64@0.33.5':
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8082,6 +8114,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@img/sharp-darwin-arm64@0.35.4':
+ resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [darwin]
+
'@img/sharp-darwin-x64@0.33.5':
resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8094,6 +8132,17 @@ packages:
cpu: [x64]
os: [darwin]
+ '@img/sharp-darwin-x64@0.35.4':
+ resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-freebsd-wasm32@0.35.4':
+ resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==}
+ engines: {node: '>=20.9.0'}
+ os: [freebsd]
+
'@img/sharp-libvips-darwin-arm64@1.0.4':
resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==}
cpu: [arm64]
@@ -8104,6 +8153,11 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@img/sharp-libvips-darwin-arm64@1.3.3':
+ resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==}
+ cpu: [arm64]
+ os: [darwin]
+
'@img/sharp-libvips-darwin-x64@1.0.4':
resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==}
cpu: [x64]
@@ -8114,6 +8168,11 @@ packages:
cpu: [x64]
os: [darwin]
+ '@img/sharp-libvips-darwin-x64@1.3.3':
+ resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==}
+ cpu: [x64]
+ os: [darwin]
+
'@img/sharp-libvips-linux-arm64@1.0.4':
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
cpu: [arm64]
@@ -8126,6 +8185,12 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-arm64@1.3.3':
+ resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linux-arm@1.0.5':
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
cpu: [arm]
@@ -8138,18 +8203,36 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-arm@1.3.3':
+ resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linux-ppc64@1.2.4':
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-ppc64@1.3.3':
+ resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linux-riscv64@1.2.4':
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-riscv64@1.3.3':
+ resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linux-s390x@1.0.4':
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
cpu: [s390x]
@@ -8162,6 +8245,12 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-s390x@1.3.3':
+ resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linux-x64@1.0.4':
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
cpu: [x64]
@@ -8174,6 +8263,12 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-libvips-linux-x64@1.3.3':
+ resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
cpu: [arm64]
@@ -8186,6 +8281,12 @@ packages:
os: [linux]
libc: [musl]
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
+ resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
cpu: [x64]
@@ -8198,6 +8299,12 @@ packages:
os: [linux]
libc: [musl]
+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
+ resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
'@img/sharp-linux-arm64@0.33.5':
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8212,6 +8319,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-arm64@0.35.4':
+ resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linux-arm@0.33.5':
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8226,6 +8340,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-arm@0.35.4':
+ resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linux-ppc64@0.34.5':
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8233,6 +8354,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-ppc64@0.35.4':
+ resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linux-riscv64@0.34.5':
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8240,6 +8368,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-riscv64@0.35.4':
+ resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linux-s390x@0.33.5':
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8254,6 +8389,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-s390x@0.35.4':
+ resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linux-x64@0.33.5':
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8268,6 +8410,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@img/sharp-linux-x64@0.35.4':
+ resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
'@img/sharp-linuxmusl-arm64@0.33.5':
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8282,6 +8431,13 @@ packages:
os: [linux]
libc: [musl]
+ '@img/sharp-linuxmusl-arm64@0.35.4':
+ resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
'@img/sharp-linuxmusl-x64@0.33.5':
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8296,6 +8452,13 @@ packages:
os: [linux]
libc: [musl]
+ '@img/sharp-linuxmusl-x64@0.35.4':
+ resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
'@img/sharp-wasm32@0.33.5':
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8306,12 +8469,27 @@ packages:
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [wasm32]
+ '@img/sharp-wasm32@0.35.4':
+ resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==}
+ engines: {node: '>=20.9.0'}
+
+ '@img/sharp-webcontainers-wasm32@0.35.4':
+ resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [wasm32]
+
'@img/sharp-win32-arm64@0.34.5':
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [win32]
+ '@img/sharp-win32-arm64@0.35.4':
+ resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [win32]
+
'@img/sharp-win32-ia32@0.33.5':
resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8324,6 +8502,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@img/sharp-win32-ia32@0.35.4':
+ resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==}
+ engines: {node: ^20.9.0}
+ cpu: [ia32]
+ os: [win32]
+
'@img/sharp-win32-x64@0.33.5':
resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -8336,6 +8520,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@img/sharp-win32-x64@0.35.4':
+ resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [win32]
+
'@inquirer/ansi@1.0.2':
resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==}
engines: {node: '>=18'}
@@ -9966,11 +10156,11 @@ packages:
'@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4
'@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4
- '@next/env@16.1.3':
- resolution: {integrity: sha512-BLP14oBOvZWXgfdJf9ao+VD8O30uE+x7PaV++QtACLX329WcRSJRO5YJ+Bcvu0Q+c/lei41TjSiFf6pXqnpbQA==}
+ '@next/env@15.5.24':
+ resolution: {integrity: sha512-mBDF7T0XKZjs9SpUAl0buizVO+O02ULjOvWX8o/AZo/5AGw/UAS1Zzcylmd4pqbftzmKQi+L/nB4jgBYKEAl5Q==}
- '@next/env@16.2.3':
- resolution: {integrity: sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==}
+ '@next/env@16.3.3':
+ resolution: {integrity: sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==}
'@next/eslint-plugin-next@15.4.4':
resolution: {integrity: sha512-1FDsyN//ai3Jd97SEd7scw5h1yLdzDACGOPRofr2GD3sEFsBylEEoL0MHSerd4n2dq9Zm/mFMqi4+NRMOreOKA==}
@@ -9978,106 +10168,106 @@ packages:
'@next/eslint-plugin-next@16.0.8':
resolution: {integrity: sha512-1miV0qXDcLUaOdHridVPCh4i39ElRIAraseVIbb3BEqyZ5ol9sPyjTP/GNTPV5rBxqxjF6/vv5zQTVbhiNaLqA==}
- '@next/swc-darwin-arm64@16.1.3':
- resolution: {integrity: sha512-CpOD3lmig6VflihVoGxiR/l5Jkjfi4uLaOR4ziriMv0YMDoF6cclI+p5t2nstM8TmaFiY6PCTBgRWB57/+LiBA==}
+ '@next/swc-darwin-arm64@15.5.24':
+ resolution: {integrity: sha512-AGdNLvxZNY6eR2iSnV+6wUa8CiHTMr4F7g3uHH7fT4ICIJBE00R9u4tzN/Vuwsw0cOi8MTD2HJcTCb6siMH88Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-arm64@16.2.3':
- resolution: {integrity: sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==}
+ '@next/swc-darwin-arm64@16.3.3':
+ resolution: {integrity: sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@16.1.3':
- resolution: {integrity: sha512-aF4us2JXh0zn3hNxvL1Bx3BOuh8Lcw3p3Xnurlvca/iptrDH1BrpObwkw9WZra7L7/0qB9kjlREq3hN/4x4x+Q==}
+ '@next/swc-darwin-x64@15.5.24':
+ resolution: {integrity: sha512-9HrQajBMmGcrrrvDfRimiCrbAPh3E6uHJmwBovYr6Yrmi9p9PZqI876BrXX280wICh3o2XwUlp4blkB0NNBqFg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-darwin-x64@16.2.3':
- resolution: {integrity: sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==}
+ '@next/swc-darwin-x64@16.3.3':
+ resolution: {integrity: sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@16.1.3':
- resolution: {integrity: sha512-8VRkcpcfBtYvhGgXAF7U3MBx6+G1lACM1XCo1JyaUr4KmAkTNP8Dv2wdMq7BI+jqRBw3zQE7c57+lmp7jCFfKA==}
+ '@next/swc-linux-arm64-gnu@15.5.24':
+ resolution: {integrity: sha512-rl9LSfE75si0WT3cDgdUC1XYCKS+TgxC+/IjitmeycrAG18X/plIP1/vy8dd/HPycYcIvE688PD7FuvEAiEAew==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-arm64-gnu@16.2.3':
- resolution: {integrity: sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==}
+ '@next/swc-linux-arm64-gnu@16.3.3':
+ resolution: {integrity: sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-arm64-musl@16.1.3':
- resolution: {integrity: sha512-UbFx69E2UP7MhzogJRMFvV9KdEn4sLGPicClwgqnLht2TEi204B71HuVfps3ymGAh0c44QRAF+ZmvZZhLLmhNg==}
+ '@next/swc-linux-arm64-musl@15.5.24':
+ resolution: {integrity: sha512-TlNAnpsjxSF3aAUtqnfmtXXf8m9sIDBlmF3c7bTAlnshUYu2U0OxN2uf5d0gcFwqHVEdivJNBcCaqNOwPGNimw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@next/swc-linux-arm64-musl@16.2.3':
- resolution: {integrity: sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==}
+ '@next/swc-linux-arm64-musl@16.3.3':
+ resolution: {integrity: sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@next/swc-linux-x64-gnu@16.1.3':
- resolution: {integrity: sha512-SzGTfTjR5e9T+sZh5zXqG/oeRQufExxBF6MssXS7HPeZFE98JDhCRZXpSyCfWrWrYrzmnw/RVhlP2AxQm+wkRQ==}
+ '@next/swc-linux-x64-gnu@15.5.24':
+ resolution: {integrity: sha512-7dwtlhr0SLndqTG1z9ncRkbJswDZiKWlxzFyXDvJ2RDZRDRHp8zyMJ4D9UH/FgnQeXxxB6gZy2pMcIUoNKQ4pA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-x64-gnu@16.2.3':
- resolution: {integrity: sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==}
+ '@next/swc-linux-x64-gnu@16.3.3':
+ resolution: {integrity: sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-x64-musl@16.1.3':
- resolution: {integrity: sha512-HlrDpj0v+JBIvQex1mXHq93Mht5qQmfyci+ZNwGClnAQldSfxI6h0Vupte1dSR4ueNv4q7qp5kTnmLOBIQnGow==}
+ '@next/swc-linux-x64-musl@15.5.24':
+ resolution: {integrity: sha512-kGZxM+WhkYs0276lFrMkj7PRtXT3Btp6cwvfSO/cCVLxJJttB5Ccnl2niaCgUja8HgSbEVnMHpg3FJWoOJ9e/g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
- '@next/swc-linux-x64-musl@16.2.3':
- resolution: {integrity: sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==}
+ '@next/swc-linux-x64-musl@16.3.3':
+ resolution: {integrity: sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
- '@next/swc-win32-arm64-msvc@16.1.3':
- resolution: {integrity: sha512-3gFCp83/LSduZMSIa+lBREP7+5e7FxpdBoc9QrCdmp+dapmTK9I+SLpY60Z39GDmTXSZA4huGg9WwmYbr6+WRw==}
+ '@next/swc-win32-arm64-msvc@15.5.24':
+ resolution: {integrity: sha512-jBDDkZ/qKAqkWivWDMkJSXUzbzV0QKRBKJjEHUAvSB97Hzw7NLzJ6yV56Lts/wjir7s4P31GYgpbS6ZL+hasAA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-arm64-msvc@16.2.3':
- resolution: {integrity: sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==}
+ '@next/swc-win32-arm64-msvc@16.3.3':
+ resolution: {integrity: sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.1.3':
- resolution: {integrity: sha512-1SZVfFT8zmMB+Oblrh5OKDvUo5mYQOkX2We6VGzpg7JUVZlqe4DYOFGKYZKTweSx1gbMixyO1jnFT4thU+nNHQ==}
+ '@next/swc-win32-x64-msvc@15.5.24':
+ resolution: {integrity: sha512-JqtwjvvorjacQ0spgjmUJoxySoYgPwdT1sFdQ0/zmW4iMlP2hjYlCoJIyS7o6Epb4Fug8eco3HXFoBDUCDeH7Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.2.3':
- resolution: {integrity: sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==}
+ '@next/swc-win32-x64-msvc@16.3.3':
+ resolution: {integrity: sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -13909,6 +14099,9 @@ packages:
'@swc/helpers@0.5.18':
resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==}
+ '@swc/helpers@0.5.23':
+ resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==}
+
'@swc/types@0.1.25':
resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==}
@@ -21891,9 +22084,9 @@ packages:
react: 19.2.3
react-dom: 19.2.3
- next@16.1.3:
- resolution: {integrity: sha512-gthG3TRD+E3/mA0uDQb9lqBmx1zVosq5kIwxNN6+MRNd085GzD+9VXMPUs+GGZCbZ+GDZdODUq4Pm7CTXK6ipw==}
- engines: {node: '>=20.9.0'}
+ next@15.5.24:
+ resolution: {integrity: sha512-Y+xn8EQCoC3ZbsFPyzE+tE8XOdrWeUdUF7NeXbmg9DsgAxl5UYxlsrvgVESHTyTGigoTa1bCUrxn70F5bqt0Gw==}
+ engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
@@ -21912,8 +22105,8 @@ packages:
sass:
optional: true
- next@16.2.3:
- resolution: {integrity: sha512-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA==}
+ next@16.3.3:
+ resolution: {integrity: sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -23310,6 +23503,10 @@ packages:
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
engines: {node: ^10 || ^12 || >=14}
+ postcss@8.5.23:
+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+ engines: {node: ^10 || ^12 || >=14}
+
postcss@8.5.25:
resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==}
engines: {node: ^10 || ^12 || >=14}
@@ -24578,6 +24775,15 @@ packages:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ sharp@0.35.4:
+ resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==}
+ engines: {node: '>=20.9.0'}
+ peerDependencies:
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -33003,6 +33209,11 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@emnapi/runtime@1.11.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@emnapi/runtime@1.4.5':
dependencies:
tslib: 2.8.1
@@ -34377,6 +34588,9 @@ snapshots:
'@img/colour@1.0.0': {}
+ '@img/colour@1.1.0':
+ optional: true
+
'@img/sharp-darwin-arm64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.0.4
@@ -34387,6 +34601,11 @@ snapshots:
'@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
+ '@img/sharp-darwin-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-arm64': 1.3.3
+ optional: true
+
'@img/sharp-darwin-x64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.0.4
@@ -34397,60 +34616,100 @@ snapshots:
'@img/sharp-libvips-darwin-x64': 1.2.4
optional: true
+ '@img/sharp-darwin-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.3.3
+ optional: true
+
+ '@img/sharp-freebsd-wasm32@0.35.4':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.4
+ optional: true
+
'@img/sharp-libvips-darwin-arm64@1.0.4':
optional: true
'@img/sharp-libvips-darwin-arm64@1.2.4':
optional: true
+ '@img/sharp-libvips-darwin-arm64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-darwin-x64@1.0.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.2.4':
optional: true
+ '@img/sharp-libvips-darwin-x64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-arm64@1.0.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-arm64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-arm@1.0.5':
optional: true
'@img/sharp-libvips-linux-arm@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-arm@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-ppc64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-ppc64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-riscv64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-riscv64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-s390x@1.0.4':
optional: true
'@img/sharp-libvips-linux-s390x@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-s390x@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linux-x64@1.0.4':
optional: true
'@img/sharp-libvips-linux-x64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-x64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
+ optional: true
+
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
+ optional: true
+
'@img/sharp-linux-arm64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.0.4
@@ -34461,6 +34720,11 @@ snapshots:
'@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
+ '@img/sharp-linux-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.3.3
+ optional: true
+
'@img/sharp-linux-arm@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.0.5
@@ -34471,16 +34735,31 @@ snapshots:
'@img/sharp-libvips-linux-arm': 1.2.4
optional: true
+ '@img/sharp-linux-arm@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.3.3
+ optional: true
+
'@img/sharp-linux-ppc64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-ppc64': 1.2.4
optional: true
+ '@img/sharp-linux-ppc64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-ppc64': 1.3.3
+ optional: true
+
'@img/sharp-linux-riscv64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
+ '@img/sharp-linux-riscv64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-riscv64': 1.3.3
+ optional: true
+
'@img/sharp-linux-s390x@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.0.4
@@ -34491,6 +34770,11 @@ snapshots:
'@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
+ '@img/sharp-linux-s390x@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.3.3
+ optional: true
+
'@img/sharp-linux-x64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.0.4
@@ -34501,6 +34785,11 @@ snapshots:
'@img/sharp-libvips-linux-x64': 1.2.4
optional: true
+ '@img/sharp-linux-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.3.3
+ optional: true
+
'@img/sharp-linuxmusl-arm64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.0.4
@@ -34511,6 +34800,11 @@ snapshots:
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
+ '@img/sharp-linuxmusl-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
+ optional: true
+
'@img/sharp-linuxmusl-x64@0.33.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.0.4
@@ -34521,6 +34815,11 @@ snapshots:
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
+ '@img/sharp-linuxmusl-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
+ optional: true
+
'@img/sharp-wasm32@0.33.5':
dependencies:
'@emnapi/runtime': 1.11.2
@@ -34531,21 +34830,40 @@ snapshots:
'@emnapi/runtime': 1.8.1
optional: true
+ '@img/sharp-wasm32@0.35.4':
+ dependencies:
+ '@emnapi/runtime': 1.11.3
+ optional: true
+
+ '@img/sharp-webcontainers-wasm32@0.35.4':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.4
+ optional: true
+
'@img/sharp-win32-arm64@0.34.5':
optional: true
+ '@img/sharp-win32-arm64@0.35.4':
+ optional: true
+
'@img/sharp-win32-ia32@0.33.5':
optional: true
'@img/sharp-win32-ia32@0.34.5':
optional: true
+ '@img/sharp-win32-ia32@0.35.4':
+ optional: true
+
'@img/sharp-win32-x64@0.33.5':
optional: true
'@img/sharp-win32-x64@0.34.5':
optional: true
+ '@img/sharp-win32-x64@0.35.4':
+ optional: true
+
'@inquirer/ansi@1.0.2': {}
'@inquirer/ansi@2.0.7': {}
@@ -36813,9 +37131,9 @@ snapshots:
'@tybys/wasm-util': 0.10.3
optional: true
- '@next/env@16.1.3': {}
+ '@next/env@15.5.24': {}
- '@next/env@16.2.3': {}
+ '@next/env@16.3.3': {}
'@next/eslint-plugin-next@15.4.4':
dependencies:
@@ -36825,52 +37143,52 @@ snapshots:
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@16.1.3':
+ '@next/swc-darwin-arm64@15.5.24':
optional: true
- '@next/swc-darwin-arm64@16.2.3':
+ '@next/swc-darwin-arm64@16.3.3':
optional: true
- '@next/swc-darwin-x64@16.1.3':
+ '@next/swc-darwin-x64@15.5.24':
optional: true
- '@next/swc-darwin-x64@16.2.3':
+ '@next/swc-darwin-x64@16.3.3':
optional: true
- '@next/swc-linux-arm64-gnu@16.1.3':
+ '@next/swc-linux-arm64-gnu@15.5.24':
optional: true
- '@next/swc-linux-arm64-gnu@16.2.3':
+ '@next/swc-linux-arm64-gnu@16.3.3':
optional: true
- '@next/swc-linux-arm64-musl@16.1.3':
+ '@next/swc-linux-arm64-musl@15.5.24':
optional: true
- '@next/swc-linux-arm64-musl@16.2.3':
+ '@next/swc-linux-arm64-musl@16.3.3':
optional: true
- '@next/swc-linux-x64-gnu@16.1.3':
+ '@next/swc-linux-x64-gnu@15.5.24':
optional: true
- '@next/swc-linux-x64-gnu@16.2.3':
+ '@next/swc-linux-x64-gnu@16.3.3':
optional: true
- '@next/swc-linux-x64-musl@16.1.3':
+ '@next/swc-linux-x64-musl@15.5.24':
optional: true
- '@next/swc-linux-x64-musl@16.2.3':
+ '@next/swc-linux-x64-musl@16.3.3':
optional: true
- '@next/swc-win32-arm64-msvc@16.1.3':
+ '@next/swc-win32-arm64-msvc@15.5.24':
optional: true
- '@next/swc-win32-arm64-msvc@16.2.3':
+ '@next/swc-win32-arm64-msvc@16.3.3':
optional: true
- '@next/swc-win32-x64-msvc@16.1.3':
+ '@next/swc-win32-x64-msvc@15.5.24':
optional: true
- '@next/swc-win32-x64-msvc@16.2.3':
+ '@next/swc-win32-x64-msvc@16.3.3':
optional: true
'@ngtools/webpack@22.1.5(@angular/compiler-cli@22.0.0(@angular/compiler@22.0.0)(typescript@6.0.3))(typescript@6.0.3)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(lightningcss@1.32.0)(postcss@8.5.6))':
@@ -38155,6 +38473,22 @@ snapshots:
webpack-dev-server: 5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
webpack-hot-middleware: 2.26.1
+ '@pmmmwh/react-refresh-webpack-plugin@0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))':
+ dependencies:
+ ansi-html: 0.0.9
+ core-js-pure: 3.47.0
+ error-stack-parser: 2.1.4
+ html-entities: 2.6.0
+ loader-utils: 2.0.4
+ react-refresh: 0.14.2
+ schema-utils: 4.3.3
+ source-map: 0.7.6
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+ optionalDependencies:
+ type-fest: 4.41.0
+ webpack-dev-server: 5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
+ webpack-hot-middleware: 2.26.1
+
'@polka/url@1.0.0-next.29': {}
'@popperjs/core@2.11.8': {}
@@ -40739,6 +41073,33 @@ snapshots:
- uglify-js
- webpack-cli
+ '@storybook/builder-webpack5@10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)':
+ dependencies:
+ '@storybook/core-webpack': 10.3.5(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
+ case-sensitive-paths-webpack-plugin: 2.4.0
+ cjs-module-lexer: 1.4.3
+ css-loader: 7.1.2(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ es-module-lexer: 1.7.0
+ fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.8.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ html-webpack-plugin: 5.6.5(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ magic-string: 0.30.21
+ storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ style-loader: 4.0.0(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ terser-webpack-plugin: 5.3.16(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ ts-dedent: 2.2.0
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+ webpack-dev-middleware: 6.1.3(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ webpack-hot-middleware: 2.26.1
+ webpack-virtual-modules: 0.6.2
+ optionalDependencies:
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@rspack/core'
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+ - webpack-cli
+
'@storybook/builder-webpack5@10.6.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)(storybook@10.6.0(@types/react@19.1.8)(prettier@3.7.4)(react@19.2.3))(typescript@6.0.3)':
dependencies:
'@storybook/core-webpack': 10.6.0(storybook@10.6.0(@types/react@19.1.8)(prettier@3.7.4)(react@19.2.3))
@@ -40827,7 +41188,7 @@ snapshots:
dependencies:
react: 19.2.3
- '@storybook/nextjs@10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(next@16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(type-fest@4.41.0)(typescript@5.8.2)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))':
+ '@storybook/nextjs@10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(next@15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(type-fest@4.41.0)(typescript@5.8.2)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5)
@@ -40842,33 +41203,33 @@ snapshots:
'@babel/preset-react': 7.28.5(@babel/core@7.28.5)
'@babel/preset-typescript': 7.28.5(@babel/core@7.28.5)
'@babel/runtime': 7.29.2
- '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
- '@storybook/builder-webpack5': 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
- '@storybook/preset-react-webpack': 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
+ '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)))(webpack-hot-middleware@2.26.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
+ '@storybook/builder-webpack5': 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
+ '@storybook/preset-react-webpack': 10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
'@storybook/react': 10.3.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)
'@types/semver': 7.7.1
- babel-loader: 9.2.1(@babel/core@7.28.5)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
- css-loader: 6.11.0(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ babel-loader: 9.2.1(@babel/core@7.28.5)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
+ css-loader: 6.11.0(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
image-size: 2.0.2
loader-utils: 3.3.1
- next: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
- node-polyfill-webpack-plugin: 2.0.1(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ next: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ node-polyfill-webpack-plugin: 2.0.1(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
postcss: 8.5.15
- postcss-loader: 8.2.0(postcss@8.5.15)(typescript@5.8.2)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ postcss-loader: 8.2.0(postcss@8.5.15)(typescript@5.8.2)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
react-refresh: 0.14.2
resolve-url-loader: 5.0.0
- sass-loader: 16.0.6(sass@1.101.0)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ sass-loader: 16.0.6(sass@1.101.0)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
semver: 7.7.4
storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- style-loader: 3.3.4(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15))
+ style-loader: 3.3.4(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
styled-jsx: 5.1.7(@babel/core@7.28.5)(react@19.2.3)
tsconfig-paths: 4.2.0
tsconfig-paths-webpack-plugin: 4.2.0
optionalDependencies:
typescript: 5.8.2
- webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
transitivePeerDependencies:
- '@rspack/core'
- '@swc/core'
@@ -40933,6 +41294,29 @@ snapshots:
- uglify-js
- webpack-cli
+ '@storybook/preset-react-webpack@10.3.5(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.8.2)':
+ dependencies:
+ '@storybook/core-webpack': 10.3.5(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
+ '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ '@types/semver': 7.7.1
+ magic-string: 0.30.21
+ react: 19.2.3
+ react-docgen: 7.1.1
+ react-dom: 19.2.3(react@19.2.3)
+ resolve: 1.22.11
+ semver: 7.8.5
+ storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ tsconfig-paths: 4.2.0
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+ optionalDependencies:
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - supports-color
+ - uglify-js
+ - webpack-cli
+
'@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.8.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3))':
dependencies:
debug: 4.4.3(supports-color@5.5.0)
@@ -40947,6 +41331,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.8.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))':
+ dependencies:
+ debug: 4.4.3(supports-color@5.5.0)
+ endent: 2.1.0
+ find-cache-dir: 3.3.2
+ flat-cache: 3.2.0
+ micromatch: 4.0.8
+ react-docgen-typescript: 2.4.0(typescript@5.8.2)
+ tslib: 2.8.1
+ typescript: 5.8.2
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+ transitivePeerDependencies:
+ - supports-color
+
'@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.9.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3))':
dependencies:
debug: 4.4.3(supports-color@5.5.0)
@@ -41127,6 +41525,23 @@ snapshots:
'@swc/core-win32-x64-msvc': 1.15.8
'@swc/helpers': 0.5.18
+ '@swc/core@1.15.8(@swc/helpers@0.5.23)':
+ dependencies:
+ '@swc/counter': 0.1.3
+ '@swc/types': 0.1.25
+ optionalDependencies:
+ '@swc/core-darwin-arm64': 1.15.8
+ '@swc/core-darwin-x64': 1.15.8
+ '@swc/core-linux-arm-gnueabihf': 1.15.8
+ '@swc/core-linux-arm64-gnu': 1.15.8
+ '@swc/core-linux-arm64-musl': 1.15.8
+ '@swc/core-linux-x64-gnu': 1.15.8
+ '@swc/core-linux-x64-musl': 1.15.8
+ '@swc/core-win32-arm64-msvc': 1.15.8
+ '@swc/core-win32-ia32-msvc': 1.15.8
+ '@swc/core-win32-x64-msvc': 1.15.8
+ '@swc/helpers': 0.5.23
+
'@swc/core@1.5.28(@swc/helpers@0.5.18)':
dependencies:
'@swc/counter': 0.1.3
@@ -41154,6 +41569,10 @@ snapshots:
dependencies:
tslib: 2.8.1
+ '@swc/helpers@0.5.23':
+ dependencies:
+ tslib: 2.8.1
+
'@swc/types@0.1.25':
dependencies:
'@swc/counter': 0.1.3
@@ -43681,6 +44100,13 @@ snapshots:
schema-utils: 4.3.3
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ babel-loader@9.2.1(@babel/core@7.28.5)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ '@babel/core': 7.28.5
+ find-cache-dir: 4.0.0
+ schema-utils: 4.3.3
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+
babel-plugin-istanbul@6.1.1:
dependencies:
'@babel/helper-plugin-utils': 7.29.7
@@ -45227,6 +45653,19 @@ snapshots:
optionalDependencies:
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ css-loader@6.11.0(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ icss-utils: 5.1.0(postcss@8.5.26)
+ postcss: 8.5.26
+ postcss-modules-extract-imports: 3.1.0(postcss@8.5.26)
+ postcss-modules-local-by-default: 4.2.0(postcss@8.5.26)
+ postcss-modules-scope: 3.2.1(postcss@8.5.26)
+ postcss-modules-values: 4.0.0(postcss@8.5.26)
+ postcss-value-parser: 4.2.0
+ semver: 7.8.5
+ optionalDependencies:
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+
css-loader@7.1.2(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)):
dependencies:
icss-utils: 5.1.0(postcss@8.5.15)
@@ -45240,6 +45679,19 @@ snapshots:
optionalDependencies:
webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)
+ css-loader@7.1.2(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ icss-utils: 5.1.0(postcss@8.5.15)
+ postcss: 8.5.15
+ postcss-modules-extract-imports: 3.1.0(postcss@8.5.15)
+ postcss-modules-local-by-default: 4.2.0(postcss@8.5.15)
+ postcss-modules-scope: 3.2.1(postcss@8.5.15)
+ postcss-modules-values: 4.0.0(postcss@8.5.15)
+ postcss-value-parser: 4.2.0
+ semver: 7.7.3
+ optionalDependencies:
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+
css-loader@7.1.2(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)):
dependencies:
icss-utils: 5.1.0(postcss@8.5.15)
@@ -47462,6 +47914,23 @@ snapshots:
typescript: 5.8.2
webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)
+ fork-ts-checker-webpack-plugin@9.1.0(typescript@5.8.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ chalk: 4.1.2
+ chokidar: 4.0.3
+ cosmiconfig: 8.3.6(typescript@5.8.2)
+ deepmerge: 4.3.1
+ fs-extra: 10.1.0
+ memfs: 3.5.3
+ minimatch: 10.2.4
+ node-abort-controller: 3.1.1
+ schema-utils: 3.3.0
+ semver: 7.8.5
+ tapable: 2.3.0
+ typescript: 5.8.2
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+
fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.2)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)):
dependencies:
'@babel/code-frame': 7.29.7
@@ -48399,6 +48868,16 @@ snapshots:
optionalDependencies:
webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)
+ html-webpack-plugin@5.6.5(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ '@types/html-minifier-terser': 6.1.0
+ html-minifier-terser: 6.1.0
+ lodash: 4.18.1
+ pretty-error: 4.0.0
+ tapable: 2.3.0
+ optionalDependencies:
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+
html-webpack-plugin@5.6.5(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(lightningcss@1.32.0)(postcss@8.5.6)):
dependencies:
'@types/html-minifier-terser': 6.1.0
@@ -51890,6 +52369,18 @@ snapshots:
'@swc/core': 1.15.8(@swc/helpers@0.5.18)
esbuild: 0.27.3
+ minimizer-webpack-plugin@5.6.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ jest-worker: 27.5.1
+ schema-utils: 4.3.3
+ terser: 5.49.0
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+ optionalDependencies:
+ '@swc/core': 1.15.8(@swc/helpers@0.5.23)
+ esbuild: 0.27.3
+ postcss: 8.5.15
+
minipass-collect@2.0.1:
dependencies:
minipass: 7.1.2
@@ -52092,31 +52583,30 @@ snapshots:
- supports-color
- unified
- next-themes@0.2.1(next@16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ next-themes@0.2.1(next@15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
- next: 16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
+ next: 15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
- next@16.1.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0):
+ next@15.5.24(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0):
dependencies:
- '@next/env': 16.1.3
+ '@next/env': 15.5.24
'@swc/helpers': 0.5.15
- baseline-browser-mapping: 2.9.13
- caniuse-lite: 1.0.30001769
+ caniuse-lite: 1.0.30001809
postcss: 8.4.31
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
styled-jsx: 5.1.6(@babel/core@8.0.1)(react@19.2.3)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.1.3
- '@next/swc-darwin-x64': 16.1.3
- '@next/swc-linux-arm64-gnu': 16.1.3
- '@next/swc-linux-arm64-musl': 16.1.3
- '@next/swc-linux-x64-gnu': 16.1.3
- '@next/swc-linux-x64-musl': 16.1.3
- '@next/swc-win32-arm64-msvc': 16.1.3
- '@next/swc-win32-x64-msvc': 16.1.3
+ '@next/swc-darwin-arm64': 15.5.24
+ '@next/swc-darwin-x64': 15.5.24
+ '@next/swc-linux-arm64-gnu': 15.5.24
+ '@next/swc-linux-arm64-musl': 15.5.24
+ '@next/swc-linux-x64-gnu': 15.5.24
+ '@next/swc-linux-x64-musl': 15.5.24
+ '@next/swc-win32-arm64-msvc': 15.5.24
+ '@next/swc-win32-x64-msvc': 15.5.24
'@opentelemetry/api': 1.9.0
'@playwright/test': 1.59.1
babel-plugin-react-compiler: 1.0.0
@@ -52126,32 +52616,62 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
- next@16.2.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0):
+ next@16.3.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(@types/node@20.19.27)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0):
dependencies:
- '@next/env': 16.2.3
- '@swc/helpers': 0.5.15
- baseline-browser-mapping: 2.10.24
- caniuse-lite: 1.0.30001793
- postcss: 8.4.31
+ '@next/env': 16.3.3
+ '@swc/helpers': 0.5.23
+ baseline-browser-mapping: 2.11.15
+ caniuse-lite: 1.0.30001809
+ postcss: 8.5.23
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
styled-jsx: 5.1.6(@babel/core@8.0.1)(react@19.2.3)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.2.3
- '@next/swc-darwin-x64': 16.2.3
- '@next/swc-linux-arm64-gnu': 16.2.3
- '@next/swc-linux-arm64-musl': 16.2.3
- '@next/swc-linux-x64-gnu': 16.2.3
- '@next/swc-linux-x64-musl': 16.2.3
- '@next/swc-win32-arm64-msvc': 16.2.3
- '@next/swc-win32-x64-msvc': 16.2.3
+ '@next/swc-darwin-arm64': 16.3.3
+ '@next/swc-darwin-x64': 16.3.3
+ '@next/swc-linux-arm64-gnu': 16.3.3
+ '@next/swc-linux-arm64-musl': 16.3.3
+ '@next/swc-linux-x64-gnu': 16.3.3
+ '@next/swc-linux-x64-musl': 16.3.3
+ '@next/swc-win32-arm64-msvc': 16.3.3
+ '@next/swc-win32-x64-msvc': 16.3.3
'@opentelemetry/api': 1.9.0
'@playwright/test': 1.59.1
babel-plugin-react-compiler: 1.0.0
sass: 1.101.0
- sharp: 0.34.5
+ sharp: 0.35.4(@types/node@20.19.27)
transitivePeerDependencies:
- '@babel/core'
+ - '@types/node'
+ - babel-plugin-macros
+
+ next@16.3.3(@babel/core@8.0.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.59.1)(@types/node@22.19.11)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.101.0):
+ dependencies:
+ '@next/env': 16.3.3
+ '@swc/helpers': 0.5.23
+ baseline-browser-mapping: 2.11.15
+ caniuse-lite: 1.0.30001809
+ postcss: 8.5.23
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ styled-jsx: 5.1.6(@babel/core@8.0.1)(react@19.2.3)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 16.3.3
+ '@next/swc-darwin-x64': 16.3.3
+ '@next/swc-linux-arm64-gnu': 16.3.3
+ '@next/swc-linux-arm64-musl': 16.3.3
+ '@next/swc-linux-x64-gnu': 16.3.3
+ '@next/swc-linux-x64-musl': 16.3.3
+ '@next/swc-win32-arm64-msvc': 16.3.3
+ '@next/swc-win32-x64-msvc': 16.3.3
+ '@opentelemetry/api': 1.9.0
+ '@playwright/test': 1.59.1
+ babel-plugin-react-compiler: 1.0.0
+ sass: 1.101.0
+ sharp: 0.35.4(@types/node@22.19.11)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@types/node'
- babel-plugin-macros
ng-packagr@21.2.3(@angular/compiler-cli@21.2.18(@angular/compiler@21.2.18)(typescript@5.9.3))(tailwindcss@4.2.2)(tslib@2.8.1)(typescript@5.9.3):
@@ -52498,6 +53018,35 @@ snapshots:
vm-browserify: 1.1.2
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ node-polyfill-webpack-plugin@2.0.1(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ assert: 2.1.0
+ browserify-zlib: 0.2.0
+ buffer: 6.0.3
+ console-browserify: 1.2.0
+ constants-browserify: 1.0.0
+ crypto-browserify: 3.12.1
+ domain-browser: 4.23.0
+ events: 3.3.0
+ filter-obj: 2.0.2
+ https-browserify: 1.0.0
+ os-browserify: 0.3.0
+ path-browserify: 1.0.1
+ process: 0.11.10
+ punycode: 2.3.1
+ querystring-es3: 0.2.1
+ readable-stream: 4.7.0
+ stream-browserify: 3.0.0
+ stream-http: 3.2.0
+ string_decoder: 1.3.0
+ timers-browserify: 2.0.12
+ tty-browserify: 0.0.1
+ type-fest: 2.19.0
+ url: 0.11.4
+ util: 0.12.5
+ vm-browserify: 1.1.2
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+
node-releases@2.0.27: {}
node-releases@2.0.45: {}
@@ -53976,6 +54525,17 @@ snapshots:
transitivePeerDependencies:
- typescript
+ postcss-loader@8.2.0(postcss@8.5.15)(typescript@5.8.2)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ cosmiconfig: 9.0.0(typescript@5.8.2)
+ jiti: 2.6.1
+ postcss: 8.5.15
+ semver: 7.7.3
+ optionalDependencies:
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+ transitivePeerDependencies:
+ - typescript
+
postcss-loader@8.2.0(postcss@8.5.6)(typescript@6.0.3)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)):
dependencies:
cosmiconfig: 9.0.0(typescript@6.0.3)
@@ -54227,6 +54787,12 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ postcss@8.5.23:
+ dependencies:
+ nanoid: 3.3.18
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
postcss@8.5.25:
dependencies:
nanoid: 3.3.18
@@ -55809,6 +56375,13 @@ snapshots:
sass: 1.101.0
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ sass-loader@16.0.6(sass@1.101.0)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ neo-async: 2.6.2
+ optionalDependencies:
+ sass: 1.101.0
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+
sass-loader@17.0.0(sass@1.101.0)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(lightningcss@1.32.0)(postcss@8.5.6)):
optionalDependencies:
sass: 1.101.0
@@ -56117,6 +56690,74 @@ snapshots:
'@img/sharp-win32-ia32': 0.34.5
'@img/sharp-win32-x64': 0.34.5
+ sharp@0.35.4(@types/node@20.19.27):
+ dependencies:
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.5
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.35.4
+ '@img/sharp-darwin-x64': 0.35.4
+ '@img/sharp-freebsd-wasm32': 0.35.4
+ '@img/sharp-libvips-darwin-arm64': 1.3.3
+ '@img/sharp-libvips-darwin-x64': 1.3.3
+ '@img/sharp-libvips-linux-arm': 1.3.3
+ '@img/sharp-libvips-linux-arm64': 1.3.3
+ '@img/sharp-libvips-linux-ppc64': 1.3.3
+ '@img/sharp-libvips-linux-riscv64': 1.3.3
+ '@img/sharp-libvips-linux-s390x': 1.3.3
+ '@img/sharp-libvips-linux-x64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
+ '@img/sharp-linux-arm': 0.35.4
+ '@img/sharp-linux-arm64': 0.35.4
+ '@img/sharp-linux-ppc64': 0.35.4
+ '@img/sharp-linux-riscv64': 0.35.4
+ '@img/sharp-linux-s390x': 0.35.4
+ '@img/sharp-linux-x64': 0.35.4
+ '@img/sharp-linuxmusl-arm64': 0.35.4
+ '@img/sharp-linuxmusl-x64': 0.35.4
+ '@img/sharp-webcontainers-wasm32': 0.35.4
+ '@img/sharp-win32-arm64': 0.35.4
+ '@img/sharp-win32-ia32': 0.35.4
+ '@img/sharp-win32-x64': 0.35.4
+ '@types/node': 20.19.27
+ optional: true
+
+ sharp@0.35.4(@types/node@22.19.11):
+ dependencies:
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.5
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.35.4
+ '@img/sharp-darwin-x64': 0.35.4
+ '@img/sharp-freebsd-wasm32': 0.35.4
+ '@img/sharp-libvips-darwin-arm64': 1.3.3
+ '@img/sharp-libvips-darwin-x64': 1.3.3
+ '@img/sharp-libvips-linux-arm': 1.3.3
+ '@img/sharp-libvips-linux-arm64': 1.3.3
+ '@img/sharp-libvips-linux-ppc64': 1.3.3
+ '@img/sharp-libvips-linux-riscv64': 1.3.3
+ '@img/sharp-libvips-linux-s390x': 1.3.3
+ '@img/sharp-libvips-linux-x64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
+ '@img/sharp-linux-arm': 0.35.4
+ '@img/sharp-linux-arm64': 0.35.4
+ '@img/sharp-linux-ppc64': 0.35.4
+ '@img/sharp-linux-riscv64': 0.35.4
+ '@img/sharp-linux-s390x': 0.35.4
+ '@img/sharp-linux-x64': 0.35.4
+ '@img/sharp-linuxmusl-arm64': 0.35.4
+ '@img/sharp-linuxmusl-x64': 0.35.4
+ '@img/sharp-webcontainers-wasm32': 0.35.4
+ '@img/sharp-win32-arm64': 0.35.4
+ '@img/sharp-win32-ia32': 0.35.4
+ '@img/sharp-win32-x64': 0.35.4
+ '@types/node': 22.19.11
+ optional: true
+
shebang-command@2.0.0:
dependencies:
shebang-regex: 3.0.0
@@ -56812,10 +57453,18 @@ snapshots:
dependencies:
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.15)
+ style-loader@3.3.4(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+
style-loader@4.0.0(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)):
dependencies:
webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)
+ style-loader@4.0.0(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+
style-loader@4.0.0(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)):
dependencies:
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)
@@ -57108,6 +57757,18 @@ snapshots:
'@swc/core': 1.15.8(@swc/helpers@0.5.18)
esbuild: 0.27.3
+ terser-webpack-plugin@5.3.16(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ jest-worker: 27.5.1
+ schema-utils: 4.3.3
+ serialize-javascript: 7.0.5
+ terser: 5.46.0
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+ optionalDependencies:
+ '@swc/core': 1.15.8(@swc/helpers@0.5.23)
+ esbuild: 0.27.3
+
terser-webpack-plugin@5.6.1(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -59448,6 +60109,16 @@ snapshots:
optionalDependencies:
webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)
+ webpack-dev-middleware@6.1.3(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)):
+ dependencies:
+ colorette: 2.0.20
+ memfs: 3.5.3
+ mime-types: 2.1.35
+ range-parser: 1.2.1
+ schema-utils: 4.3.3
+ optionalDependencies:
+ webpack: 5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)
+
webpack-dev-middleware@6.1.3(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)):
dependencies:
colorette: 2.0.20
@@ -59493,6 +60164,18 @@ snapshots:
optionalDependencies:
webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(postcss@8.5.6)
+ webpack-dev-middleware@7.4.5(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ colorette: 2.0.20
+ memfs: 4.51.1
+ mime-types: 3.0.2
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ schema-utils: 4.3.3
+ optionalDependencies:
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+ optional: true
+
webpack-dev-middleware@8.0.3(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3)(lightningcss@1.32.0)(postcss@8.5.6)):
dependencies:
memfs: 4.68.1
@@ -59630,6 +60313,45 @@ snapshots:
- supports-color
- utf-8-validate
+ webpack-dev-server@5.2.6(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)):
+ dependencies:
+ '@types/bonjour': 3.5.13
+ '@types/connect-history-api-fallback': 1.5.4
+ '@types/express': 4.17.25
+ '@types/express-serve-static-core': 4.19.7
+ '@types/serve-index': 1.9.4
+ '@types/serve-static': 1.15.10
+ '@types/sockjs': 0.3.36
+ '@types/ws': 8.18.1
+ ansi-html-community: 0.0.8
+ bonjour-service: 1.3.0
+ chokidar: 3.6.0
+ colorette: 2.0.20
+ compression: 1.8.1
+ connect-history-api-fallback: 2.0.0
+ express: 5.2.1
+ graceful-fs: 4.2.11
+ http-proxy-middleware: 2.0.9(@types/express@4.17.25)
+ ipaddr.js: 2.3.0
+ launch-editor: 2.14.1
+ open: 10.2.0
+ p-retry: 6.2.1
+ schema-utils: 4.3.3
+ selfsigned: 5.5.0
+ serve-index: 1.9.1
+ sockjs: 0.3.24
+ spdy: 4.0.2
+ webpack-dev-middleware: 7.4.5(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
+ ws: 8.19.0
+ optionalDependencies:
+ webpack: 5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)
+ transitivePeerDependencies:
+ - bufferutil
+ - debug
+ - supports-color
+ - utf-8-validate
+ optional: true
+
webpack-hot-middleware@2.26.1:
dependencies:
ansi-html-community: 0.0.8
@@ -59695,6 +60417,38 @@ snapshots:
- esbuild
- uglify-js
+ webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3):
+ dependencies:
+ '@types/eslint-scope': 3.7.7
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/wasm-edit': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+ acorn: 8.16.0
+ acorn-import-phases: 1.0.4(acorn@8.16.0)
+ browserslist: 4.28.8
+ chrome-trace-event: 1.0.4
+ enhanced-resolve: 5.19.0
+ es-module-lexer: 2.0.0
+ eslint-scope: 5.1.1
+ events: 3.3.0
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+ json-parse-even-better-errors: 2.3.1
+ loader-runner: 4.3.1
+ mime-types: 2.1.35
+ neo-async: 2.6.2
+ schema-utils: 4.3.3
+ tapable: 2.3.0
+ terser-webpack-plugin: 5.3.16(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(webpack@5.105.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3))
+ watchpack: 2.5.2
+ webpack-sources: 3.3.3
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+
webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.27.3):
dependencies:
'@types/estree': 1.0.8
@@ -59950,6 +60704,42 @@ snapshots:
- postcss
- uglify-js
+ webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15):
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/wasm-edit': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+ acorn: 8.16.0
+ browserslist: 4.28.8
+ chrome-trace-event: 1.0.4
+ enhanced-resolve: 5.24.5
+ es-module-lexer: 2.3.2
+ eslint-scope: 5.1.1
+ events: 3.3.0
+ graceful-fs: 4.2.11
+ mime-db: 1.54.0
+ minimizer-webpack-plugin: 5.6.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.27.3)(postcss@8.5.15))
+ neo-async: 2.6.2
+ schema-utils: 4.3.3
+ tapable: 2.3.3
+ watchpack: 2.5.2
+ webpack-sources: 3.5.1
+ transitivePeerDependencies:
+ - '@minify-html/node'
+ - '@swc/core'
+ - '@swc/css'
+ - '@swc/html'
+ - clean-css
+ - cssnano
+ - csso
+ - esbuild
+ - html-minifier-terser
+ - lightningcss
+ - postcss
+ - uglify-js
+
websocket-driver@0.7.4:
dependencies:
http-parser-js: 0.5.10
diff --git a/release.config.json b/release.config.json
index b541f2ef7d..f1a2eae754 100644
--- a/release.config.json
+++ b/release.config.json
@@ -6,6 +6,7 @@
"@copilotkit/a2ui-renderer",
"@copilotkit/agentcore-runner",
"@copilotkit/core",
+ "@copilotkit/mcp-apps-renderer",
"@copilotkit/react-core",
"@copilotkit/react-native",
"@copilotkit/react-textarea",
diff --git a/scripts/release/lib/build-release-notification.wrapper.test.ts b/scripts/release/lib/build-release-notification.wrapper.test.ts
index 33b07aac38..5d3b833aa7 100644
--- a/scripts/release/lib/build-release-notification.wrapper.test.ts
+++ b/scripts/release/lib/build-release-notification.wrapper.test.ts
@@ -145,10 +145,10 @@ describe("resolvePackageCountSafe", () => {
});
it("returns the real package count for the monorepo scope (drift guard)", () => {
- // Pins the actual count from release.config.json (16). If the package set
+ // Pins the actual count from release.config.json (17). If the package set
// drifts, this catches the staleness of the hardcoded "16 packages"
// assertions in build-release-notification.test.ts.
- expect(resolvePackageCountSafe("monorepo")).toBe(16);
+ expect(resolvePackageCountSafe("monorepo")).toBe(17);
});
it("returns the real package count for the shared Channels scope (drift guard)", () => {
diff --git a/scripts/release/public-api/manifest.v1.json b/scripts/release/public-api/manifest.v1.json
index fcf7f063c9..75f9afa734 100644
--- a/scripts/release/public-api/manifest.v1.json
+++ b/scripts/release/public-api/manifest.v1.json
@@ -167,7 +167,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"provenance": [
{
@@ -989,7 +989,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"provenance": [
{
@@ -1017,6 +1017,90 @@
}
}
},
+ {
+ "name": "@copilotkit/mcp-apps-renderer",
+ "version": "1.71.0",
+ "sourceDirectory": "packages/mcp-apps-renderer",
+ "entrypoints": [
+ {
+ "importPath": "@copilotkit/mcp-apps-renderer",
+ "exportKey": ".",
+ "kind": "code",
+ "conditions": {
+ "import": {
+ "types": "./dist/index.d.mts",
+ "default": "./dist/index.mjs"
+ }
+ },
+ "provenance": {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "exports[\".\"]"
+ }
+ },
+ {
+ "importPath": "@copilotkit/mcp-apps-renderer/activity",
+ "exportKey": "./activity",
+ "kind": "code",
+ "conditions": {
+ "import": {
+ "types": "./dist/activity.d.mts",
+ "default": "./dist/activity.mjs"
+ },
+ "require": {
+ "types": "./dist/activity.d.cts",
+ "default": "./dist/activity.cjs"
+ }
+ },
+ "provenance": {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "exports[\"./activity\"]"
+ }
+ },
+ {
+ "importPath": "@copilotkit/mcp-apps-renderer/package.json",
+ "exportKey": "./package.json",
+ "kind": "metadata",
+ "conditions": "./package.json",
+ "provenance": {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "exports[\"./package.json\"]"
+ }
+ }
+ ],
+ "compatibility": {
+ "peerDependencies": {
+ "@ag-ui/client": "0.0.59",
+ "zod": ">=3.25"
+ },
+ "provenance": [
+ {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "peerDependencies"
+ }
+ ]
+ },
+ "provenance": {
+ "name": {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "name"
+ },
+ "version": {
+ "kind": "package-json",
+ "path": "packages/mcp-apps-renderer/package.json",
+ "selector": "version"
+ },
+ "releaseScope": {
+ "kind": "release-config",
+ "path": "release.config.json",
+ "selector": "scopes.monorepo.packages"
+ }
+ }
+ },
{
"name": "@copilotkit/react-core",
"version": "1.71.1",
@@ -1103,7 +1187,6 @@
],
"compatibility": {
"peerDependencies": {
- "@modelcontextprotocol/sdk": "^1.29.0",
"react": "^18 || ^19 || ^19.0.0-rc",
"react-dom": "^18 || ^19 || ^19.0.0-rc",
"zod": ">=3.25"
@@ -1587,6 +1670,9 @@
}
],
"compatibility": {
+ "engines": {
+ "node": ">=20"
+ },
"peerDependencies": {
"@anthropic-ai/sdk": ">=0.57.0",
"@langchain/aws": ">=0.1.9",
@@ -1611,6 +1697,11 @@
"openai"
],
"provenance": [
+ {
+ "kind": "package-json",
+ "path": "packages/runtime/package.json",
+ "selector": "engines"
+ },
{
"kind": "package-json",
"path": "packages/runtime/package.json",
@@ -1917,7 +2008,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"peerDependencies": {
"better-sqlite3": "^12.2.0"
@@ -1994,7 +2085,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"peerDependencies": {
"@copilotkit/runtime": "workspace:*"
@@ -2100,7 +2191,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"peerDependencies": {
"vue": ">=3.3.0"
@@ -2195,7 +2286,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"peerDependencies": {
"lit": "^3.3.2"
@@ -2264,7 +2355,7 @@
],
"compatibility": {
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"provenance": [
{
diff --git a/showcase/shell-docs/src/content/docs/cookbook/oracle-agent-spec-memory.mdx b/showcase/shell-docs/src/content/docs/cookbook/oracle-agent-spec-memory.mdx
index 02bdaf1990..048985abbc 100644
--- a/showcase/shell-docs/src/content/docs/cookbook/oracle-agent-spec-memory.mdx
+++ b/showcase/shell-docs/src/content/docs/cookbook/oracle-agent-spec-memory.mdx
@@ -49,7 +49,7 @@ the current conversation.
## Prerequisites
-- **Python 3.12** (required — `oracleagentmemory` ships a cp312 wheel), [`uv`](https://docs.astral.sh/uv/), Node.js 18+
+- **Python 3.12** (required — `oracleagentmemory` ships a cp312 wheel), [`uv`](https://docs.astral.sh/uv/), Node.js 20+
- Docker (for the local Oracle AI Database) or your own Oracle AI Database
- `OPENAI_API_KEY` (defaults use OpenAI via litellm)
diff --git a/showcase/shell-docs/src/content/docs/deploy/aws-lambda.mdx b/showcase/shell-docs/src/content/docs/deploy/aws-lambda.mdx
index 46e08efa54..eece5f7956 100644
--- a/showcase/shell-docs/src/content/docs/deploy/aws-lambda.mdx
+++ b/showcase/shell-docs/src/content/docs/deploy/aws-lambda.mdx
@@ -26,7 +26,7 @@ The handler code below is the same for both streaming paths; only the event shap
## Function URL with response streaming
-Response streaming requires three things: a Function URL with its invoke mode set to `RESPONSE_STREAM`, a handler wrapped in `awslambda.streamifyResponse`, and a Node.js managed runtime (Node.js 18 or later).
+Response streaming requires three things: a Function URL with its invoke mode set to `RESPONSE_STREAM`, a handler wrapped in `awslambda.streamifyResponse`, and a Node.js managed runtime of version 20 or later. AWS supports response streaming from Node.js 18, but `@copilotkit/runtime` requires Node.js 20.
### 1. The handler
diff --git a/showcase/shell-docs/src/content/snippets/langgraph-platform-deployment-tabs.mdx b/showcase/shell-docs/src/content/snippets/langgraph-platform-deployment-tabs.mdx
index 813bc05e8d..a543df4191 100644
--- a/showcase/shell-docs/src/content/snippets/langgraph-platform-deployment-tabs.mdx
+++ b/showcase/shell-docs/src/content/snippets/langgraph-platform-deployment-tabs.mdx
@@ -24,7 +24,7 @@ import { Tab } from "../components/react/tabs";
```
```bash
- # For TypeScript with Node 18 or above
+ # For TypeScript with Node 20 or above
npx @langchain/langgraph-cli dev --host localhost --port 8000
```