mirror of
https://github.com/penpot/penpot.git
synced 2026-05-24 17:33:41 +00:00
✨ Bound MCP memory consumption by limiting parallel exports & response size (#9748)
* ✨ Bound the size of plugin task responses When using the integrated remote MCP server, bound response size. All responses are passed to LLMs, which themselves impose bounds. This is a measure to bound memory usage in the centrally provided MCP server. GitHub #9493 * ✨ Bound parallelism in ExportShapeTool Use an integer semaphore to bound parallel requests to this memory-intensive tool, thus bounding memory usage. GitHub #9493 * ✨ Add (manual) integration test script for ExportShapeTool parallelism Add dependency tsx to facilitate executions. GitHub #9493 * ✨ Make number of parallel export requests configurable in ExportShapeTool Use env var PENPOT_MCP_EXPORT_SHAPE_MAX_PARALLEL_REQUESTS to configure the maximum number of requests in multi-user mode (default 0, no limit).
This commit is contained in:
parent
6be4f157d6
commit
14b53ecfec
@ -264,14 +264,15 @@ The Penpot MCP server can be configured using environment variables.
|
|||||||
|
|
||||||
### Server Configuration
|
### Server Configuration
|
||||||
|
|
||||||
| Environment Variable | Description | Default |
|
| Environment Variable | Description | Default |
|
||||||
|------------------------------------|----------------------------------------------------------------------------|--------------|
|
|--------------------------------------------------|----------------------------------------------------------------------------|----------------|
|
||||||
| `PENPOT_MCP_SERVER_HOST` | Address on which the MCP server listens (binds to) | `localhost` |
|
| `PENPOT_MCP_SERVER_HOST` | Address on which the MCP server listens (binds to) | `localhost` |
|
||||||
| `PENPOT_MCP_SERVER_PORT` | Port for the HTTP/SSE server | `4401` |
|
| `PENPOT_MCP_SERVER_PORT` | Port for the HTTP/SSE server | `4401` |
|
||||||
| `PENPOT_MCP_WEBSOCKET_PORT` | Port for the WebSocket server (plugin connection) | `4402` |
|
| `PENPOT_MCP_WEBSOCKET_PORT` | Port for the WebSocket server (plugin connection) | `4402` |
|
||||||
| `PENPOT_MCP_REPL_PORT` | Port for the REPL server (development/debugging) | `4403` |
|
| `PENPOT_MCP_REPL_PORT` | Port for the REPL server (development/debugging) | `4403` |
|
||||||
| `PENPOT_MCP_REMOTE_MODE` | Enable remote mode (disables file system access). Set to `true` to enable. | `false` |
|
| `PENPOT_MCP_REMOTE_MODE` | Enable remote mode (disables file system access). Set to `true` to enable. | `false` |
|
||||||
| `PENPOT_MCP_DEVENV` | Enable Penpot development environment tools. Set to `true` to enable. | `false` |
|
| `PENPOT_MCP_DEVENV` | Enable Penpot development environment tools. Set to `true` to enable. | `false` |
|
||||||
|
| `PENPOT_MCP_EXPORT_SHAPE_MAX_PARALLEL_REQUESTS` | Maximum number of parallel export shape requests (multi-user mode only). | `0` (no limit) |
|
||||||
|
|
||||||
### Logging Configuration
|
### Logging Configuration
|
||||||
|
|
||||||
|
|||||||
@ -24,8 +24,10 @@ export class Task<TParams = any> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create response object
|
||||||
const response = {
|
const response = {
|
||||||
type: "task-response",
|
type: "task-response",
|
||||||
|
// NOTE: This inner response schema also constructed in main.ts/sendTaskResponse.
|
||||||
response: {
|
response: {
|
||||||
id: this.requestId,
|
id: this.requestId,
|
||||||
success: success,
|
success: success,
|
||||||
|
|||||||
@ -1,12 +1,29 @@
|
|||||||
import "./style.css";
|
import "./style.css";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the maximum allowed size for task responses sent back to the MCP server in the integrated remote MCP mode.
|
||||||
|
* This bounds the JSON response size.
|
||||||
|
* Note that in the remote MCP case, responses are transferred to LLMs (not the file system) and LLMs have
|
||||||
|
* size limitations. This serves to bound the size of returned images in particular.
|
||||||
|
* Too many overly large simultaneous responses can cause OOM issues in the MCP server, so this contributes
|
||||||
|
* to bounding memory usage in the centrally provided MCP server.
|
||||||
|
*/
|
||||||
|
const MAX_TASK_RESPONSE_SIZE_REMOTE_MCP = 15_000_000;
|
||||||
|
|
||||||
// get the current theme from the URL
|
// get the current theme from the URL
|
||||||
const searchParams = new URLSearchParams(window.location.hash.split("?")[1]);
|
const searchParams = new URLSearchParams(window.location.hash.split("?")[1]);
|
||||||
document.body.dataset.theme = searchParams.get("theme") ?? "light";
|
document.body.dataset.theme = searchParams.get("theme") ?? "light";
|
||||||
|
|
||||||
// WebSocket connection management
|
// WebSocket connection to the MCP server
|
||||||
let ws: WebSocket | null = null;
|
let ws: WebSocket | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* indicates whether the plugin is running with the Penpot-integrated remote MCP server enabled
|
||||||
|
* (as opposed to a local server used with the explicitly loaded plugin);
|
||||||
|
* set via the "mcp-mode" message sent by plugin.ts on initialization
|
||||||
|
*/
|
||||||
|
let isIntegratedRemoteMcp = false;
|
||||||
|
|
||||||
const statusPill = document.getElementById("connection-status") as HTMLElement;
|
const statusPill = document.getElementById("connection-status") as HTMLElement;
|
||||||
const statusText = document.getElementById("status-text") as HTMLElement;
|
const statusText = document.getElementById("status-text") as HTMLElement;
|
||||||
const currentTaskEl = document.getElementById("current-task") as HTMLElement;
|
const currentTaskEl = document.getElementById("current-task") as HTMLElement;
|
||||||
@ -79,7 +96,22 @@ function updateExecutedCode(code: string | null): void {
|
|||||||
*/
|
*/
|
||||||
function sendTaskResponse(response: any): void {
|
function sendTaskResponse(response: any): void {
|
||||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(JSON.stringify(response));
|
let responseString = JSON.stringify(response);
|
||||||
|
if (isIntegratedRemoteMcp && responseString.length > MAX_TASK_RESPONSE_SIZE_REMOTE_MCP) {
|
||||||
|
const errorMessage = `Serialised response size (${responseString.length}) exceeds maximum of ${MAX_TASK_RESPONSE_SIZE_REMOTE_MCP}.`;
|
||||||
|
console.warn(
|
||||||
|
errorMessage +
|
||||||
|
" [integrated remote MCP mode restriction]; sending error response instead; original response:",
|
||||||
|
response
|
||||||
|
);
|
||||||
|
response = {
|
||||||
|
id: response.id,
|
||||||
|
success: false,
|
||||||
|
error: errorMessage,
|
||||||
|
};
|
||||||
|
responseString = JSON.stringify(response);
|
||||||
|
}
|
||||||
|
ws.send(responseString);
|
||||||
console.log("Sent response to MCP server:", response);
|
console.log("Sent response to MCP server:", response);
|
||||||
} else {
|
} else {
|
||||||
console.error("WebSocket not connected, cannot send response");
|
console.error("WebSocket not connected, cannot send response");
|
||||||
@ -176,6 +208,9 @@ disconnectBtn?.addEventListener("click", () => {
|
|||||||
|
|
||||||
// Listen plugin.ts messages
|
// Listen plugin.ts messages
|
||||||
window.addEventListener("message", (event) => {
|
window.addEventListener("message", (event) => {
|
||||||
|
if (event.data.type === "mcp-mode") {
|
||||||
|
isIntegratedRemoteMcp = event.data.integratedRemoteMcp;
|
||||||
|
}
|
||||||
if (event.data.type === "start-server") {
|
if (event.data.type === "start-server") {
|
||||||
connectToMcpServer(event.data.url, event.data.token);
|
connectToMcpServer(event.data.url, event.data.token);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler";
|
import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler";
|
||||||
import { Task, TaskHandler } from "./TaskHandler";
|
import { Task, TaskHandler } from "./TaskHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* indicates whether the plugin is running in an environment with the Penpot-integrated remote MCP server
|
||||||
|
* enabled (as opposed to a local server used with the explicitly loaded plugin)
|
||||||
|
*/
|
||||||
|
const isIntegratedRemoteMcp = !!mcp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the major.minor.patch prefix from a version string.
|
* Extracts the major.minor.patch prefix from a version string.
|
||||||
*
|
*
|
||||||
@ -23,12 +29,17 @@ const taskHandlers: TaskHandler[] = [new ExecuteCodeTaskHandler()];
|
|||||||
penpot.ui.open("Penpot MCP Plugin", `?theme=${penpot.theme}`, {
|
penpot.ui.open("Penpot MCP Plugin", `?theme=${penpot.theme}`, {
|
||||||
width: 236,
|
width: 236,
|
||||||
height: 210,
|
height: 210,
|
||||||
hidden: !!mcp,
|
hidden: isIntegratedRemoteMcp,
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
// Register message handlers
|
// Register message handlers
|
||||||
penpot.ui.onMessage<string | { id: string; type?: string; status?: string; task: string; params: any }>((message) => {
|
penpot.ui.onMessage<string | { id: string; type?: string; status?: string; task: string; params: any }>((message) => {
|
||||||
if (typeof message === "object" && message.type === "ui-initialized") {
|
if (typeof message === "object" && message.type === "ui-initialized") {
|
||||||
|
// Inform the UI about the operating mode
|
||||||
|
penpot.ui.sendMessage({
|
||||||
|
type: "mcp-mode",
|
||||||
|
integratedRemoteMcp: isIntegratedRemoteMcp,
|
||||||
|
});
|
||||||
// Check Penpot version compatibility
|
// Check Penpot version compatibility
|
||||||
const penpotVersionPrefix = penpot.version ? extractVersionPrefix(penpot.version) : "<2.15"; // pre-2.15 versions don't have version info
|
const penpotVersionPrefix = penpot.version ? extractVersionPrefix(penpot.version) : "<2.15"; // pre-2.15 versions don't have version info
|
||||||
const mcpVersionPrefix = extractVersionPrefix(PENPOT_MCP_VERSION);
|
const mcpVersionPrefix = extractVersionPrefix(PENPOT_MCP_VERSION);
|
||||||
@ -42,7 +53,7 @@ penpot.ui.onMessage<string | { id: string; type?: string; status?: string; task:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Initiate connection to remote MCP server (if enabled)
|
// Initiate connection to remote MCP server (if enabled)
|
||||||
if (mcp) {
|
if (isIntegratedRemoteMcp) {
|
||||||
penpot.ui.sendMessage({
|
penpot.ui.sendMessage({
|
||||||
type: "start-server",
|
type: "start-server",
|
||||||
url: mcp?.getServerUrl(),
|
url: mcp?.getServerUrl(),
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
"start:multi-user": "node dist/index.js --multi-user",
|
"start:multi-user": "node dist/index.js --multi-user",
|
||||||
"start:dev": "node --import ts-node/register src/index.ts",
|
"start:dev": "node --import ts-node/register src/index.ts",
|
||||||
"start:dev:multi-user": "node --loader ts-node/esm src/index.ts --multi-user",
|
"start:dev:multi-user": "node --loader ts-node/esm src/index.ts --multi-user",
|
||||||
|
"test:integration:export-sema": "tsx scripts/integration-test-export-image-semaphore.ts",
|
||||||
"types:check": "tsc --noEmit",
|
"types:check": "tsc --noEmit",
|
||||||
"clean": "rm -rf dist/"
|
"clean": "rm -rf dist/"
|
||||||
},
|
},
|
||||||
@ -40,14 +41,15 @@
|
|||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"@penpot/mcp-common": "workspace:../common",
|
"@penpot/mcp-common": "workspace:../common",
|
||||||
"@types/express": "^4.17.0",
|
"@types/express": "^4.17.0",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"@types/ws": "^8.5.10",
|
"@types/ws": "^8.5.10",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
|
"tsx": "^4.22.3",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
|
|||||||
@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* One-off integration test for the parallelism bound around image exports.
|
||||||
|
*
|
||||||
|
* Setup:
|
||||||
|
* - Stubs ExportShapeTool.exportImage to sleep SLEEP_MS instead of doing real work,
|
||||||
|
* so no actual plugin connection is needed.
|
||||||
|
* - Replaces the static parallelism semaphore with one of size N.
|
||||||
|
* - Starts a PenpotMcpServer in multi-user mode on three random free ports.
|
||||||
|
* - Fires M > N parallel MCP clients that each call the export_shape tool.
|
||||||
|
*
|
||||||
|
* Expectations (observed manually from the server's console output):
|
||||||
|
* - "Semaphore 'ExportShapeTool' saturated; request queued (k waiting)" lines appear
|
||||||
|
* at INFO level (at least M - N of them).
|
||||||
|
* - All M tool calls return successfully.
|
||||||
|
* - Total elapsed wall-clock time is approximately ceil(M / N) * SLEEP_MS.
|
||||||
|
*
|
||||||
|
* Invoke from packages/server with:
|
||||||
|
* pnpm run test:integration:export
|
||||||
|
*/
|
||||||
|
import * as net from "node:net";
|
||||||
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||||
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
||||||
|
|
||||||
|
import { PenpotMcpServer } from "../src/PenpotMcpServer";
|
||||||
|
import { ExportShapeTool } from "../src/tools/ExportShapeTool";
|
||||||
|
import { TextResponse } from "../src/ToolResponse";
|
||||||
|
import { Semaphore } from "../src/utils/Semaphore";
|
||||||
|
|
||||||
|
// === parameters ===
|
||||||
|
|
||||||
|
const N = 3;
|
||||||
|
const M = 6;
|
||||||
|
const SLEEP_MS = 5_000;
|
||||||
|
|
||||||
|
// === helpers ===
|
||||||
|
|
||||||
|
async function findFreePort(): Promise<number> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const srv = net.createServer();
|
||||||
|
srv.unref();
|
||||||
|
srv.on("error", reject);
|
||||||
|
srv.listen(0, "127.0.0.1", () => {
|
||||||
|
const port = (srv.address() as net.AddressInfo).port;
|
||||||
|
srv.close(() => resolve(port));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function callExportShape(url: URL, idx: number): Promise<unknown> {
|
||||||
|
const client = new Client({ name: `integration-test-client-${idx}`, version: "0.0.0" });
|
||||||
|
const transport = new StreamableHTTPClientTransport(url);
|
||||||
|
await client.connect(transport);
|
||||||
|
try {
|
||||||
|
return await client.callTool({
|
||||||
|
name: "export_shape",
|
||||||
|
arguments: { shapeId: "selection" },
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === main ===
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
// dynamic ports must be set before PenpotMcpServer is constructed
|
||||||
|
const httpPort = await findFreePort();
|
||||||
|
process.env.PENPOT_MCP_SERVER_HOST = "127.0.0.1";
|
||||||
|
process.env.PENPOT_MCP_SERVER_PORT = String(httpPort);
|
||||||
|
process.env.PENPOT_MCP_WEBSOCKET_PORT = String(await findFreePort());
|
||||||
|
process.env.PENPOT_MCP_REPL_PORT = String(await findFreePort());
|
||||||
|
|
||||||
|
// shrink the gate and stub the worker
|
||||||
|
(ExportShapeTool as any).parallelismSemaphore = new Semaphore("ExportShapeTool", N);
|
||||||
|
(ExportShapeTool.prototype as any).exportImage = async (): Promise<TextResponse> => {
|
||||||
|
await new Promise((r) => setTimeout(r, SLEEP_MS));
|
||||||
|
return new TextResponse("stubbed export");
|
||||||
|
};
|
||||||
|
|
||||||
|
const server = new PenpotMcpServer(/* isMultiUser */ true);
|
||||||
|
await server.start();
|
||||||
|
|
||||||
|
console.log(`\n=== integration test: N=${N} permits, M=${M} clients, sleep=${SLEEP_MS}ms ===\n`);
|
||||||
|
|
||||||
|
// fire M parallel tool calls, each via its own MCP session with a distinct userToken
|
||||||
|
const start = Date.now();
|
||||||
|
const results = await Promise.allSettled(
|
||||||
|
Array.from({ length: M }, (_, i) =>
|
||||||
|
callExportShape(new URL(`http://127.0.0.1:${httpPort}/mcp?userToken=test-token-${i}`), i)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const elapsed = Date.now() - start;
|
||||||
|
|
||||||
|
await server.stop();
|
||||||
|
|
||||||
|
// report
|
||||||
|
const failures = results.map((r, i) => ({ r, i })).filter(({ r }) => r.status === "rejected");
|
||||||
|
|
||||||
|
console.log(`\n=== results ===`);
|
||||||
|
console.log(` elapsed: ${elapsed}ms (expected ~${Math.ceil(M / N) * SLEEP_MS}ms)`);
|
||||||
|
console.log(` succeeded: ${M - failures.length}/${M}`);
|
||||||
|
if (failures.length > 0) {
|
||||||
|
console.log(` failures:`);
|
||||||
|
for (const { r, i } of failures) {
|
||||||
|
console.log(` [${i}] ${(r as PromiseRejectedResult).reason}`);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log(`\nAll ${M} tool calls succeeded. Scroll up to verify saturation log lines.\n`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error("Integration test crashed:", err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@ -1,10 +1,12 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Tool } from "../Tool";
|
import { Tool } from "../Tool";
|
||||||
import { ImageContent, PNGImageContent, PNGResponse, TextContent, TextResponse, ToolResponse } from "../ToolResponse";
|
import { ImageContent, PNGResponse, TextContent, TextResponse, ToolResponse } from "../ToolResponse";
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { PenpotMcpServer } from "../PenpotMcpServer";
|
import { PenpotMcpServer } from "../PenpotMcpServer";
|
||||||
import { ExecuteCodePluginTask } from "../tasks/ExecuteCodePluginTask";
|
import { ExecuteCodePluginTask } from "../tasks/ExecuteCodePluginTask";
|
||||||
|
import { createLogger } from "../logger";
|
||||||
import { FileUtils } from "../utils/FileUtils";
|
import { FileUtils } from "../utils/FileUtils";
|
||||||
|
import { Semaphore } from "../utils/Semaphore";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +51,38 @@ export class ExportShapeArgs {
|
|||||||
* Tool for executing JavaScript code in the Penpot plugin context
|
* Tool for executing JavaScript code in the Penpot plugin context
|
||||||
*/
|
*/
|
||||||
export class ExportShapeTool extends Tool<ExportShapeArgs> {
|
export class ExportShapeTool extends Tool<ExportShapeArgs> {
|
||||||
|
/**
|
||||||
|
* Maximum number of image-export operations that may run concurrently in multi-user mode.
|
||||||
|
* Configurable via the PENPOT_MCP_EXPORT_SHAPE_MAX_PARALLEL_REQUESTS environment variable;
|
||||||
|
* defaults to 0, meaning no limit.
|
||||||
|
*
|
||||||
|
* When set to a positive value (and combined with the plugin-side per-response cap
|
||||||
|
* MAX_TASK_RESPONSE_SIZE_REMOTE_MCP, ~15 MB JSON), this caps the in-flight memory
|
||||||
|
* footprint of image exports at roughly N x cap on the centrally hosted MCP server.
|
||||||
|
*/
|
||||||
|
private static readonly MAX_PARALLEL_EXPORTS = parseInt(
|
||||||
|
process.env.PENPOT_MCP_EXPORT_SHAPE_MAX_PARALLEL_REQUESTS ?? "0",
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gates concurrent export operations across all tool instances (one per session in
|
||||||
|
* multi-user mode). Static because instances are per-session, but the bound has to
|
||||||
|
* apply across the whole process. Permits beyond the maximum queue in FIFO order.
|
||||||
|
* Undefined when MAX_PARALLEL_EXPORTS is non-positive, indicating no limit.
|
||||||
|
*/
|
||||||
|
private static readonly parallelismSemaphore: Semaphore | undefined =
|
||||||
|
ExportShapeTool.MAX_PARALLEL_EXPORTS > 0
|
||||||
|
? new Semaphore("ExportShapeTool", ExportShapeTool.MAX_PARALLEL_EXPORTS)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
static {
|
||||||
|
createLogger("ExportShapeTool").info(
|
||||||
|
"Max parallel exports (multi-user mode): %d (0 = unbounded)",
|
||||||
|
ExportShapeTool.MAX_PARALLEL_EXPORTS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new ExecuteCode tool instance.
|
* Creates a new ExecuteCode tool instance.
|
||||||
*
|
*
|
||||||
@ -79,6 +113,25 @@ export class ExportShapeTool extends Tool<ExportShapeArgs> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async executeCore(args: ExportShapeArgs): Promise<ToolResponse> {
|
protected async executeCore(args: ExportShapeArgs): Promise<ToolResponse> {
|
||||||
|
// bound concurrent exports in multi-user mode to keep peak server memory under control;
|
||||||
|
// in single-user mode (or when no limit is configured) the gate is irrelevant
|
||||||
|
// and the export runs directly
|
||||||
|
if (this.mcpServer.isMultiUserMode() && ExportShapeTool.parallelismSemaphore) {
|
||||||
|
return ExportShapeTool.parallelismSemaphore.withPermit(() => this.exportImage(args));
|
||||||
|
} else {
|
||||||
|
return this.exportImage(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual image export: requests the image via the plugin and either
|
||||||
|
* returns it as a tool response or saves it to the requested file path. The bulk
|
||||||
|
* of the memory pressure (parsed plugin response, decoded image buffer, optional
|
||||||
|
* re-encoding via sharp) lives here, which is why executeCore gates the call.
|
||||||
|
*
|
||||||
|
* @param args - the validated tool arguments
|
||||||
|
*/
|
||||||
|
private async exportImage(args: ExportShapeArgs): Promise<ToolResponse> {
|
||||||
// check arguments
|
// check arguments
|
||||||
if (args.filePath) {
|
if (args.filePath) {
|
||||||
FileUtils.checkPathIsAbsolute(args.filePath);
|
FileUtils.checkPathIsAbsolute(args.filePath);
|
||||||
|
|||||||
69
mcp/packages/server/src/utils/Semaphore.ts
Normal file
69
mcp/packages/server/src/utils/Semaphore.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { createLogger } from "../logger";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counting semaphore for bounding the parallelism of asynchronous operations.
|
||||||
|
*
|
||||||
|
* Calls in excess of the configured maximum are queued in FIFO order and
|
||||||
|
* proceed once an earlier holder has released its permit.
|
||||||
|
*/
|
||||||
|
export class Semaphore {
|
||||||
|
private static readonly logger = createLogger("Semaphore");
|
||||||
|
|
||||||
|
private available: number;
|
||||||
|
private readonly waiters: Array<() => void> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name - identifier used in log messages so the source of contention is recognisable
|
||||||
|
* @param maxConcurrent - the maximum number of permits that may be held simultaneously
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly name: string,
|
||||||
|
maxConcurrent: number
|
||||||
|
) {
|
||||||
|
if (maxConcurrent < 1) {
|
||||||
|
throw new Error(`maxConcurrent must be at least 1; got ${maxConcurrent}`);
|
||||||
|
}
|
||||||
|
this.available = maxConcurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquires a permit, runs the given function, and releases the permit when it
|
||||||
|
* settles - including on rejection. Queues if no permit is currently available.
|
||||||
|
*
|
||||||
|
* @param fn - the function to run while holding the permit
|
||||||
|
* @returns the value returned by fn
|
||||||
|
*/
|
||||||
|
public async withPermit<T>(fn: () => Promise<T>): Promise<T> {
|
||||||
|
await this.acquire();
|
||||||
|
try {
|
||||||
|
return await fn();
|
||||||
|
} finally {
|
||||||
|
this.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private acquire(): Promise<void> {
|
||||||
|
if (this.available > 0) {
|
||||||
|
this.available--;
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
this.waiters.push(resolve);
|
||||||
|
Semaphore.logger.info(
|
||||||
|
"Semaphore '%s' saturated; request queued (%d waiting)",
|
||||||
|
this.name,
|
||||||
|
this.waiters.length
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private release(): void {
|
||||||
|
const next = this.waiters.shift();
|
||||||
|
if (next !== undefined) {
|
||||||
|
// pass the permit directly to the next waiter without touching `available`
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
this.available++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
293
mcp/pnpm-lock.yaml
generated
293
mcp/pnpm-lock.yaml
generated
@ -38,10 +38,10 @@ importers:
|
|||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^7.0.8
|
specifier: ^7.0.8
|
||||||
version: 7.3.1(@types/node@20.19.30)
|
version: 7.3.1(@types/node@20.19.30)(tsx@4.22.3)
|
||||||
vite-live-preview:
|
vite-live-preview:
|
||||||
specifier: ^0.3.2
|
specifier: ^0.3.2
|
||||||
version: 0.3.2(vite@7.3.1(@types/node@20.19.30))
|
version: 0.3.2(vite@7.3.1(@types/node@20.19.30)(tsx@4.22.3))
|
||||||
|
|
||||||
packages/server:
|
packages/server:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -112,6 +112,9 @@ importers:
|
|||||||
ts-node:
|
ts-node:
|
||||||
specifier: ^10.9.2
|
specifier: ^10.9.2
|
||||||
version: 10.9.2(@types/node@20.19.30)(typescript@5.9.3)
|
version: 10.9.2(@types/node@20.19.30)(typescript@5.9.3)
|
||||||
|
tsx:
|
||||||
|
specifier: ^4.22.3
|
||||||
|
version: 4.22.3
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
@ -142,6 +145,12 @@ packages:
|
|||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [aix]
|
os: [aix]
|
||||||
|
|
||||||
|
'@esbuild/aix-ppc64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [aix]
|
||||||
|
|
||||||
'@esbuild/android-arm64@0.25.12':
|
'@esbuild/android-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
|
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -154,6 +163,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/android-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/android-arm@0.25.12':
|
'@esbuild/android-arm@0.25.12':
|
||||||
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
|
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -166,6 +181,12 @@ packages:
|
|||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/android-arm@0.28.0':
|
||||||
|
resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/android-x64@0.25.12':
|
'@esbuild/android-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
|
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -178,6 +199,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
|
'@esbuild/android-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/darwin-arm64@0.25.12':
|
'@esbuild/darwin-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
|
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -190,6 +217,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
|
'@esbuild/darwin-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
'@esbuild/darwin-x64@0.25.12':
|
'@esbuild/darwin-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
|
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -202,6 +235,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
|
'@esbuild/darwin-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
'@esbuild/freebsd-arm64@0.25.12':
|
'@esbuild/freebsd-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
|
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -214,6 +253,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@esbuild/freebsd-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
'@esbuild/freebsd-x64@0.25.12':
|
'@esbuild/freebsd-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
|
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -226,6 +271,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@esbuild/freebsd-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
'@esbuild/linux-arm64@0.25.12':
|
'@esbuild/linux-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
|
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -238,6 +289,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-arm@0.25.12':
|
'@esbuild/linux-arm@0.25.12':
|
||||||
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
|
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -250,6 +307,12 @@ packages:
|
|||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-arm@0.28.0':
|
||||||
|
resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-ia32@0.25.12':
|
'@esbuild/linux-ia32@0.25.12':
|
||||||
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
|
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -262,6 +325,12 @@ packages:
|
|||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-ia32@0.28.0':
|
||||||
|
resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-loong64@0.25.12':
|
'@esbuild/linux-loong64@0.25.12':
|
||||||
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
|
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -274,6 +343,12 @@ packages:
|
|||||||
cpu: [loong64]
|
cpu: [loong64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-loong64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [loong64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-mips64el@0.25.12':
|
'@esbuild/linux-mips64el@0.25.12':
|
||||||
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
|
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -286,6 +361,12 @@ packages:
|
|||||||
cpu: [mips64el]
|
cpu: [mips64el]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-mips64el@0.28.0':
|
||||||
|
resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [mips64el]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-ppc64@0.25.12':
|
'@esbuild/linux-ppc64@0.25.12':
|
||||||
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
|
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -298,6 +379,12 @@ packages:
|
|||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-ppc64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-riscv64@0.25.12':
|
'@esbuild/linux-riscv64@0.25.12':
|
||||||
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
|
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -310,6 +397,12 @@ packages:
|
|||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-riscv64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-s390x@0.25.12':
|
'@esbuild/linux-s390x@0.25.12':
|
||||||
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
|
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -322,6 +415,12 @@ packages:
|
|||||||
cpu: [s390x]
|
cpu: [s390x]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-s390x@0.28.0':
|
||||||
|
resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [s390x]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-x64@0.25.12':
|
'@esbuild/linux-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
|
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -334,6 +433,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
|
'@esbuild/linux-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/netbsd-arm64@0.25.12':
|
'@esbuild/netbsd-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
|
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -346,6 +451,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [netbsd]
|
os: [netbsd]
|
||||||
|
|
||||||
|
'@esbuild/netbsd-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [netbsd]
|
||||||
|
|
||||||
'@esbuild/netbsd-x64@0.25.12':
|
'@esbuild/netbsd-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
|
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -358,6 +469,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [netbsd]
|
os: [netbsd]
|
||||||
|
|
||||||
|
'@esbuild/netbsd-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [netbsd]
|
||||||
|
|
||||||
'@esbuild/openbsd-arm64@0.25.12':
|
'@esbuild/openbsd-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
|
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -370,6 +487,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openbsd]
|
os: [openbsd]
|
||||||
|
|
||||||
|
'@esbuild/openbsd-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [openbsd]
|
||||||
|
|
||||||
'@esbuild/openbsd-x64@0.25.12':
|
'@esbuild/openbsd-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
|
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -382,6 +505,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [openbsd]
|
os: [openbsd]
|
||||||
|
|
||||||
|
'@esbuild/openbsd-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [openbsd]
|
||||||
|
|
||||||
'@esbuild/openharmony-arm64@0.25.12':
|
'@esbuild/openharmony-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
|
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -394,6 +523,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openharmony]
|
os: [openharmony]
|
||||||
|
|
||||||
|
'@esbuild/openharmony-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [openharmony]
|
||||||
|
|
||||||
'@esbuild/sunos-x64@0.25.12':
|
'@esbuild/sunos-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
|
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -406,6 +541,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [sunos]
|
os: [sunos]
|
||||||
|
|
||||||
|
'@esbuild/sunos-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [sunos]
|
||||||
|
|
||||||
'@esbuild/win32-arm64@0.25.12':
|
'@esbuild/win32-arm64@0.25.12':
|
||||||
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
|
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -418,6 +559,12 @@ packages:
|
|||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@esbuild/win32-arm64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
'@esbuild/win32-ia32@0.25.12':
|
'@esbuild/win32-ia32@0.25.12':
|
||||||
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
|
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -430,6 +577,12 @@ packages:
|
|||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@esbuild/win32-ia32@0.28.0':
|
||||||
|
resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
'@esbuild/win32-x64@0.25.12':
|
'@esbuild/win32-x64@0.25.12':
|
||||||
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
|
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -442,6 +595,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@esbuild/win32-x64@0.28.0':
|
||||||
|
resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
'@hono/node-server@1.19.9':
|
'@hono/node-server@1.19.9':
|
||||||
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
|
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
@ -1035,6 +1194,11 @@ packages:
|
|||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
esbuild@0.28.0:
|
||||||
|
resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
escalade@3.2.0:
|
escalade@3.2.0:
|
||||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -1485,6 +1649,11 @@ packages:
|
|||||||
tslib@2.8.1:
|
tslib@2.8.1:
|
||||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
|
tsx@4.22.3:
|
||||||
|
resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
type-is@2.0.1:
|
type-is@2.0.1:
|
||||||
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@ -1627,156 +1796,234 @@ snapshots:
|
|||||||
'@esbuild/aix-ppc64@0.27.2':
|
'@esbuild/aix-ppc64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/aix-ppc64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm64@0.25.12':
|
'@esbuild/android-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm64@0.27.2':
|
'@esbuild/android-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm@0.25.12':
|
'@esbuild/android-arm@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm@0.27.2':
|
'@esbuild/android-arm@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-arm@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-x64@0.25.12':
|
'@esbuild/android-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-x64@0.27.2':
|
'@esbuild/android-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/android-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-arm64@0.25.12':
|
'@esbuild/darwin-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-arm64@0.27.2':
|
'@esbuild/darwin-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/darwin-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-x64@0.25.12':
|
'@esbuild/darwin-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-x64@0.27.2':
|
'@esbuild/darwin-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/darwin-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-arm64@0.25.12':
|
'@esbuild/freebsd-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-arm64@0.27.2':
|
'@esbuild/freebsd-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/freebsd-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-x64@0.25.12':
|
'@esbuild/freebsd-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-x64@0.27.2':
|
'@esbuild/freebsd-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/freebsd-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm64@0.25.12':
|
'@esbuild/linux-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm64@0.27.2':
|
'@esbuild/linux-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm@0.25.12':
|
'@esbuild/linux-arm@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm@0.27.2':
|
'@esbuild/linux-arm@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-arm@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ia32@0.25.12':
|
'@esbuild/linux-ia32@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ia32@0.27.2':
|
'@esbuild/linux-ia32@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-ia32@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-loong64@0.25.12':
|
'@esbuild/linux-loong64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-loong64@0.27.2':
|
'@esbuild/linux-loong64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-loong64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-mips64el@0.25.12':
|
'@esbuild/linux-mips64el@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-mips64el@0.27.2':
|
'@esbuild/linux-mips64el@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-mips64el@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ppc64@0.25.12':
|
'@esbuild/linux-ppc64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ppc64@0.27.2':
|
'@esbuild/linux-ppc64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-ppc64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-riscv64@0.25.12':
|
'@esbuild/linux-riscv64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-riscv64@0.27.2':
|
'@esbuild/linux-riscv64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-riscv64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-s390x@0.25.12':
|
'@esbuild/linux-s390x@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-s390x@0.27.2':
|
'@esbuild/linux-s390x@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-s390x@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-x64@0.25.12':
|
'@esbuild/linux-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-x64@0.27.2':
|
'@esbuild/linux-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/linux-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-arm64@0.25.12':
|
'@esbuild/netbsd-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-arm64@0.27.2':
|
'@esbuild/netbsd-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/netbsd-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-x64@0.25.12':
|
'@esbuild/netbsd-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-x64@0.27.2':
|
'@esbuild/netbsd-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/netbsd-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-arm64@0.25.12':
|
'@esbuild/openbsd-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-arm64@0.27.2':
|
'@esbuild/openbsd-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/openbsd-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-x64@0.25.12':
|
'@esbuild/openbsd-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-x64@0.27.2':
|
'@esbuild/openbsd-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/openbsd-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openharmony-arm64@0.25.12':
|
'@esbuild/openharmony-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openharmony-arm64@0.27.2':
|
'@esbuild/openharmony-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/openharmony-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/sunos-x64@0.25.12':
|
'@esbuild/sunos-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/sunos-x64@0.27.2':
|
'@esbuild/sunos-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/sunos-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-arm64@0.25.12':
|
'@esbuild/win32-arm64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-arm64@0.27.2':
|
'@esbuild/win32-arm64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-arm64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-ia32@0.25.12':
|
'@esbuild/win32-ia32@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-ia32@0.27.2':
|
'@esbuild/win32-ia32@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-ia32@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-x64@0.25.12':
|
'@esbuild/win32-x64@0.25.12':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-x64@0.27.2':
|
'@esbuild/win32-x64@0.27.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@esbuild/win32-x64@0.28.0':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@hono/node-server@1.19.9(hono@4.11.7)':
|
'@hono/node-server@1.19.9(hono@4.11.7)':
|
||||||
dependencies:
|
dependencies:
|
||||||
hono: 4.11.7
|
hono: 4.11.7
|
||||||
@ -2288,6 +2535,35 @@ snapshots:
|
|||||||
'@esbuild/win32-ia32': 0.27.2
|
'@esbuild/win32-ia32': 0.27.2
|
||||||
'@esbuild/win32-x64': 0.27.2
|
'@esbuild/win32-x64': 0.27.2
|
||||||
|
|
||||||
|
esbuild@0.28.0:
|
||||||
|
optionalDependencies:
|
||||||
|
'@esbuild/aix-ppc64': 0.28.0
|
||||||
|
'@esbuild/android-arm': 0.28.0
|
||||||
|
'@esbuild/android-arm64': 0.28.0
|
||||||
|
'@esbuild/android-x64': 0.28.0
|
||||||
|
'@esbuild/darwin-arm64': 0.28.0
|
||||||
|
'@esbuild/darwin-x64': 0.28.0
|
||||||
|
'@esbuild/freebsd-arm64': 0.28.0
|
||||||
|
'@esbuild/freebsd-x64': 0.28.0
|
||||||
|
'@esbuild/linux-arm': 0.28.0
|
||||||
|
'@esbuild/linux-arm64': 0.28.0
|
||||||
|
'@esbuild/linux-ia32': 0.28.0
|
||||||
|
'@esbuild/linux-loong64': 0.28.0
|
||||||
|
'@esbuild/linux-mips64el': 0.28.0
|
||||||
|
'@esbuild/linux-ppc64': 0.28.0
|
||||||
|
'@esbuild/linux-riscv64': 0.28.0
|
||||||
|
'@esbuild/linux-s390x': 0.28.0
|
||||||
|
'@esbuild/linux-x64': 0.28.0
|
||||||
|
'@esbuild/netbsd-arm64': 0.28.0
|
||||||
|
'@esbuild/netbsd-x64': 0.28.0
|
||||||
|
'@esbuild/openbsd-arm64': 0.28.0
|
||||||
|
'@esbuild/openbsd-x64': 0.28.0
|
||||||
|
'@esbuild/openharmony-arm64': 0.28.0
|
||||||
|
'@esbuild/sunos-x64': 0.28.0
|
||||||
|
'@esbuild/win32-arm64': 0.28.0
|
||||||
|
'@esbuild/win32-ia32': 0.28.0
|
||||||
|
'@esbuild/win32-x64': 0.28.0
|
||||||
|
|
||||||
escalade@3.2.0: {}
|
escalade@3.2.0: {}
|
||||||
|
|
||||||
escape-goat@4.0.0: {}
|
escape-goat@4.0.0: {}
|
||||||
@ -2796,6 +3072,12 @@ snapshots:
|
|||||||
|
|
||||||
tslib@2.8.1: {}
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
|
tsx@4.22.3:
|
||||||
|
dependencies:
|
||||||
|
esbuild: 0.28.0
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
|
||||||
type-is@2.0.1:
|
type-is@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
@ -2814,7 +3096,7 @@ snapshots:
|
|||||||
|
|
||||||
vary@1.1.2: {}
|
vary@1.1.2: {}
|
||||||
|
|
||||||
vite-live-preview@0.3.2(vite@7.3.1(@types/node@20.19.30)):
|
vite-live-preview@0.3.2(vite@7.3.1(@types/node@20.19.30)(tsx@4.22.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@commander-js/extra-typings': 12.1.0(commander@12.1.0)
|
'@commander-js/extra-typings': 12.1.0(commander@12.1.0)
|
||||||
'@types/ansi-html': 0.0.0
|
'@types/ansi-html': 0.0.0
|
||||||
@ -2826,14 +3108,14 @@ snapshots:
|
|||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
escape-goat: 4.0.0
|
escape-goat: 4.0.0
|
||||||
p-defer: 4.0.1
|
p-defer: 4.0.1
|
||||||
vite: 7.3.1(@types/node@20.19.30)
|
vite: 7.3.1(@types/node@20.19.30)(tsx@4.22.3)
|
||||||
ws: 8.19.0
|
ws: 8.19.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
vite@7.3.1(@types/node@20.19.30):
|
vite@7.3.1(@types/node@20.19.30)(tsx@4.22.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.27.2
|
esbuild: 0.27.2
|
||||||
fdir: 6.5.0(picomatch@4.0.3)
|
fdir: 6.5.0(picomatch@4.0.3)
|
||||||
@ -2844,6 +3126,7 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 20.19.30
|
'@types/node': 20.19.30
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
tsx: 4.22.3
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user