diff --git a/apps/web/src/app/(application)/files/page.tsx b/apps/web/src/app/(application)/files/page.tsx index 87c33b5..90d2f44 100644 --- a/apps/web/src/app/(application)/files/page.tsx +++ b/apps/web/src/app/(application)/files/page.tsx @@ -1,6 +1,6 @@ "use client" -import { useCallback, useRef, useState } from "react" +import React, { useCallback, useRef, useState } from "react" import { toast } from "sonner" // UI Components @@ -354,16 +354,18 @@ const FilesPage = () => { {breadcrumbs.map((entry, i) => ( - + {i > 0 && } - {i === breadcrumbs.length - 1 ? ( - {entry.name} - ) : ( - navigateToBreadcrumb(entry)}> - {entry.name} - - )} - + + {i === breadcrumbs.length - 1 ? ( + {entry.name} + ) : ( + navigateToBreadcrumb(entry)}> + {entry.name} + + )} + + ))} diff --git a/apps/web/src/app/api/conversations/[conversationid]/artifacts/[filename]/route.ts b/apps/web/src/app/api/conversations/[conversationid]/artifacts/[filename]/route.ts index 15f6502..8cd4e60 100644 --- a/apps/web/src/app/api/conversations/[conversationid]/artifacts/[filename]/route.ts +++ b/apps/web/src/app/api/conversations/[conversationid]/artifacts/[filename]/route.ts @@ -32,7 +32,9 @@ export async function GET( // Proxy to gateway try { const gatewayUrl = `${GATEWAY_URL}/api/v1/sessions/${conversationid}/artifacts/${encodeURIComponent(filename)}${queryString}` - const response = await fetch(gatewayUrl) + const response = await fetch(gatewayUrl, { + headers: { cookie: reqheaders.get("cookie") ?? "" }, + }) if (!response.ok) { return NextResponse.json({ error: "Artifact not found" }, { status: response.status }) diff --git a/apps/web/src/utils/file-utils.tsx b/apps/web/src/utils/file-utils.tsx index d890120..256864a 100644 --- a/apps/web/src/utils/file-utils.tsx +++ b/apps/web/src/utils/file-utils.tsx @@ -45,7 +45,8 @@ export const isPreviewable = (mediatype: string): boolean => { mediatype === "text/plain" || mediatype === "text/markdown" || mediatype === "text/csv" || - mediatype === "application/json" + mediatype === "application/json" || + mediatype === "application/pdf" ) } diff --git a/infra/openshell/Dockerfile b/infra/openshell/Dockerfile index 8de6e9e..9395f9c 100644 --- a/infra/openshell/Dockerfile +++ b/infra/openshell/Dockerfile @@ -17,10 +17,28 @@ # ============================================================================= # --------------------------------------------------------------------------- -# Stage 1: Build sandbox-server and produce a deployable bundle +# Stage 1: Build sandbox-server and produce a deployable bundle. +# Also pre-builds all native npm globals here so the runtime stage does not +# need a C/C++ toolchain. # --------------------------------------------------------------------------- FROM node:22-slim AS builder +# Build-time system dependencies: +# - build-essential / g++ / make / pkg-config: required by node-gyp for native modules +# - *-dev packages: header files needed to compile canvas (cairo, gif, jpeg, pango, rsvg) +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + g++ \ + libcairo2-dev \ + libgif-dev \ + libjpeg-dev \ + libpango1.0-dev \ + librsvg2-dev \ + make \ + pkg-config \ + python3 \ + && rm -rf /var/lib/apt/lists/* + RUN corepack enable && corepack prepare pnpm@10.32.1 --activate WORKDIR /build @@ -53,35 +71,66 @@ RUN pnpm --filter @openzosma/sandbox-server deploy /deploy --prod --legacy # Copy built dist into the deploy directory RUN cp -r packages/sandbox-server/dist /deploy/dist +# Pre-build all global npm packages that contain native modules or are large. +# Installing here (with the toolchain present) means the runtime stage only +# needs to COPY the pre-compiled /usr/local/lib/node_modules directory — +# no compiler required at runtime. +RUN npm install -g \ + @mariozechner/pi-coding-agent \ + agent-slack \ + chart.js \ + chartjs-node-canvas \ + d3 \ + exceljs + # --------------------------------------------------------------------------- # Stage 2: Runtime # --------------------------------------------------------------------------- FROM node:22-slim -# Install runtime dependencies and developer tools. -# iproute2 is required by the OpenShell sandbox supervisor for network namespace creation. -# python3-venv provides virtualenv support for isolated Python environments. -# tree, jq, wget, less, unzip, zip are general-purpose CLI tools the agent can use. -# make + g++ are required for native npm modules that use node-gyp. -# Node.js and npm are already present from the node:22-slim base image. +# Runtime system dependencies only — no compiler toolchain, no *-dev headers. +# +# Shared libraries required by pre-compiled native modules (e.g. canvas): +# libcairo2, libgif7, libjpeg62-turbo, libpango-1.0-0, libpangocairo-1.0-0, +# librsvg2-2 — these are the runtime counterparts of the *-dev packages used +# in the builder stage. +# +# iproute2: required by the OpenShell sandbox supervisor for network namespace creation. +# python3 / python3-pip / python3-venv: agent-generated Python code + report generation. +# tini: PID 1 / signal handling. +# git, curl, wget, jq, less, tree, unzip, zip: general-purpose CLI tools for the agent. RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ git \ + iproute2 \ + jq \ + less \ + libcairo2 \ + libgif7 \ + libjpeg62-turbo \ + libpango-1.0-0 \ + libpangocairo-1.0-0 \ + librsvg2-2 \ python3 \ python3-pip \ python3-venv \ tini \ - curl \ - iproute2 \ tree \ - jq \ - wget \ - less \ unzip \ + wget \ zip \ - make \ - g++ \ && rm -rf /var/lib/apt/lists/* +# Install Python reporting libraries +RUN pip3 install --break-system-packages \ + matplotlib \ + numpy \ + openpyxl \ + pandas \ + python-pptx \ + reportlab \ + seaborn + # Create sandbox user (OpenShell convention: non-root execution) # --home is required so homedir() returns a real path; bootstrapPiExtensions() # writes config files to ~/.pi/ and will crash if home is /nonexistent. @@ -95,11 +144,12 @@ WORKDIR /app # Copy the self-contained deploy bundle (node_modules + dist, no symlinks) COPY --from=builder /deploy ./ -RUN npm install -g @mariozechner/pi-coding-agent - -# Install agent-slack CLI so the agent can query Slack from inside the sandbox. -# The CLI reads SLACK_TOKEN from the environment (injected via .env by the orchestrator). -RUN npm install -g agent-slack +# Copy pre-compiled global npm packages from the builder stage. +# All native modules (e.g. canvas inside chartjs-node-canvas) were compiled +# there with the full toolchain. The runtime stage needs only the shared libs +# (installed above), not the compiler. +COPY --from=builder /usr/local/lib/node_modules /usr/local/lib/node_modules +COPY --from=builder /usr/local/bin /usr/local/bin # Copy extension manifest and install script before switching to sandbox user COPY packages/agents/extensions.json /tmp/extensions.json @@ -123,7 +173,7 @@ RUN chown root:root -R ./skills/ && chmod 444 -R ./skills/ # In per-user persistent sandboxes, this directory persists across sessions. # /sandbox is the OpenShell writable root where .env is uploaded. # .knowledge-base is pre-created so the agent prompt doesn't error on ls. -RUN mkdir -p /workspace/.knowledge-base /tmp/agent /sandbox && \ +RUN mkdir -p /workspace/.knowledge-base /workspace/output /tmp/agent /sandbox && \ chown -R sandbox:sandbox /workspace /tmp/agent /sandbox # Copy entrypoint into /app/ which is already in the policy read_only allowlist. diff --git a/packages/agents/package.json b/packages/agents/package.json index bd1add9..655066b 100644 --- a/packages/agents/package.json +++ b/packages/agents/package.json @@ -29,6 +29,7 @@ "uuid": "^13.0.0", "@openzosma/db": "workspace:*", "@openzosma/integrations": "workspace:*", + "@openzosma/skill-reports": "workspace:*", "pg": "^8.13.1", "@mariozechner/pi-agent-core": "^0.61.0" }, diff --git a/packages/agents/src/pi.agent.ts b/packages/agents/src/pi.agent.ts index dca2810..b5d76a6 100644 --- a/packages/agents/src/pi.agent.ts +++ b/packages/agents/src/pi.agent.ts @@ -11,7 +11,12 @@ import { createLogger } from "@openzosma/logger" import { bootstrapMemory } from "@openzosma/memory" import { DEFAULT_SYSTEM_PROMPT } from "./pi/config.js" import { resolveModel } from "./pi/model.js" -import { createDefaultTools, createListDatabaseSchemasTool, createQueryDatabaseTool } from "./pi/tools.js" +import { + createDefaultTools, + createListDatabaseSchemasTool, + createQueryDatabaseTool, + createReportTools, +} from "./pi/tools.js" import type { AgentMessage, AgentProvider, AgentSession, AgentSessionOpts, AgentStreamEvent } from "./types.js" const log = createLogger({ component: "agents" }) @@ -52,9 +57,11 @@ class PiAgentSession implements AgentSession { memoryDir: opts.memoryDir, }) const toolList = [...createDefaultTools(opts.workspaceDir, opts.toolsEnabled)] - const customTools = opts.dbPool - ? [createQueryDatabaseTool(opts.dbPool), createListDatabaseSchemasTool(opts.dbPool)] - : undefined + const reportTools = createReportTools(opts.toolsEnabled, opts.workspaceDir) + const customTools = [ + ...reportTools, + ...(opts.dbPool ? [createQueryDatabaseTool(opts.dbPool), createListDatabaseSchemasTool(opts.dbPool)] : []), + ] const { model, apiKey } = resolveModel({ provider: opts.provider, model: opts.model, diff --git a/packages/agents/src/pi/tools.ts b/packages/agents/src/pi/tools.ts index 5f6c960..d059e6e 100644 --- a/packages/agents/src/pi/tools.ts +++ b/packages/agents/src/pi/tools.ts @@ -12,21 +12,75 @@ import type { ToolDefinition } from "@mariozechner/pi-coding-agent" import { integrationQueries } from "@openzosma/db" import type { IntegrationConfig } from "@openzosma/db" import { executequery, getschema, safeDecrypt } from "@openzosma/integrations" +import { + createReportExecuteCodeTool, + createReportGenerateTool, + createReportListTemplatesTool, +} from "@openzosma/skill-reports" import { Type } from "@sinclair/typebox" import type pg from "pg" -export type BuiltInToolName = "read" | "bash" | "edit" | "write" | "grep" | "find" | "ls" +export type BuiltInToolName = + | "read" + | "bash" + | "edit" + | "write" + | "grep" + | "find" + | "ls" + | "report_list_templates" + | "report_generate" + | "report_execute_code" + +// Built-in AgentTool entries (accepted by createAgentSession's `tools` field). +const BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"] as const +type BuiltinToolName = (typeof BUILTIN_TOOL_NAMES)[number] + +// Custom ToolDefinition entries (accepted by createAgentSession's `customTools` field). +const CUSTOM_TOOL_NAMES = ["report_list_templates", "report_generate", "report_execute_code"] as const +type CustomToolName = (typeof CUSTOM_TOOL_NAMES)[number] +/** + * Create the built-in AgentTool instances (read, bash, edit, write, grep, find, ls). + * These go in `tools` when calling createAgentSession. + * + * @param workspaceDir - Root workspace directory. + * @param toolsEnabled - Optional allow-list of tool names. If omitted, all tools are returned. + */ export const createDefaultTools = (workspaceDir: string, toolsEnabled?: string[]) => { const allTools = [ - { name: "read", tool: createReadTool(workspaceDir) }, - { name: "bash", tool: createBashTool(workspaceDir) }, - { name: "edit", tool: createEditTool(workspaceDir) }, - { name: "write", tool: createWriteTool(workspaceDir) }, - { name: "grep", tool: createGrepTool(workspaceDir) }, - { name: "find", tool: createFindTool(workspaceDir) }, - { name: "ls", tool: createLsTool(workspaceDir) }, - ] as const + { name: "read" as BuiltinToolName, tool: createReadTool(workspaceDir) }, + { name: "bash" as BuiltinToolName, tool: createBashTool(workspaceDir) }, + { name: "edit" as BuiltinToolName, tool: createEditTool(workspaceDir) }, + { name: "write" as BuiltinToolName, tool: createWriteTool(workspaceDir) }, + { name: "grep" as BuiltinToolName, tool: createGrepTool(workspaceDir) }, + { name: "find" as BuiltinToolName, tool: createFindTool(workspaceDir) }, + { name: "ls" as BuiltinToolName, tool: createLsTool(workspaceDir) }, + ] + + if (!toolsEnabled || toolsEnabled.length === 0) { + return allTools.map((t) => t.tool) + } + + const allow = new Set(toolsEnabled) + return allTools.filter((t) => allow.has(t.name)).map((t) => t.tool) +} + +/** + * Create the report ToolDefinition instances (report_list_templates, report_generate, report_execute_code). + * These go in `customTools` when calling createAgentSession. + * + * @param toolsEnabled - Optional allow-list of tool names. If omitted, all report tools are returned. + * @param workspaceDir - Workspace root; report output will go to /output. + * Defaults to /workspace/output when omitted (sandbox mode). + */ +export const createReportTools = (toolsEnabled?: string[], workspaceDir?: string): ToolDefinition[] => { + const outputDir = workspaceDir ? `${workspaceDir}/output` : undefined + const allTools = [ + { name: "report_list_templates" as CustomToolName, tool: createReportListTemplatesTool({ outputDir }) }, + { name: "report_generate" as CustomToolName, tool: createReportGenerateTool({ outputDir }) }, + { name: "report_execute_code" as CustomToolName, tool: createReportExecuteCodeTool({ outputDir }) }, + ] if (!toolsEnabled || toolsEnabled.length === 0) { return allTools.map((t) => t.tool) diff --git a/packages/gateway/src/app.ts b/packages/gateway/src/app.ts index 7acf6fd..172d0e0 100644 --- a/packages/gateway/src/app.ts +++ b/packages/gateway/src/app.ts @@ -1,4 +1,6 @@ import { createHash, randomBytes } from "node:crypto" +import { createReadStream, existsSync, mkdirSync, readdirSync, statSync } from "node:fs" +import { join, resolve } from "node:path" import { buildDefaultAgentCard } from "@openzosma/a2a" import type { Auth } from "@openzosma/auth" import type { Role } from "@openzosma/auth" @@ -79,10 +81,173 @@ export const createApp = ( // File management routes (require orchestrator for sandbox filesystem access) // ----------------------------------------------------------------------- + // MIME types for agent-generated artifacts (used in local-mode file routes + // and the session artifact routes below). + const ARTIFACT_MIME_MAP: Record = { + png: "image/png", + svg: "image/svg+xml", + pdf: "application/pdf", + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", + csv: "text/csv", + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + txt: "text/plain", + json: "application/json", + } + if (orchestrator) { app.route("/api/v1/files", createFileRoutes({ orchestrator })) + } else { + // Local mode: serve files from workspace/user-files/ai-generated/. + // Files are copied here by scanOutputDir whenever the agent generates an artifact. + + const localUserFilesDir = (): string => { + const root = resolve(process.env.OPENZOSMA_WORKSPACE ?? join(process.cwd(), "workspace")) + const dir = join(root, "user-files", "ai-generated") + mkdirSync(dir, { recursive: true }) + return dir + } + + const LOCAL_MIME_MAP: Record = { + png: "image/png", + svg: "image/svg+xml", + pdf: "application/pdf", + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", + csv: "text/csv", + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + txt: "text/plain", + json: "application/json", + } + + const scanLocalFiles = (dir: string) => + existsSync(dir) + ? readdirSync(dir) + .filter((f) => LOCAL_MIME_MAP[f.split(".").pop() ?? ""]) + .map((filename) => { + const ext = filename.split(".").pop() ?? "" + return { + name: filename, + path: `/ai-generated/${filename}`, + isFolder: false, + mimeType: LOCAL_MIME_MAP[ext] ?? "application/octet-stream", + sizeBytes: statSync(join(dir, filename)).size, + modifiedAt: statSync(join(dir, filename)).mtime.toISOString(), + } + }) + : [] + + app.get("/api/v1/files/tree", requirePermission("files", "read"), (c) => { + const dir = localUserFilesDir() + const files = scanLocalFiles(dir) + const entries = + files.length > 0 + ? [ + { + name: "ai-generated", + path: "/ai-generated", + isFolder: true, + mimeType: null, + sizeBytes: 0, + modifiedAt: new Date().toISOString(), + children: files, + }, + ] + : [] + return c.json({ entries }) + }) + + app.get("/api/v1/files/list", requirePermission("files", "read"), (c) => { + const dir = localUserFilesDir() + return c.json({ entries: scanLocalFiles(dir) }) + }) + + app.get("/api/v1/files/download", requirePermission("files", "read"), (c) => { + const filePath = c.req.query("path") + if (!filePath) return c.json({ error: "path query parameter is required" }, 400) + + const dir = localUserFilesDir() + // path is like /ai-generated/filename.pdf — strip the folder prefix + const filename = filePath.replace(/^\/ai-generated\//, "") + const fullPath = join(dir, filename) + + if (!existsSync(fullPath)) return c.json({ error: "File not found" }, 404) + + const ext = filename.split(".").pop() ?? "" + const contentType = LOCAL_MIME_MAP[ext] ?? "application/octet-stream" + const stat = statSync(fullPath) + const download = c.req.query("download") === "true" + + c.header("Content-Type", contentType) + c.header("Content-Length", String(stat.size)) + c.header("Cache-Control", "private, max-age=3600") + if (download) c.header("Content-Disposition", `attachment; filename="${filename}"`) + + const stream = createReadStream(fullPath) + return c.body(stream as unknown as ReadableStream) + }) } + // ----------------------------------------------------------------------- + // Session artifact routes (local mode — serve files from session output dir) + // ----------------------------------------------------------------------- + + app.get("/api/v1/sessions/:id/artifacts/:filename", requirePermission("sessions", "read"), (c) => { + const sessionId = c.req.param("id") + const filename = c.req.param("filename") + + const workspaceDir = sessionManager.getSessionWorkspaceDir(sessionId) + if (!workspaceDir) { + return c.json({ error: "Session not found or not in local mode" }, 404) + } + + const filePath = join(workspaceDir, "output", filename) + if (!existsSync(filePath)) { + return c.json({ error: "Artifact not found" }, 404) + } + + const stat = statSync(filePath) + const ext = filename.split(".").pop() ?? "" + const contentType = ARTIFACT_MIME_MAP[ext] ?? "application/octet-stream" + const download = c.req.query("download") === "true" + + c.header("Content-Type", contentType) + c.header("Content-Length", String(stat.size)) + c.header("Cache-Control", "private, max-age=3600") + if (download) { + c.header("Content-Disposition", `attachment; filename="${filename}"`) + } + + // Stream the file to avoid loading it fully into memory + const stream = createReadStream(filePath) + return c.body(stream as unknown as ReadableStream) + }) + + app.get("/api/v1/sessions/:id/artifacts", requirePermission("sessions", "read"), (c) => { + const sessionId = c.req.param("id") + const workspaceDir = sessionManager.getSessionWorkspaceDir(sessionId) + if (!workspaceDir) { + return c.json({ artifacts: [] }) + } + + const outputDir = join(workspaceDir, "output") + if (!existsSync(outputDir)) { + return c.json({ artifacts: [] }) + } + + const TRACKED_EXTS = new Set(Object.keys(ARTIFACT_MIME_MAP)) + const artifacts = readdirSync(outputDir) + .filter((f) => TRACKED_EXTS.has(f.split(".").pop() ?? "")) + .map((filename) => { + const ext = filename.split(".").pop() ?? "" + return { + filename, + mediatype: ARTIFACT_MIME_MAP[ext] ?? "application/octet-stream", + sizebytes: statSync(join(outputDir, filename)).size, + } + }) + + return c.json({ artifacts }) + }) + // ----------------------------------------------------------------------- // Session routes // ----------------------------------------------------------------------- diff --git a/packages/gateway/src/session-manager.ts b/packages/gateway/src/session-manager.ts index 590f25e..0bacf64 100644 --- a/packages/gateway/src/session-manager.ts +++ b/packages/gateway/src/session-manager.ts @@ -1,6 +1,6 @@ import { randomUUID } from "node:crypto" import { EventEmitter } from "node:events" -import { mkdirSync, symlinkSync, writeFileSync } from "node:fs" +import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, symlinkSync, writeFileSync } from "node:fs" import { dirname, join, resolve } from "node:path" import type { AgentProvider, AgentSession } from "@openzosma/agents" import { PiAgentProvider } from "@openzosma/agents" @@ -241,6 +241,14 @@ export class SessionManager { return this.sessions.get(id)?.session } + /** + * Return the workspace directory for a local-mode session, or undefined + * when running in orchestrator mode or the session does not exist. + */ + getSessionWorkspaceDir(id: string): string | undefined { + return this.sessions.get(id)?.workspaceDir + } + deleteSession(id: string): boolean { if (this.orchestrator) { const session = this.sessions.get(id) @@ -578,6 +586,8 @@ export class SessionManager { let lastAssistantText = "" let lastMessageId: string | undefined const emitter = this.getEmitter(sessionId) + // Track files already seen so we only emit each artifact once per message. + const seenOutputFiles = new Set() for await (const event of agentSession.sendMessage(augmentedContent, signal)) { const gatewayEvent: GatewayEvent = event as GatewayEvent @@ -591,6 +601,17 @@ export class SessionManager { emitter.emit("event", gatewayEvent) yield gatewayEvent + + // After each tool call completes, scan the output directory for new files + // and emit a file_output event so the frontend can display download links. + if (event.type === "tool_call_end") { + const newArtifacts = this.scanOutputDir(workspaceDir, seenOutputFiles) + if (newArtifacts.length > 0) { + const fileEvent: GatewayEvent = { type: "file_output", artifacts: newArtifacts } + emitter.emit("event", fileEvent) + yield fileEvent + } + } } // Store assistant message for session history @@ -605,6 +626,53 @@ export class SessionManager { } } + /** + * Scan workspaceDir/output for files and return FileArtifact metadata. + * Used in local mode to emit file_output events after tool calls. + */ + private scanOutputDir(workspaceDir: string, seenFiles: Set): FileArtifact[] { + const outputDir = join(workspaceDir, "output") + if (!existsSync(outputDir)) return [] + + const MIME_MAP: Record = { + png: "image/png", + svg: "image/svg+xml", + pdf: "application/pdf", + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", + csv: "text/csv", + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + } + const TRACKED_EXTS = new Set(Object.keys(MIME_MAP)) + + // Copy new artifacts to the central user-files area so the Files page can list them + const workspaceRoot = resolve(process.env.OPENZOSMA_WORKSPACE ?? join(process.cwd(), "workspace")) + const userFilesDir = join(workspaceRoot, "user-files", "ai-generated") + mkdirSync(userFilesDir, { recursive: true }) + + const newArtifacts: FileArtifact[] = [] + for (const filename of readdirSync(outputDir)) { + if (seenFiles.has(filename)) continue + const ext = filename.split(".").pop() ?? "" + if (!TRACKED_EXTS.has(ext)) continue + const filepath = join(outputDir, filename) + const sizebytes = statSync(filepath).size + seenFiles.add(filename) + newArtifacts.push({ + filename, + mediatype: MIME_MAP[ext] ?? "application/octet-stream", + sizebytes, + }) + + // Non-fatal: artifact card in chat still works via the session artifact route + try { + copyFileSync(filepath, join(userFilesDir, filename)) + } catch { + /* ignore */ + } + } + return newArtifacts + } + /** * Decode a data URL into a Buffer and MIME type. * diff --git a/packages/skills/reports/package.json b/packages/skills/reports/package.json index d4c1c62..eb354ec 100644 --- a/packages/skills/reports/package.json +++ b/packages/skills/reports/package.json @@ -13,10 +13,24 @@ }, "scripts": { "build": "tsc", - "check": "tsc --noEmit" + "check": "tsc --noEmit", + "test": "vitest --run" + }, + "dependencies": { + "@mariozechner/pi-agent-core": "^0.61.0", + "@mariozechner/pi-coding-agent": "^0.61.0", + "@react-pdf/renderer": "^4.3.0", + "@sinclair/typebox": "^0.34.48", + "chart.js": "^4.4.9", + "chartjs-node-canvas": "^4.1.6", + "exceljs": "^4.4.0", + "pptxgenjs": "^3.12.0", + "react": "^19.1.0" }, "devDependencies": { "@types/node": "^22.15.2", - "typescript": "^5.7.3" + "@types/react": "^19.1.2", + "typescript": "^5.7.3", + "vitest": "^3.1.1" } } diff --git a/packages/skills/reports/src/index.ts b/packages/skills/reports/src/index.ts index 755e155..fc00e44 100644 --- a/packages/skills/reports/src/index.ts +++ b/packages/skills/reports/src/index.ts @@ -1,3 +1,14 @@ -// Reports Skill - Template-based and agent-generated report creation. -// Implementation in Phase 6. -export {} +// Reports Skill — template-based and agent-generated report creation. +export { createReportListTemplatesTool, createReportGenerateTool, createReportExecuteCodeTool } from "./tools.js" +export type { + MonthlyReportData, + MetricRow, + ChartDefinition, + ChartDataset, + TableDefinition, + RenderOpts, + ReportFormat, + ReportTemplate, +} from "./templates/types.js" +export { MonthlyReportDataSchema, MonthlyReportTemplate } from "./templates/monthly-report.js" +export { getTemplate, listTemplates, registerTemplate } from "./templates/registry.js" diff --git a/packages/skills/reports/src/renderers/chart.test.ts b/packages/skills/reports/src/renderers/chart.test.ts new file mode 100644 index 0000000..7ad1355 --- /dev/null +++ b/packages/skills/reports/src/renderers/chart.test.ts @@ -0,0 +1,82 @@ +import { beforeEach, describe, expect, it, vi } from "vitest" + +// Mock chartjs-node-canvas before importing renderChart so the native canvas +// binary is never loaded. CI runners do not have the system libraries (Cairo, +// libpng) required to compile canvas@2.x, causing a hard module-not-found +// error when the real binding is required. +vi.mock("chartjs-node-canvas", () => { + const PNG_HEADER = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]) + + const ChartJSNodeCanvas = vi.fn().mockImplementation(() => ({ + renderToBuffer: vi.fn().mockResolvedValue(PNG_HEADER), + renderToBufferSync: vi.fn().mockReturnValue(Buffer.from("", "utf-8")), + })) + + return { ChartJSNodeCanvas } +}) + +import { renderChart } from "./chart.js" + +describe("renderChart", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it("renders a bar chart and returns a Buffer with PNG magic bytes", async () => { + const buf = await renderChart({ + type: "bar", + title: "Test Bar Chart", + labels: ["Jan", "Feb", "Mar"], + datasets: [ + { + label: "Sessions", + data: [10, 20, 15], + backgroundColor: "rgba(54, 162, 235, 0.5)", + }, + ], + }) + + expect(buf).toBeInstanceOf(Buffer) + // PNG magic bytes: \x89PNG + expect(buf[0]).toBe(0x89) + expect(buf[1]).toBe(0x50) // P + expect(buf[2]).toBe(0x4e) // N + expect(buf[3]).toBe(0x47) // G + }) + + it("renders a line chart", async () => { + const buf = await renderChart({ + type: "line", + title: "Line Chart", + labels: ["Q1", "Q2"], + datasets: [{ label: "Value", data: [5, 10] }], + }) + expect(buf).toBeInstanceOf(Buffer) + expect(buf.length).toBeGreaterThan(0) + }) + + it("renders a pie chart", async () => { + const buf = await renderChart({ + type: "pie", + title: "Pie Chart", + labels: ["A", "B"], + datasets: [{ label: "Share", data: [60, 40] }], + }) + expect(buf).toBeInstanceOf(Buffer) + expect(buf.length).toBeGreaterThan(0) + }) + + it("renders an SVG when format is svg", async () => { + const buf = await renderChart( + { + type: "bar", + title: "SVG Chart", + labels: ["X"], + datasets: [{ label: "Y", data: [1] }], + }, + "svg", + ) + expect(buf).toBeInstanceOf(Buffer) + expect(buf.toString()).toContain(" => { + const canvasType = format === "svg" ? "svg" : undefined + const canvas = new ChartJSNodeCanvas({ + width: CANVAS_WIDTH, + height: CANVAS_HEIGHT, + type: canvasType, + backgroundColour: "white", + }) + + const config: ChartConfiguration = { + type: spec.type, + data: { + labels: spec.labels, + datasets: spec.datasets, + }, + options: { + plugins: { + title: { + display: true, + text: spec.title, + }, + legend: { + display: true, + }, + }, + responsive: false, + }, + } + + if (format === "svg") { + return canvas.renderToBufferSync(config, "image/svg+xml") + } + + return canvas.renderToBuffer(config) +} diff --git a/packages/skills/reports/src/renderers/csv.test.ts b/packages/skills/reports/src/renderers/csv.test.ts new file mode 100644 index 0000000..994d54d --- /dev/null +++ b/packages/skills/reports/src/renderers/csv.test.ts @@ -0,0 +1,98 @@ +import { describe, expect, it } from "vitest" +import type { MonthlyReportData } from "../templates/types.js" +import { renderCsv } from "./csv.js" + +const baseData: MonthlyReportData = { + title: "March 2026 Report", + period: { start: "2026-03-01", end: "2026-03-31" }, + metrics: [ + { label: "Sessions", value: 42, unit: "count", change: 0.12 }, + { label: "Avg Duration", value: 95, unit: "s" }, + ], + charts: [], + tables: [ + { + title: "Top Channels", + headers: ["Channel", "Messages"], + rows: [ + ["#general", "310"], + ["#engineering", "205"], + ], + }, + ], +} + +describe("renderCsv", () => { + it("returns a non-empty Buffer", async () => { + const buf = await renderCsv(baseData) + expect(buf).toBeInstanceOf(Buffer) + expect(buf.length).toBeGreaterThan(0) + }) + + it("metrics section has correct headers and values", async () => { + const buf = await renderCsv(baseData) + const text = buf.toString("utf-8") + expect(text).toContain("label,value,unit,change") + expect(text).toContain("Sessions,42,count,0.12") + expect(text).toContain("Avg Duration,95,s,") + }) + + it("table section uses the table title as a comment header", async () => { + const buf = await renderCsv(baseData) + const text = buf.toString("utf-8") + expect(text).toContain("# Top Channels") + expect(text).toContain("Channel,Messages") + expect(text).toContain("#general,310") + }) + + it("sections are separated by a blank line", async () => { + const buf = await renderCsv(baseData) + const text = buf.toString("utf-8") + expect(text).toContain("\n\n") + }) + + it("escapes fields containing commas", async () => { + const data: MonthlyReportData = { + ...baseData, + tables: [ + { + title: "Test", + headers: ["Name"], + rows: [["Smith, John"]], + }, + ], + } + const buf = await renderCsv(data) + expect(buf.toString("utf-8")).toContain('"Smith, John"') + }) + + it("escapes fields containing double-quotes", async () => { + const data: MonthlyReportData = { + ...baseData, + tables: [ + { + title: "Test", + headers: ["Name"], + rows: [['He said "hello"']], + }, + ], + } + const buf = await renderCsv(data) + expect(buf.toString("utf-8")).toContain('"He said ""hello"""') + }) + + it("escapes fields containing newlines", async () => { + const data: MonthlyReportData = { + ...baseData, + tables: [ + { + title: "Test", + headers: ["Name"], + rows: [["line1\nline2"]], + }, + ], + } + const buf = await renderCsv(data) + expect(buf.toString("utf-8")).toContain('"line1\nline2"') + }) +}) diff --git a/packages/skills/reports/src/renderers/csv.ts b/packages/skills/reports/src/renderers/csv.ts new file mode 100644 index 0000000..8b9b83c --- /dev/null +++ b/packages/skills/reports/src/renderers/csv.ts @@ -0,0 +1,54 @@ +import type { MonthlyReportData } from "../templates/types.js" + +/** + * Escape a single CSV field value. + * Wraps in double-quotes if the value contains a comma, newline, or double-quote. + * Inner double-quotes are escaped as "". + */ +const escapeCsvField = (value: string): string => { + if (value.includes(",") || value.includes("\n") || value.includes('"')) { + return `"${value.replace(/"/g, '""')}"` + } + return value +} + +/** + * Render a 2D array of string rows as a CSV block. + */ +const renderTable = (headers: string[], rows: string[][]): string => { + const lines: string[] = [headers.map(escapeCsvField).join(",")] + for (const row of rows) { + lines.push(row.map(escapeCsvField).join(",")) + } + return lines.join("\n") +} + +/** + * Render MonthlyReportData to a CSV buffer. + * + * Outputs three sections separated by blank lines: + * 1. Summary metrics (label, value, unit, change) + * 2. One block per table defined in data.tables + * + * @param data - The monthly report data to render. + * @returns A Buffer containing the UTF-8 encoded CSV content. + */ +export const renderCsv = async (data: MonthlyReportData): Promise => { + const sections: string[] = [] + + // Section 1: metrics + sections.push( + renderTable( + ["label", "value", "unit", "change"], + data.metrics.map((m) => [m.label, String(m.value), m.unit ?? "", m.change !== undefined ? String(m.change) : ""]), + ), + ) + + // Section 2+: one block per table + for (const table of data.tables) { + sections.push(`# ${table.title}`) + sections.push(renderTable(table.headers, table.rows)) + } + + return Buffer.from(sections.join("\n\n"), "utf-8") +} diff --git a/packages/skills/reports/src/renderers/pdf.ts b/packages/skills/reports/src/renderers/pdf.ts new file mode 100644 index 0000000..34006f9 --- /dev/null +++ b/packages/skills/reports/src/renderers/pdf.ts @@ -0,0 +1,161 @@ +import { Document, Image, Page, StyleSheet, Text, View, renderToBuffer } from "@react-pdf/renderer" +import React from "react" +import type { MonthlyReportData, RenderOpts } from "../templates/types.js" +import { renderChart } from "./chart.js" + +const styles = StyleSheet.create({ + page: { + padding: 40, + fontFamily: "Helvetica", + fontSize: 11, + color: "#222", + }, + title: { + fontSize: 22, + fontFamily: "Helvetica-Bold", + marginBottom: 4, + }, + subtitle: { + fontSize: 12, + marginBottom: 20, + color: "#555", + }, + sectionHeading: { + fontSize: 13, + fontFamily: "Helvetica-Bold", + marginBottom: 6, + marginTop: 16, + }, + tableRow: { + flexDirection: "row", + borderBottomWidth: 0.5, + borderBottomColor: "#ccc", + paddingVertical: 3, + }, + tableHeaderRow: { + flexDirection: "row", + borderBottomWidth: 1, + borderBottomColor: "#888", + paddingVertical: 3, + fontFamily: "Helvetica-Bold", + }, + cell: { + flex: 1, + fontSize: 10, + }, + chart: { + width: 480, + height: 240, + marginBottom: 10, + }, + summary: { + fontSize: 11, + color: "#444", + marginBottom: 12, + lineHeight: 1.5, + }, +}) + +/** + * Render MonthlyReportData to a PDF buffer using @react-pdf/renderer. + * + * Layout: + * Page 1 — title, period, optional summary, metrics table + * Page 2+ — one chart image per ChartDefinition (PNG embedded) + * Final — one section per TableDefinition + * + * @param data - The monthly report data to render. + * @param opts - Render options. + * @returns A Buffer containing the PDF binary content. + */ +export const renderPdf = async (data: MonthlyReportData, _opts?: RenderOpts): Promise => { + // Pre-render all charts to base64 PNG data URIs + const chartUris: string[] = await Promise.all( + data.charts.map(async (chart) => { + const buf = await renderChart(chart) + return `data:image/png;base64,${buf.toString("base64")}` + }), + ) + + const children: React.ReactElement[] = [] + + // --- Page 1: title + metrics --- + const page1Rows: React.ReactElement[] = [ + React.createElement(Text, { key: "title", style: styles.title }, data.title), + React.createElement(Text, { key: "period", style: styles.subtitle }, `${data.period.start} — ${data.period.end}`), + ] + + if (data.summary) { + page1Rows.push(React.createElement(Text, { key: "summary", style: styles.summary }, data.summary)) + } + + if (data.metrics.length > 0) { + page1Rows.push(React.createElement(Text, { key: "metricsHeading", style: styles.sectionHeading }, "Metrics")) + + const metricHeaderRow = React.createElement( + View, + { key: "metricHeader", style: styles.tableHeaderRow }, + React.createElement(Text, { style: styles.cell }, "Metric"), + React.createElement(Text, { style: styles.cell }, "Value"), + React.createElement(Text, { style: styles.cell }, "Unit"), + React.createElement(Text, { style: styles.cell }, "Change"), + ) + + const metricDataRows = data.metrics.map((m, i) => + React.createElement( + View, + { key: `m${i}`, style: styles.tableRow }, + React.createElement(Text, { style: styles.cell }, m.label), + React.createElement(Text, { style: styles.cell }, String(m.value)), + React.createElement(Text, { style: styles.cell }, m.unit ?? ""), + React.createElement(Text, { style: styles.cell }, m.change !== undefined ? String(m.change) : ""), + ), + ) + + page1Rows.push(React.createElement(View, { key: "metricsTable" }, metricHeaderRow, ...metricDataRows)) + } + + children.push(React.createElement(Page, { key: "p1", size: "A4", style: styles.page }, ...page1Rows)) + + // --- Chart pages --- + for (let i = 0; i < data.charts.length; i++) { + const chart = data.charts[i] + const uri = chartUris[i] + children.push( + React.createElement( + Page, + { key: `chart${i}`, size: "A4", style: styles.page }, + React.createElement(Text, { style: styles.sectionHeading }, chart.title), + React.createElement(Image, { src: uri, style: styles.chart }), + ), + ) + } + + // --- Table pages --- + for (let t = 0; t < data.tables.length; t++) { + const table = data.tables[t] + const headerRow = React.createElement( + View, + { key: "th", style: styles.tableHeaderRow }, + ...table.headers.map((h, hi) => React.createElement(Text, { key: hi, style: styles.cell }, h)), + ) + const dataRows = table.rows.map((row, ri) => + React.createElement( + View, + { key: `r${ri}`, style: styles.tableRow }, + ...row.map((cell, ci) => React.createElement(Text, { key: ci, style: styles.cell }, cell)), + ), + ) + children.push( + React.createElement( + Page, + { key: `table${t}`, size: "A4", style: styles.page }, + React.createElement(Text, { style: styles.sectionHeading }, table.title), + React.createElement(View, { key: "tableBody" }, headerRow, ...dataRows), + ), + ) + } + + const doc = React.createElement(Document, null, ...children) + return renderToBuffer(doc) +} diff --git a/packages/skills/reports/src/renderers/pptx.ts b/packages/skills/reports/src/renderers/pptx.ts new file mode 100644 index 0000000..c40d448 --- /dev/null +++ b/packages/skills/reports/src/renderers/pptx.ts @@ -0,0 +1,137 @@ +import { createRequire } from "node:module" +import type { MonthlyReportData, RenderOpts } from "../templates/types.js" +import { renderChart } from "./chart.js" + +const require = createRequire(import.meta.url) +// pptxgenjs ships a CJS bundle; load it via require to get the constructor +const PptxGenJS = require("pptxgenjs") as new () => { + layout: string + addSlide(): { + addText(text: string, opts: object): void + addTable(rows: object[], opts: object): void + addImage(opts: object): void + } + write(opts: { outputType: string }): Promise +} + +type PptxRow = { text: string; options?: { bold?: boolean } }[] + +/** + * Render MonthlyReportData to a PowerPoint (PPTX) buffer using pptxgenjs. + * + * Slide layout: + * 1. Title slide — report title + period + * 2. Metrics slide — label/value/unit/change table + * 3+. One slide per chart (PNG embedded via addImage) + * N+. One slide per table + * + * Charts are rendered via chartjs-node-canvas → PNG buffer → base64 → addImage. + * + * @param data - The monthly report data to render. + * @param opts - Render options. + * @returns A Buffer containing the PPTX binary content. + */ +export const renderPptx = async (data: MonthlyReportData, _opts?: RenderOpts): Promise => { + const pptx = new PptxGenJS() + pptx.layout = "LAYOUT_16x9" + + // --- Slide 1: Title --- + const titleSlide = pptx.addSlide() + titleSlide.addText(data.title, { + x: 0.5, + y: 1.5, + w: 9, + h: 1.2, + fontSize: 36, + bold: true, + align: "center", + }) + titleSlide.addText(`${data.period.start} — ${data.period.end}`, { + x: 0.5, + y: 2.9, + w: 9, + h: 0.7, + fontSize: 20, + align: "center", + color: "555555", + }) + + if (data.summary) { + titleSlide.addText(data.summary, { + x: 0.5, + y: 3.8, + w: 9, + h: 1.2, + fontSize: 14, + align: "center", + color: "444444", + }) + } + + // --- Slide 2: Metrics --- + if (data.metrics.length > 0) { + const metricsSlide = pptx.addSlide() + metricsSlide.addText("Metrics", { x: 0.5, y: 0.3, w: 9, h: 0.6, fontSize: 20, bold: true }) + + const headerRow: PptxRow = [ + { text: "Metric", options: { bold: true } }, + { text: "Value", options: { bold: true } }, + { text: "Unit", options: { bold: true } }, + { text: "Change", options: { bold: true } }, + ] + + const metricRows: PptxRow[] = data.metrics.map((m) => [ + { text: m.label }, + { text: String(m.value) }, + { text: m.unit ?? "" }, + { text: m.change !== undefined ? String(m.change) : "" }, + ]) + + metricsSlide.addTable([headerRow, ...metricRows], { + x: 0.5, + y: 1.1, + w: 9, + colW: [3, 2, 2, 2], + fontSize: 13, + }) + } + + // --- Chart slides: one per chart --- + for (const chart of data.charts) { + const chartBuf = await renderChart(chart) + const chartBase64 = chartBuf.toString("base64") + + const chartSlide = pptx.addSlide() + chartSlide.addText(chart.title, { x: 0.5, y: 0.3, w: 9, h: 0.6, fontSize: 20, bold: true }) + chartSlide.addImage({ + data: `image/png;base64,${chartBase64}`, + x: 0.5, + y: 1.1, + w: 9, + h: 4.5, + }) + } + + // --- Table slides: one per table --- + for (const table of data.tables) { + const tableSlide = pptx.addSlide() + tableSlide.addText(table.title, { x: 0.5, y: 0.3, w: 9, h: 0.6, fontSize: 20, bold: true }) + + const headerRow: PptxRow = table.headers.map((h) => ({ text: h, options: { bold: true } })) + const dataRows: PptxRow[] = table.rows.map((row) => row.map((cell) => ({ text: cell }))) + + const colCount = table.headers.length + const colW = Array(colCount).fill(9 / colCount) as number[] + + tableSlide.addTable([headerRow, ...dataRows], { + x: 0.5, + y: 1.1, + w: 9, + colW, + fontSize: 12, + }) + } + + const result = await pptx.write({ outputType: "nodebuffer" }) + return result as Buffer +} diff --git a/packages/skills/reports/src/renderers/xlsx.ts b/packages/skills/reports/src/renderers/xlsx.ts new file mode 100644 index 0000000..42fd668 --- /dev/null +++ b/packages/skills/reports/src/renderers/xlsx.ts @@ -0,0 +1,66 @@ +import ExcelJS from "exceljs" +import type { MonthlyReportData, RenderOpts } from "../templates/types.js" + +/** + * Render MonthlyReportData to an Excel (XLSX) buffer using exceljs. + * + * Sheet layout: + * - Sheet "Metrics": label, value, unit, change columns + * - One sheet per table in data.tables, using the table title as the sheet name + * + * @param data - The monthly report data to render. + * @param opts - Render options. + * @returns A Buffer containing the XLSX binary content. + */ +export const renderXlsx = async (data: MonthlyReportData, _opts?: RenderOpts): Promise => { + const workbook = new ExcelJS.Workbook() + + // --- Sheet 1: Metrics --- + const metricsSheet = workbook.addWorksheet("Metrics") + metricsSheet.columns = [ + { header: "label", key: "label", width: 28 }, + { header: "value", key: "value", width: 20 }, + { header: "unit", key: "unit", width: 14 }, + { header: "change", key: "change", width: 14 }, + ] + const metricsHeader = metricsSheet.getRow(1) + metricsHeader.font = { bold: true } + metricsHeader.commit() + + for (const m of data.metrics) { + metricsSheet.addRow({ + label: m.label, + value: m.value, + unit: m.unit ?? "", + change: m.change ?? "", + }) + } + + // --- One sheet per table --- + for (const table of data.tables) { + // Excel sheet names max 31 chars, strip invalid chars + const sheetName = table.title.replace(/[[\]\\/*?:]/g, "").slice(0, 31) + const sheet = workbook.addWorksheet(sheetName) + + sheet.columns = table.headers.map((h) => ({ + header: h, + key: h, + width: Math.max(h.length + 4, 14), + })) + + const headerRow = sheet.getRow(1) + headerRow.font = { bold: true } + headerRow.commit() + + for (const row of table.rows) { + const rowObj: Record = {} + table.headers.forEach((h, i) => { + rowObj[h] = row[i] ?? "" + }) + sheet.addRow(rowObj) + } + } + + const arrayBuffer = await workbook.xlsx.writeBuffer() + return Buffer.from(arrayBuffer) +} diff --git a/packages/skills/reports/src/templates/monthly-report.ts b/packages/skills/reports/src/templates/monthly-report.ts new file mode 100644 index 0000000..4d2f994 --- /dev/null +++ b/packages/skills/reports/src/templates/monthly-report.ts @@ -0,0 +1,103 @@ +/** + * Built-in monthly report template. + * + * Accepts MonthlyReportData, validates it via TypeBox, and dispatches + * rendering to format-specific renderers. + */ + +import { Type } from "@sinclair/typebox" +import { renderCsv } from "../renderers/csv.js" +import { renderPdf } from "../renderers/pdf.js" +import { renderPptx } from "../renderers/pptx.js" +import { renderXlsx } from "../renderers/xlsx.js" +import type { MonthlyReportData, RenderOpts, ReportFormat, ReportTemplate } from "./types.js" + +// --------------------------------------------------------------------------- +// TypeBox schema (mirrors the MonthlyReportData interface in types.ts) +// --------------------------------------------------------------------------- + +const MetricRowSchema = Type.Object({ + label: Type.String(), + value: Type.Number(), + unit: Type.Optional(Type.String()), + change: Type.Optional(Type.Number()), +}) + +const ChartDatasetSchema = Type.Object({ + label: Type.String(), + data: Type.Array(Type.Number()), + backgroundColor: Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())])), + borderColor: Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())])), +}) + +const ChartDefinitionSchema = Type.Object({ + type: Type.Union([Type.Literal("bar"), Type.Literal("line"), Type.Literal("pie")]), + title: Type.String(), + labels: Type.Array(Type.String()), + datasets: Type.Array(ChartDatasetSchema), +}) + +const TableDefinitionSchema = Type.Object({ + title: Type.String(), + headers: Type.Array(Type.String()), + rows: Type.Array(Type.Array(Type.String())), +}) + +/** TypeBox schema for {@link MonthlyReportData}. Exported for use by the tool layer. */ +export const MonthlyReportDataSchema = Type.Object({ + title: Type.String({ minLength: 1 }), + period: Type.Object({ + start: Type.String({ minLength: 1 }), + end: Type.String({ minLength: 1 }), + }), + metrics: Type.Array(MetricRowSchema), + charts: Type.Array(ChartDefinitionSchema), + tables: Type.Array(TableDefinitionSchema), + summary: Type.Optional(Type.String()), +}) + +// --------------------------------------------------------------------------- +// Renderer dispatcher +// --------------------------------------------------------------------------- + +const renderMonthlyReport = async ( + format: ReportFormat, + data: MonthlyReportData, + opts: RenderOpts, +): Promise => { + switch (format) { + case "pdf": + return renderPdf(data, opts) + case "pptx": + return renderPptx(data, opts) + case "csv": + return renderCsv(data) + case "xlsx": + return renderXlsx(data, opts) + case "png": + case "svg": + throw new Error( + `Format '${format}' is not supported by the monthly-report template directly. Use report_execute_code to generate charts as standalone image files.`, + ) + default: { + const _exhaustive: never = format + throw new Error(`Unsupported format: ${String(_exhaustive)}`) + } + } +} + +// --------------------------------------------------------------------------- +// Template definition +// --------------------------------------------------------------------------- + +/** Built-in monthly report template. */ +export const MonthlyReportTemplate: ReportTemplate = { + name: "monthly-report", + label: "Monthly Report", + description: + "A structured monthly report with summary metrics, embedded charts, and data tables. " + + "Supports PDF, PPTX, CSV, and XLSX output formats.", + schema: MonthlyReportDataSchema, + formats: ["pdf", "pptx", "csv", "xlsx"], + render: renderMonthlyReport, +} diff --git a/packages/skills/reports/src/templates/registry.test.ts b/packages/skills/reports/src/templates/registry.test.ts new file mode 100644 index 0000000..2bfedb9 --- /dev/null +++ b/packages/skills/reports/src/templates/registry.test.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from "vitest" +import { getTemplate, listTemplates, registerTemplate } from "./registry.js" +import type { MonthlyReportData, ReportTemplate } from "./types.js" + +describe("template registry", () => { + it("lists built-in monthly-report template", () => { + const templates = listTemplates() + const names = templates.map((t) => t.name) + expect(names).toContain("monthly-report") + }) + + it("getTemplate returns the monthly-report template", () => { + const tmpl = getTemplate("monthly-report") + expect(tmpl).toBeDefined() + expect(tmpl?.name).toBe("monthly-report") + expect(tmpl?.label).toBe("Monthly Report") + expect(tmpl?.formats).toContain("pdf") + expect(tmpl?.formats).toContain("csv") + }) + + it("getTemplate returns undefined for unknown name", () => { + expect(getTemplate("nonexistent-report")).toBeUndefined() + }) + + it("registerTemplate adds a custom template visible in listTemplates", () => { + const custom: ReportTemplate = { + name: "custom-test", + label: "Custom Test Report", + description: "A test template", + schema: {} as never, + formats: ["csv"], + render: async () => Buffer.from(""), + } + + registerTemplate(custom) + + const found = getTemplate("custom-test") + expect(found).toBeDefined() + expect(found?.name).toBe("custom-test") + + const names = listTemplates().map((t) => t.name) + expect(names).toContain("custom-test") + }) + + it("registerTemplate overwrites an existing template with the same name", () => { + const makeTemplate = (label: string): ReportTemplate => ({ + name: "overwrite-test", + label, + description: "", + schema: {} as never, + formats: ["pdf"], + render: async (_format, _data: MonthlyReportData) => Buffer.from(""), + }) + + registerTemplate(makeTemplate("Version 1")) + registerTemplate(makeTemplate("Version 2")) + + const found = getTemplate("overwrite-test") + expect(found?.label).toBe("Version 2") + }) +}) diff --git a/packages/skills/reports/src/templates/registry.ts b/packages/skills/reports/src/templates/registry.ts new file mode 100644 index 0000000..39ccbd6 --- /dev/null +++ b/packages/skills/reports/src/templates/registry.ts @@ -0,0 +1,39 @@ +/** + * Template registry for the report generation skill. + * + * Built-in templates are registered on module load. Custom templates can be + * added at runtime via registerTemplate(), making this the extension point + * for adding templates beyond the built-in set. + */ + +import { MonthlyReportTemplate } from "./monthly-report.js" +import type { ReportTemplate } from "./types.js" + +const registry = new Map([[MonthlyReportTemplate.name, MonthlyReportTemplate]]) + +/** + * Register a report template. + * + * If a template with the same name already exists it will be overwritten. + * Use this to add custom templates at application startup. + * + * @param template - Template to register. + */ +export const registerTemplate = (template: ReportTemplate): void => { + registry.set(template.name, template) +} + +/** + * List all registered report templates. + * + * @returns Array of all registered templates. + */ +export const listTemplates = (): ReportTemplate[] => Array.from(registry.values()) + +/** + * Look up a template by name. + * + * @param name - Template identifier, e.g. "monthly-report". + * @returns The template, or undefined if not found. + */ +export const getTemplate = (name: string): ReportTemplate | undefined => registry.get(name) diff --git a/packages/skills/reports/src/templates/types.ts b/packages/skills/reports/src/templates/types.ts new file mode 100644 index 0000000..f63173b --- /dev/null +++ b/packages/skills/reports/src/templates/types.ts @@ -0,0 +1,112 @@ +/** + * Core types for the report generation skill. + * + * MonthlyReportData is the canonical data shape accepted by the built-in + * monthly-report template. Custom templates may define their own shapes. + */ +import type { TSchema } from "@sinclair/typebox" + +/** Output format supported by report templates. */ +export type ReportFormat = "pdf" | "pptx" | "csv" | "xlsx" | "png" | "svg" + +/** Options passed to a template renderer. */ +export interface RenderOpts { + /** Directory where rendered output files are written. */ + outputDir: string +} + +/** A single dataset within a chart. */ +export interface ChartDataset { + /** Dataset label shown in the chart legend. */ + label: string + /** Numeric data values aligned with the chart's labels array. */ + data: number[] + /** Optional bar/area fill color(s). */ + backgroundColor?: string | string[] + /** Optional line border color(s). */ + borderColor?: string | string[] +} + +/** A chart definition embedded in a report. */ +export interface ChartDefinition { + /** Chart type. */ + type: "bar" | "line" | "pie" + /** Chart title displayed above the chart. */ + title: string + /** X-axis / slice labels. */ + labels: string[] + /** One or more datasets to plot. */ + datasets: ChartDataset[] +} + +/** A table definition embedded in a report. */ +export interface TableDefinition { + /** Table title displayed above the table. */ + title: string + /** Column header labels. */ + headers: string[] + /** Data rows — each inner array must have the same length as headers. */ + rows: string[][] +} + +/** A single summary metric row. */ +export interface MetricRow { + /** Human-readable metric name. */ + label: string + /** Numeric value. */ + value: number + /** Optional unit suffix, e.g. "%" or "ms". */ + unit?: string + /** Optional period-over-period change, e.g. 0.12 for +12%. */ + change?: number +} + +/** + * Canonical data shape for the built-in monthly-report template. + * + * All fields except summary are required. charts and tables may be empty + * arrays when not applicable, but must be present. + */ +export interface MonthlyReportData { + /** Report title. */ + title: string + /** Reporting period. */ + period: { start: string; end: string } + /** Summary metrics displayed in the metrics section. */ + metrics: MetricRow[] + /** Charts to embed. Maximum 20 per render call. */ + charts: ChartDefinition[] + /** Tables to embed. */ + tables: TableDefinition[] + /** Optional executive summary paragraph. */ + summary?: string +} + +/** + * A report template definition. + * + * Register custom templates at startup via registerTemplate() from the + * registry module. The registry is the extension point for adding new + * templates beyond the built-in ones. + */ +export interface ReportTemplate { + /** Unique machine-readable name, e.g. "monthly-report". */ + name: string + /** Human-readable display label. */ + label: string + /** Short description of what the template produces. */ + description: string + /** TypeBox schema for the data payload accepted by this template. */ + schema: TSchema + /** Output formats this template supports. */ + formats: ReportFormat[] + /** + * Render the template to a Buffer. + * + * @param format - Requested output format. + * @param data - Validated template data. + * @param opts - Render options (output directory, etc.). + * @returns Buffer containing the rendered output bytes. + */ + render: (format: ReportFormat, data: MonthlyReportData, opts: RenderOpts) => Promise +} diff --git a/packages/skills/reports/src/tools.test.ts b/packages/skills/reports/src/tools.test.ts new file mode 100644 index 0000000..acb8194 --- /dev/null +++ b/packages/skills/reports/src/tools.test.ts @@ -0,0 +1,97 @@ +import type { ExtensionContext } from "@mariozechner/pi-coding-agent" +import type { Type } from "@sinclair/typebox" +import { describe, expect, it } from "vitest" +import { createReportExecuteCodeTool, createReportGenerateTool, createReportListTemplatesTool } from "./tools.js" + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +// Minimal stub — tests don't rely on ctx methods. +const stubCtx = {} as ExtensionContext + +const invoke = async (tool: ReturnType, params: unknown) => { + const result = await tool.execute("test-call-id", params, new AbortController().signal, () => {}, stubCtx) + return result.content[0].type === "text" ? (result.content[0] as { type: "text"; text: string }).text : "" +} + +// ─── report_list_templates ──────────────────────────────────────────────────── + +describe("report_list_templates", () => { + it("returns an array that includes the monthly-report template", async () => { + const tool = createReportListTemplatesTool() + const output = await invoke(tool, {}) + const templates = JSON.parse(output) as { name: string }[] + expect(Array.isArray(templates)).toBe(true) + const names = templates.map((t) => t.name) + expect(names).toContain("monthly-report") + }) +}) + +// ─── report_generate ───────────────────────────────────────────────────────── + +describe("report_generate", () => { + it("returns an error for an unknown template name", async () => { + const tool = createReportGenerateTool() + const output = await invoke(tool, { + template: "does-not-exist", + format: "pdf", + data: {}, + }) + expect(output).toContain("Unknown template: does-not-exist") + }) + + it("returns an error when charts array exceeds 20 entries", async () => { + const tool = createReportGenerateTool() + const charts = Array.from({ length: 21 }, (_, i) => ({ + type: "bar" as const, + title: `Chart ${i}`, + labels: ["A"], + datasets: [{ label: "ds", data: [i] }], + })) + const output = await invoke(tool, { + template: "monthly-report", + format: "csv", + data: { + title: "Test", + period: { start: "2025-01-01", end: "2025-01-31" }, + metrics: [], + charts, + tables: [], + }, + }) + expect(output).toContain("Chart limit exceeded") + expect(output).toContain("21") + }) + + it("returns a schema validation error for missing required field", async () => { + const tool = createReportGenerateTool() + // 'title' is required by the monthly-report schema but omitted here + const output = await invoke(tool, { + template: "monthly-report", + format: "csv", + data: { + period: { start: "2025-01-01", end: "2025-01-31" }, + metrics: [], + charts: [], + tables: [], + }, + }) + expect(output).toContain("Validation errors") + }) +}) + +// ─── report_execute_code ────────────────────────────────────────────────────── + +describe("report_execute_code", () => { + it("has the expected parameter shape", () => { + const tool = createReportExecuteCodeTool() + expect(tool.name).toBe("report_execute_code") + + const paramSchema = tool.parameters as ReturnType + const props = paramSchema.properties as Record + + expect(props).toHaveProperty("language") + expect(props).toHaveProperty("code") + expect(props).toHaveProperty("dependencies") + expect(props).toHaveProperty("outputDir") + }) +}) diff --git a/packages/skills/reports/src/tools.ts b/packages/skills/reports/src/tools.ts new file mode 100644 index 0000000..9403a6c --- /dev/null +++ b/packages/skills/reports/src/tools.ts @@ -0,0 +1,247 @@ +import { execFileSync } from "node:child_process" +import { randomUUID } from "node:crypto" +import { mkdirSync, readdirSync, statSync, writeFileSync } from "node:fs" +import type { AgentToolResult } from "@mariozechner/pi-agent-core" +import type { ToolDefinition } from "@mariozechner/pi-coding-agent" +import { Type } from "@sinclair/typebox" +import type { TSchema } from "@sinclair/typebox" +import { Value } from "@sinclair/typebox/value" +import { getTemplate, listTemplates } from "./templates/registry.js" +import type { MonthlyReportData } from "./templates/types.js" + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +const textResult = (text: string): AgentToolResult => ({ + content: [{ type: "text", text }], + details: {}, +}) + +const DEFAULT_OUTPUT_DIR = "/workspace/output" + +const MIME_MAP: Record = { + png: "image/png", + svg: "image/svg+xml", + pdf: "application/pdf", + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", + csv: "text/csv", + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", +} + +const OUTPUT_EXTENSIONS = new Set(["png", "svg", "pdf", "pptx", "csv", "xlsx"]) + +// ─── Tool factories ─────────────────────────────────────────────────────────── + +/** + * Create the report_list_templates tool. + * + * Returns a JSON array of all registered report templates, including their + * name, label, description, and supported output formats. + */ +export const createReportListTemplatesTool = (_opts?: { outputDir?: string }): ToolDefinition => ({ + name: "report_list_templates", + label: "List Report Templates", + description: "List all available report templates with their names, descriptions, and supported formats.", + promptSnippet: "report_list_templates() — list available report templates", + parameters: Type.Object({}), + execute: async (_toolCallId, _params, _signal, _onUpdate, _ctx): Promise> => { + const templates = listTemplates().map((t) => ({ + name: t.name, + label: t.label, + description: t.description, + formats: t.formats, + })) + return textResult(JSON.stringify(templates, null, 2)) + }, +}) + +/** + * Create the report_generate tool. + * + * Validates the input data against the template's TypeBox schema, renders + * the report, writes it to the output directory, and returns the file path + * and size. + * + * @param opts.outputDir - Override the output directory (default: /workspace/output). + */ +export const createReportGenerateTool = (opts?: { outputDir?: string }): ToolDefinition => ({ + name: "report_generate", + label: "Generate Report", + description: + "Generate a report or chart from a registered template and structured data. " + + "Use this tool (not matplotlib or custom code) whenever the user asks for a chart, graph, or report. " + + "Supports pdf, png, svg, xlsx, csv formats. Returns the file path and size of the generated artifact.", + promptSnippet: "report_generate(template, format, data) — preferred way to render charts and reports", + parameters: Type.Object({ + template: Type.String({ description: "Template name, e.g. 'monthly-report'." }), + format: Type.Union( + [ + Type.Literal("pdf"), + Type.Literal("pptx"), + Type.Literal("csv"), + Type.Literal("xlsx"), + Type.Literal("png"), + Type.Literal("svg"), + ], + { description: "Output format." }, + ), + data: Type.Object( + {}, + { + additionalProperties: true, + description: "Structured data matching the template schema.", + }, + ), + outputFilename: Type.Optional(Type.String({ description: "Override the output filename." })), + }), + execute: async (_toolCallId, params, _signal, _onUpdate, _ctx): Promise> => { + const p = params as { + template: string + format: "pdf" | "pptx" | "csv" | "xlsx" | "png" | "svg" + data: Record + outputFilename?: string + } + + const template = getTemplate(p.template) + if (!template) { + return textResult(`Unknown template: ${p.template}`) + } + + // Schema validation + if (!Value.Check(template.schema as TSchema, p.data)) { + const errors = [...Value.Errors(template.schema as TSchema, p.data)] + const lines = errors.map((e) => ` - ${e.path || "/"}: ${e.message}`) + return textResult(`Validation errors:\n${lines.join("\n")}`) + } + + // Chart limit guard + const charts = (p.data as { charts?: unknown[] }).charts + if (Array.isArray(charts) && charts.length > 20) { + return textResult( + `Chart limit exceeded: maximum 20 charts per report. You provided ${charts.length}. Split into multiple reports or reduce the number of charts.`, + ) + } + + const outputDir = opts?.outputDir ?? DEFAULT_OUTPUT_DIR + mkdirSync(outputDir, { recursive: true }) + + const buffer = await template.render(p.format, p.data as unknown as MonthlyReportData, { outputDir }) + + const filename = p.outputFilename ?? `${p.template}-${Date.now()}.${p.format}` + const outPath = `${outputDir}/${filename}` + writeFileSync(outPath, buffer) + + const sizeBytes = statSync(outPath).size + + return textResult(JSON.stringify({ path: outPath, filename, sizeBytes }, null, 2)) + }, +}) + +/** + * Create the report_execute_code tool. + * + * Installs optional dependencies, writes code to a temp file, executes it + * inside /workspace, and returns paths to any generated output files together + * with captured stdout. + */ +export const createReportExecuteCodeTool = (opts?: { outputDir?: string }): ToolDefinition => ({ + name: "report_execute_code", + label: "Execute Report Code", + description: + "Fallback tool: execute Python or JavaScript code to generate charts or reports when report_generate cannot satisfy the request. " + + "Code MUST save all output files to /workspace/output/ — files saved elsewhere will not appear as artifacts. " + + "Returns file paths and stdout.", + promptSnippet: + "report_execute_code(language, code, dependencies?, outputDir?) — fallback: run custom code that saves files to /workspace/output/", + parameters: Type.Object({ + language: Type.Union([Type.Literal("python"), Type.Literal("javascript")], { + description: "Runtime to use.", + }), + code: Type.String({ description: "Code to execute." }), + dependencies: Type.Optional( + Type.Array(Type.String(), { description: "Additional packages to install before execution." }), + ), + outputDir: Type.Optional( + Type.String({ description: "Override the output directory (default: /workspace/output)." }), + ), + }), + execute: async (_toolCallId, params, _signal, _onUpdate, _ctx): Promise> => { + const p = params as { + language: "python" | "javascript" + code: string + dependencies?: string[] + outputDir?: string + } + + const outputDir = p.outputDir ?? opts?.outputDir ?? DEFAULT_OUTPUT_DIR + mkdirSync(outputDir, { recursive: true }) + + // Install dependencies + if (p.dependencies && p.dependencies.length > 0) { + try { + if (p.language === "python") { + execFileSync("pip3", ["install", "--break-system-packages", ...p.dependencies], { + timeout: 30000, + }) + } else { + execFileSync("npm", ["install", "-g", ...p.dependencies], { + timeout: 30000, + }) + } + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + return textResult(`Dependency installation failed: ${msg}`) + } + } + + // Write code to temp file + const ext = p.language === "python" ? "py" : "js" + mkdirSync("/tmp/agent", { recursive: true }) + const scriptPath = `/tmp/agent/report_${randomUUID()}.${ext}` + writeFileSync(scriptPath, p.code) + + // Execute + let stdout = "" + try { + const runtime = + p.language === "python" + ? (() => { + try { + execFileSync("python3", ["--version"]) + return "python3" + } catch { + return "python" + } + })() + : "node" + const result = execFileSync(runtime, [scriptPath], { + timeout: 60000, + cwd: "/workspace", + encoding: "utf-8", + }) + stdout = result + } catch (err) { + const execErr = err as NodeJS.ErrnoException & { stderr?: string } + const msg = execErr.stderr ?? execErr.message ?? String(err) + return textResult(msg) + } + + // Collect output files + const files = readdirSync(outputDir) + .filter((f) => { + const ext = f.split(".").pop() ?? "" + return OUTPUT_EXTENSIONS.has(ext) + }) + .map((filename) => { + const filePath = `${outputDir}/${filename}` + const ext = filename.split(".").pop() ?? "" + return { + path: filePath, + filename, + sizeBytes: statSync(filePath).size, + mimeType: MIME_MAP[ext] ?? "application/octet-stream", + } + }) + + return textResult(JSON.stringify({ files, stdout }, null, 2)) + }, +}) diff --git a/packages/skills/reports/tsconfig.json b/packages/skills/reports/tsconfig.json index 7cb90b0..714f148 100644 --- a/packages/skills/reports/tsconfig.json +++ b/packages/skills/reports/tsconfig.json @@ -2,7 +2,9 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "jsx": "react-jsx", + "jsxImportSource": "react" }, "include": ["src"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8272f05..ec61707 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -372,6 +372,9 @@ importers: '@openzosma/memory': specifier: workspace:* version: link:../memory + '@openzosma/skill-reports': + specifier: workspace:* + version: link:../skills/reports '@sinclair/typebox': specifier: ^0.34.48 version: 0.34.48 @@ -672,13 +675,47 @@ importers: version: 5.9.3 packages/skills/reports: + dependencies: + '@mariozechner/pi-agent-core': + specifier: ^0.61.0 + version: 0.61.1(ws@8.19.0)(zod@4.3.6) + '@mariozechner/pi-coding-agent': + specifier: ^0.61.0 + version: 0.61.0(ws@8.19.0)(zod@4.3.6) + '@react-pdf/renderer': + specifier: ^4.3.0 + version: 4.3.2(react@19.2.4) + '@sinclair/typebox': + specifier: ^0.34.48 + version: 0.34.48 + chart.js: + specifier: ^4.4.9 + version: 4.5.1 + chartjs-node-canvas: + specifier: ^4.1.6 + version: 4.1.6(chart.js@4.5.1) + exceljs: + specifier: ^4.4.0 + version: 4.4.0 + pptxgenjs: + specifier: ^3.12.0 + version: 3.12.0 + react: + specifier: ^19.1.0 + version: 19.2.4 devDependencies: '@types/node': specifier: ^22.15.2 version: 22.19.15 + '@types/react': + specifier: ^19.1.2 + version: 19.2.14 typescript: specifier: ^5.7.3 version: 5.9.3 + vitest: + specifier: ^3.1.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2) packages: @@ -1192,6 +1229,12 @@ packages: cpu: [x64] os: [win32] + '@fast-csv/format@4.3.5': + resolution: {integrity: sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==} + + '@fast-csv/parse@4.3.6': + resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} + '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} @@ -1420,6 +1463,13 @@ packages: '@js-sdsl/ordered-map@4.4.2': resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@kurkle/color@0.3.4': + resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} + + '@mapbox/node-pre-gyp@1.0.11': + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + '@mariozechner/clipboard-darwin-arm64@0.3.2': resolution: {integrity: sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==} engines: {node: '>= 10'} @@ -2421,6 +2471,49 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@react-pdf/fns@3.1.2': + resolution: {integrity: sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==} + + '@react-pdf/font@4.0.4': + resolution: {integrity: sha512-8YtgGtL511txIEc9AjiilpZ7yjid8uCd8OGUl6jaL3LIHnrToUupSN4IzsMQpVTCMYiDLFnDNQzpZsOYtRS/Pg==} + + '@react-pdf/image@3.0.4': + resolution: {integrity: sha512-z0ogVQE0bKqgXQ5smgzIU857rLV7bMgVdrYsu3UfXDDLSzI7QPvzf6MFTFllX6Dx2rcsF13E01dqKPtJEM799g==} + + '@react-pdf/layout@4.4.2': + resolution: {integrity: sha512-gNu2oh8MiGR+NJZYTJ4c4q0nWCESBI6rKFiodVhE7OeVAjtzZzd6l65wsN7HXdWJqOZD3ttD97iE+tf5SOd/Yg==} + + '@react-pdf/pdfkit@4.1.0': + resolution: {integrity: sha512-Wm/IOAv0h/U5Ra94c/PltFJGcpTUd/fwVMVeFD6X9tTTPCttIwg0teRG1Lqq617J8K4W7jpL/B0HTH0mjp3QpQ==} + + '@react-pdf/png-js@3.0.0': + resolution: {integrity: sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==} + + '@react-pdf/primitives@4.1.1': + resolution: {integrity: sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==} + + '@react-pdf/reconciler@2.0.0': + resolution: {integrity: sha512-7zaPRujpbHSmCpIrZ+b9HSTJHthcVZzX0Wx7RzvQGsGBUbHP4p6s5itXrAIOuQuPvDepoHGNOvf6xUuMVvdoyw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@react-pdf/render@4.3.2': + resolution: {integrity: sha512-el5KYM1sH/PKcO4tRCIm8/AIEmhtraaONbwCrBhFdehoGv6JtgnXiMxHGAvZbI5kEg051GbyP+XIU6f6YbOu6Q==} + + '@react-pdf/renderer@4.3.2': + resolution: {integrity: sha512-EhPkj35gO9rXIyyx29W3j3axemvVY5RigMmlK4/6Ku0pXB8z9PEE/sz4ZBOShu2uot6V4xiCR3aG+t9IjJJlBQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@react-pdf/stylesheet@6.1.2': + resolution: {integrity: sha512-E3ftGRYUQGKiN3JOgtGsLDo0hGekA6dmkmi/MYACytmPTKxQRBSO3126MebmCq+t1rgU9uRlREIEawJ+8nzSbw==} + + '@react-pdf/textkit@6.1.0': + resolution: {integrity: sha512-sFlzDC9CDFrJsnL3B/+NHrk9+Advqk7iJZIStiYQDdskbow8GF/AGYrpIk+vWSnh35YxaGbHkqXq53XOxnyrjQ==} + + '@react-pdf/types@2.9.2': + resolution: {integrity: sha512-dufvpKId9OajLLbgn9q7VLUmyo1Jf+iyGk2ZHmCL8nIDtL8N1Ejh9TH7+pXXrR0tdie1nmnEb5Bz9U7g4hI4/g==} + '@remirror/core-constants@3.0.0': resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} @@ -3353,6 +3446,12 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@14.18.63': + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + '@types/node@22.19.15': resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} @@ -3463,6 +3562,12 @@ packages: resolution: {integrity: sha512-JtCjTvbBVNP43mmuCqhSXk16XSKE5L4/4wbVFJsz6K2syfplNUnsZxHxnqJ0dQoe3Fy70V09uWI29uaXkNdjrg==} engines: {node: '>=16.0.0'} + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + abs-svg-path@0.1.1: + resolution: {integrity: sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -3472,6 +3577,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -3508,6 +3617,26 @@ packages: any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + aproba@2.1.0: + resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -3532,6 +3661,9 @@ packages: async@3.2.3: resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -3555,6 +3687,10 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + base64-js@0.0.8: + resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} + engines: {node: '>= 0.4'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -3640,9 +3776,25 @@ packages: zod: optional: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + binary@0.3.0: + resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -3653,10 +3805,22 @@ packages: bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + brace-expansion@1.1.13: + resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==} + + brace-expansion@2.0.3: + resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + brace-expansion@5.0.4: resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} engines: {node: 18 || 20 || >=22} + brotli@1.3.3: + resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + bson@7.2.0: resolution: {integrity: sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==} engines: {node: '>=20.19.0'} @@ -3667,6 +3831,17 @@ packages: buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-indexof-polyfill@1.0.2: + resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} + engines: {node: '>=0.10'} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffers@0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -3690,6 +3865,10 @@ packages: caniuse-lite@1.0.30001780: resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==} + canvas@2.11.2: + resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} + engines: {node: '>=6'} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -3697,6 +3876,9 @@ packages: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} + chainsaw@0.1.0: + resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -3717,6 +3899,15 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + chart.js@4.5.1: + resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} + engines: {pnpm: '>=8'} + + chartjs-node-canvas@4.1.6: + resolution: {integrity: sha512-UQJbPWrvqB/FoLclGA9BaLQmZbzSYlujF4w8NZd6Xzb+sqgACBb2owDX6m7ifCXLjUW5Nz0Qx0qqrTtQkkSoYw==} + peerDependencies: + chart.js: ^3.5.1 + check-error@2.1.3: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} @@ -3729,6 +3920,10 @@ packages: chevrotain@11.1.2: resolution: {integrity: sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==} + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -3753,6 +3948,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -3770,6 +3969,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + colors@1.0.3: resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} engines: {node: '>=0.1.90'} @@ -3793,9 +3999,19 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + content-disposition@1.0.1: resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} engines: {node: '>=18'} @@ -3812,6 +4028,9 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} @@ -3826,6 +4045,15 @@ packages: resolution: {integrity: sha512-/2yieBqvMcRj8McNzkycjW2v3OIUOibBfd2dLEJ0nWts8NobAxwiyw9phVNS6oDL8x8tz9F7uNVFEVpJncQpeA==} engines: {node: '>=8.0.0'} + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -3833,6 +4061,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -4054,6 +4285,10 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + decompress-response@4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -4076,6 +4311,9 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -4098,6 +4336,9 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dfa@1.2.0: + resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==} + diff@8.0.3: resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} engines: {node: '>=0.3.1'} @@ -4120,6 +4361,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -4139,6 +4383,9 @@ packages: embla-carousel@8.6.0: resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==} + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -4239,6 +4486,10 @@ packages: eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + eventsource-parser@3.0.6: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} @@ -4247,6 +4498,10 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} + exceljs@4.4.0: + resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} + engines: {node: '>=8.3.0'} + execa@9.6.1: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} @@ -4271,6 +4526,10 @@ packages: resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} engines: {node: '> 0.1.90'} + fast-csv@4.3.6: + resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} + engines: {node: '>=10.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -4332,6 +4591,9 @@ packages: debug: optional: true + fontkit@2.0.4: + resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -4362,14 +4624,34 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + fstream@1.0.12: + resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} + engines: {node: '>=0.6'} + deprecated: This package is no longer supported. + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + gaxios@7.1.4: resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} engines: {node: '>=18'} @@ -4420,6 +4702,10 @@ packages: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + google-auth-library@10.6.2: resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} engines: {node: '>=18'} @@ -4450,6 +4736,9 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -4511,6 +4800,12 @@ packages: resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} engines: {node: ^20.17.0 || >=22.9.0} + hsl-to-hex@1.0.0: + resolution: {integrity: sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==} + + hsl-to-rgb-for-reals@1.1.1: + resolution: {integrity: sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -4525,14 +4820,24 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + https@1.0.0: + resolution: {integrity: sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==} + human-signals@8.0.1: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} engines: {node: '>=18.18.0'} + hyphen@1.14.1: + resolution: {integrity: sha512-kvL8xYl5QMTh+LwohVN72ciOxC0OEV79IPdJSTwEXok9y9QHebXGdFgrED4sWfiax/ODx++CAMk3hMy4XPJPOw==} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -4548,10 +4853,22 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} + image-size@1.2.1: + resolution: {integrity: sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==} + engines: {node: '>=16.x'} + hasBin: true + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + inflection@1.13.4: resolution: {integrity: sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==} engines: {'0': node >= 0.4.0} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -4582,6 +4899,9 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -4621,12 +4941,21 @@ packages: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + jay-peg@1.1.1: + resolution: {integrity: sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -4660,6 +4989,9 @@ packages: resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} engines: {node: '>=12', npm: '>=6'} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + jwa@2.0.1: resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} @@ -4694,6 +5026,13 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lightningcss-android-arm64@1.32.0: resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} @@ -4768,12 +5107,18 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + linebreak@1.1.0: + resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} + linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} linkifyjs@4.3.2: resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} + listenercount@1.0.1: + resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -4787,15 +5132,37 @@ packages: lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.escaperegexp@4.1.2: + resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.groupby@4.6.0: + resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + lodash.isinteger@4.0.4: resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + lodash.isnil@4.0.0: + resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} + lodash.isnumber@3.0.3: resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} @@ -4805,9 +5172,18 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.isundefined@3.0.1: + resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} @@ -4849,6 +5225,10 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + markdown-it@14.1.1: resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true @@ -4926,6 +5306,9 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-engine@1.0.3: + resolution: {integrity: sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -5072,21 +5455,49 @@ packages: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} + mimic-response@2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} + minimatch@10.2.4: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + minipass@7.1.3: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + mlly@1.8.1: resolution: {integrity: sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==} @@ -5224,6 +5635,15 @@ packages: engines: {node: '>=10.5.0'} deprecated: Use your platform's native DOMException instead + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + node-fetch@3.3.2: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5233,10 +5653,26 @@ packages: engines: {node: '>=0.1.97'} os: [linux, darwin, freebsd, win32, smartos, sunos] + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-svg-path@1.1.0: + resolution: {integrity: sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==} + npm-run-path@6.0.0: resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} engines: {node: '>=18'} + npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5312,6 +5748,12 @@ packages: package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + pako@0.2.9: + resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parse-database-url@0.3.0: resolution: {integrity: sha512-YRxDoVBAUk3ksGF9pud+aqWwXmThZzhX9Z1PPxKU03BB3/gu2RcgyMA4rktMYhkIJ9KxwW7lIj00U+TSNz80wg==} engines: {node: '>= 0.6'} @@ -5323,6 +5765,9 @@ packages: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} + parse-svg-path@0.1.2: + resolution: {integrity: sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==} + parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} @@ -5353,6 +5798,10 @@ packages: resolution: {integrity: sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==} engines: {node: '>=14.0.0'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -5431,6 +5880,9 @@ packages: points-on-path@0.2.1: resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -5455,10 +5907,16 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + pptxgenjs@3.12.0: + resolution: {integrity: sha512-ZozkYKWb1MoPR4ucw3/aFYlHkVIJxo9czikEclcUVnS4Iw/M+r+TEwdlB3fyAWO9JY1USxJDt0Y0/r15IR/RUA==} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + prompt@1.3.0: resolution: {integrity: sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==} engines: {node: '>= 6.0.0'} @@ -5560,6 +6018,9 @@ packages: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} + queue@6.0.2: + resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + radix-ui@1.4.3: resolution: {integrity: sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==} peerDependencies: @@ -5664,6 +6125,16 @@ packages: resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} engines: {node: '>=0.8'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} @@ -5752,6 +6223,9 @@ packages: engines: {node: '>= 0.4'} hasBin: true + restructure@3.0.2: + resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==} + retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -5764,6 +6238,16 @@ packages: resolution: {integrity: sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==} engines: {node: '>= 0.4.0'} + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -5788,12 +6272,22 @@ packages: rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + + scheduler@0.25.0-rc-603e6108-20241029: + resolution: {integrity: sha512-pFwF6H1XrSdYYNLfOcGlM28/j8CGLu8IvdrxqhjWULe2bPcKiKW4CV+OWqR/9fT52mywx65l7ysNkjLKBda7eA==} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -5801,6 +6295,10 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.7.4: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} @@ -5820,6 +6318,9 @@ packages: set-cookie-parser@3.0.1: resolution: {integrity: sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -5864,6 +6365,15 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@3.1.1: + resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -5933,6 +6443,12 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -5992,6 +6508,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-arc-to-cubic-bezier@3.2.0: + resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==} + tailwind-merge@3.5.0: resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} @@ -6002,6 +6521,15 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -6009,6 +6537,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -6038,6 +6569,10 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -6049,10 +6584,16 @@ packages: tokenlens@1.3.1: resolution: {integrity: sha512-7oxmsS5PNCX3z+b+z07hL5vCzlgHKkCGrEQjQmWl5l+v5cUrtL7S1cuST4XThaL1XyjbTX8J5hfP0cjDJRkaLA==} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} + traverse@0.3.9: + resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -6120,6 +6661,9 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -6127,6 +6671,12 @@ packages: resolution: {integrity: sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==} engines: {node: '>=20.18.1'} + unicode-properties@1.4.1: + resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} + + unicode-trie@2.0.0: + resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -6159,6 +6709,9 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unzipper@0.10.14: + resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} + use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -6195,6 +6748,9 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true @@ -6203,6 +6759,10 @@ packages: resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} hasBin: true + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -6225,6 +6785,10 @@ packages: victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} + vite-compatible-readable-stream@3.6.1: + resolution: {integrity: sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==} + engines: {node: '>= 6'} + vite-node@3.2.4: resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6328,6 +6892,9 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -6336,6 +6903,9 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + when@2.0.1: resolution: {integrity: sha512-h0l57vFJ4YQe1/U+C+oqBfAoopxXABUm6VqWM0x2gg4pARru4IUWo/PAxyawWgbGtndXrZbA41EzsfxacZVEXQ==} @@ -6352,6 +6922,9 @@ packages: engines: {node: '>=8'} hasBin: true + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + winston@2.4.7: resolution: {integrity: sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==} engines: {node: '>= 0.10.0'} @@ -6379,6 +6952,9 @@ packages: utf-8-validate: optional: true + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6390,6 +6966,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.8.2: resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} @@ -6426,6 +7005,13 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} + yoga-layout@3.2.1: + resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: @@ -7123,6 +7709,25 @@ snapshots: '@esbuild/win32-x64@0.27.4': optional: true + '@fast-csv/format@4.3.5': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.isboolean: 3.0.3 + lodash.isequal: 4.5.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + + '@fast-csv/parse@4.3.6': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.groupby: 4.6.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + lodash.isundefined: 3.0.1 + lodash.uniq: 4.5.0 + '@floating-ui/core@1.7.5': dependencies: '@floating-ui/utils': 0.2.11 @@ -7302,6 +7907,23 @@ snapshots: '@js-sdsl/ordered-map@4.4.2': {} + '@kurkle/color@0.3.4': {} + + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.1.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.7.4 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + '@mariozechner/clipboard-darwin-arm64@0.3.2': optional: true @@ -8345,19 +8967,120 @@ snapshots: '@radix-ui/rect@1.1.1': {} - '@remirror/core-constants@3.0.0': {} - - '@rollup/rollup-android-arm-eabi@4.60.0': - optional: true + '@react-pdf/fns@3.1.2': {} - '@rollup/rollup-android-arm64@4.60.0': - optional: true + '@react-pdf/font@4.0.4': + dependencies: + '@react-pdf/pdfkit': 4.1.0 + '@react-pdf/types': 2.9.2 + fontkit: 2.0.4 + is-url: 1.2.4 - '@rollup/rollup-darwin-arm64@4.60.0': - optional: true + '@react-pdf/image@3.0.4': + dependencies: + '@react-pdf/png-js': 3.0.0 + jay-peg: 1.1.1 - '@rollup/rollup-darwin-x64@4.60.0': - optional: true + '@react-pdf/layout@4.4.2': + dependencies: + '@react-pdf/fns': 3.1.2 + '@react-pdf/image': 3.0.4 + '@react-pdf/primitives': 4.1.1 + '@react-pdf/stylesheet': 6.1.2 + '@react-pdf/textkit': 6.1.0 + '@react-pdf/types': 2.9.2 + emoji-regex-xs: 1.0.0 + queue: 6.0.2 + yoga-layout: 3.2.1 + + '@react-pdf/pdfkit@4.1.0': + dependencies: + '@babel/runtime': 7.29.2 + '@react-pdf/png-js': 3.0.0 + browserify-zlib: 0.2.0 + crypto-js: 4.2.0 + fontkit: 2.0.4 + jay-peg: 1.1.1 + linebreak: 1.1.0 + vite-compatible-readable-stream: 3.6.1 + + '@react-pdf/png-js@3.0.0': + dependencies: + browserify-zlib: 0.2.0 + + '@react-pdf/primitives@4.1.1': {} + + '@react-pdf/reconciler@2.0.0(react@19.2.4)': + dependencies: + object-assign: 4.1.1 + react: 19.2.4 + scheduler: 0.25.0-rc-603e6108-20241029 + + '@react-pdf/render@4.3.2': + dependencies: + '@babel/runtime': 7.29.2 + '@react-pdf/fns': 3.1.2 + '@react-pdf/primitives': 4.1.1 + '@react-pdf/textkit': 6.1.0 + '@react-pdf/types': 2.9.2 + abs-svg-path: 0.1.1 + color-string: 1.9.1 + normalize-svg-path: 1.1.0 + parse-svg-path: 0.1.2 + svg-arc-to-cubic-bezier: 3.2.0 + + '@react-pdf/renderer@4.3.2(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@react-pdf/fns': 3.1.2 + '@react-pdf/font': 4.0.4 + '@react-pdf/layout': 4.4.2 + '@react-pdf/pdfkit': 4.1.0 + '@react-pdf/primitives': 4.1.1 + '@react-pdf/reconciler': 2.0.0(react@19.2.4) + '@react-pdf/render': 4.3.2 + '@react-pdf/types': 2.9.2 + events: 3.3.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + queue: 6.0.2 + react: 19.2.4 + + '@react-pdf/stylesheet@6.1.2': + dependencies: + '@react-pdf/fns': 3.1.2 + '@react-pdf/types': 2.9.2 + color-string: 1.9.1 + hsl-to-hex: 1.0.0 + media-engine: 1.0.3 + postcss-value-parser: 4.2.0 + + '@react-pdf/textkit@6.1.0': + dependencies: + '@react-pdf/fns': 3.1.2 + bidi-js: 1.0.3 + hyphen: 1.14.1 + unicode-properties: 1.4.1 + + '@react-pdf/types@2.9.2': + dependencies: + '@react-pdf/font': 4.0.4 + '@react-pdf/primitives': 4.1.1 + '@react-pdf/stylesheet': 6.1.2 + + '@remirror/core-constants@3.0.0': {} + + '@rollup/rollup-android-arm-eabi@4.60.0': + optional: true + + '@rollup/rollup-android-arm64@4.60.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.0': + optional: true + + '@rollup/rollup-darwin-x64@4.60.0': + optional: true '@rollup/rollup-freebsd-arm64@4.60.0': optional: true @@ -9387,6 +10110,12 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@14.18.63': {} + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + '@types/node@22.19.15': dependencies: undici-types: 6.21.0 @@ -9537,6 +10266,10 @@ snapshots: - debug - supports-color + abbrev@1.1.1: {} + + abs-svg-path@0.1.1: {} + accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -9544,6 +10277,12 @@ snapshots: acorn@8.16.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} ai@6.0.116(zod@4.3.6): @@ -9575,6 +10314,49 @@ snapshots: any-promise@1.3.0: {} + aproba@2.1.0: {} + + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + argparse@2.0.1: {} aria-hidden@1.2.6: @@ -9597,6 +10379,8 @@ snapshots: async@3.2.3: {} + async@3.2.6: {} + asynckit@0.4.0: {} aws-ssl-profiles@1.1.2: {} @@ -9619,6 +10403,8 @@ snapshots: balanced-match@4.0.4: {} + base64-js@0.0.8: {} + base64-js@1.5.1: {} baseline-browser-mapping@2.10.8: {} @@ -9668,8 +10454,27 @@ snapshots: optionalDependencies: zod: 4.3.6 + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + big-integer@1.6.52: {} + bignumber.js@9.3.1: {} + binary@0.3.0: + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.4.7: {} + bluebird@3.7.2: {} body-parser@2.2.2: @@ -9688,16 +10493,42 @@ snapshots: bowser@2.14.1: {} + brace-expansion@1.1.13: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.3: + dependencies: + balanced-match: 1.0.2 + brace-expansion@5.0.4: dependencies: balanced-match: 4.0.4 + brotli@1.3.3: + dependencies: + base64-js: 1.5.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + bson@7.2.0: {} buffer-crc32@0.2.13: {} buffer-equal-constant-time@1.0.1: {} + buffer-indexof-polyfill@1.0.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffers@0.1.1: {} + bytes@3.1.2: {} cac@6.7.14: {} @@ -9716,6 +10547,15 @@ snapshots: caniuse-lite@1.0.30001780: {} + canvas@2.11.2: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + nan: 2.26.2 + simple-get: 3.1.1 + transitivePeerDependencies: + - encoding + - supports-color + ccount@2.0.1: {} chai@5.3.3: @@ -9726,6 +10566,10 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 + chainsaw@0.1.0: + dependencies: + traverse: 0.3.9 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -9741,6 +10585,19 @@ snapshots: character-reference-invalid@2.0.1: {} + chart.js@4.5.1: + dependencies: + '@kurkle/color': 0.3.4 + + chartjs-node-canvas@4.1.6(chart.js@4.5.1): + dependencies: + canvas: 2.11.2 + chart.js: 4.5.1 + tslib: 2.8.1 + transitivePeerDependencies: + - encoding + - supports-color + check-error@2.1.3: {} chevrotain-allstar@0.3.1(chevrotain@11.1.2): @@ -9757,6 +10614,8 @@ snapshots: '@chevrotain/utils': 11.1.2 lodash-es: 4.17.23 + chownr@2.0.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -9792,6 +10651,8 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clone@2.1.2: {} + clsx@2.1.1: {} cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): @@ -9812,6 +10673,13 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color-support@1.1.3: {} + colors@1.0.3: {} combined-stream@1.0.8: @@ -9826,8 +10694,19 @@ snapshots: commander@8.3.0: {} + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + concat-map@0.0.1: {} + confbox@0.1.8: {} + console-control-strings@1.1.0: {} + content-disposition@1.0.1: {} content-type@1.0.5: {} @@ -9836,6 +10715,8 @@ snapshots: cookie@0.7.2: {} + core-util-is@1.0.3: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 @@ -9854,6 +10735,13 @@ snapshots: nan: 2.26.2 optional: true + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + crelt@1.0.6: {} cross-spawn@7.0.6: @@ -9862,6 +10750,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-js@4.2.0: {} + csstype@3.2.3: {} cycle@1.0.3: {} @@ -10111,6 +11001,10 @@ snapshots: dependencies: character-entities: 2.0.2 + decompress-response@4.2.1: + dependencies: + mimic-response: 2.1.0 + deep-eql@5.0.2: {} deep-extend@0.6.0: {} @@ -10129,6 +11023,8 @@ snapshots: delayed-stream@1.0.0: {} + delegates@1.0.0: {} + denque@2.1.0: {} depd@2.0.0: {} @@ -10143,6 +11039,8 @@ snapshots: dependencies: dequal: 2.0.3 + dfa@1.2.0: {} + diff@8.0.3: {} dom-helpers@5.2.1: @@ -10164,6 +11062,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 @@ -10182,6 +11084,8 @@ snapshots: embla-carousel@8.6.0: {} + emoji-regex-xs@1.0.0: {} + emoji-regex@8.0.0: {} encodeurl@2.0.0: {} @@ -10285,12 +11189,26 @@ snapshots: eventemitter3@5.0.4: {} + events@3.3.0: {} + eventsource-parser@3.0.6: {} eventsource@3.0.7: dependencies: eventsource-parser: 3.0.6 + exceljs@4.4.0: + dependencies: + archiver: 5.3.2 + dayjs: 1.11.20 + fast-csv: 4.3.6 + jszip: 3.10.1 + readable-stream: 3.6.2 + saxes: 5.0.1 + tmp: 0.2.5 + unzipper: 0.10.14 + uuid: 8.3.2 + execa@9.6.1: dependencies: '@sindresorhus/merge-streams': 4.0.0 @@ -10355,6 +11273,11 @@ snapshots: eyes@0.1.8: {} + fast-csv@4.3.6: + dependencies: + '@fast-csv/format': 4.3.5 + '@fast-csv/parse': 4.3.6 + fast-deep-equal@3.1.3: {} fast-equals@5.4.0: {} @@ -10420,6 +11343,18 @@ snapshots: follow-redirects@1.15.11: {} + fontkit@2.0.4: + dependencies: + '@swc/helpers': 0.5.15 + brotli: 1.3.3 + clone: 2.1.2 + dfa: 1.2.0 + fast-deep-equal: 3.1.3 + restructure: 3.0.2 + tiny-inflate: 1.0.3 + unicode-properties: 1.4.1 + unicode-trie: 2.0.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -10445,11 +11380,38 @@ snapshots: fresh@2.0.0: {} + fs-constants@1.0.0: {} + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true + fstream@1.0.12: + dependencies: + graceful-fs: 4.2.11 + inherits: 2.0.4 + mkdirp: 0.5.6 + rimraf: 2.7.1 + function-bind@1.1.2: {} + gauge@3.0.2: + dependencies: + aproba: 2.1.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + gaxios@7.1.4: dependencies: extend: 3.0.2 @@ -10521,6 +11483,15 @@ snapshots: minipass: 7.1.3 path-scurry: 2.0.2 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + google-auth-library@10.6.2: dependencies: base64-js: 1.5.1 @@ -10548,6 +11519,8 @@ snapshots: dependencies: has-symbols: 1.1.0 + has-unicode@2.0.1: {} + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -10688,6 +11661,12 @@ snapshots: dependencies: lru-cache: 11.2.7 + hsl-to-hex@1.0.0: + dependencies: + hsl-to-rgb-for-reals: 1.1.1 + + hsl-to-rgb-for-reals@1.1.1: {} + html-url-attributes@3.0.1: {} html-void-elements@3.0.0: {} @@ -10707,6 +11686,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 @@ -10714,8 +11700,12 @@ snapshots: transitivePeerDependencies: - supports-color + https@1.0.0: {} + human-signals@8.0.1: {} + hyphen@1.14.1: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -10728,8 +11718,19 @@ snapshots: ignore@7.0.5: {} + image-size@1.2.1: + dependencies: + queue: 6.0.2 + + immediate@3.0.6: {} + inflection@1.13.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} ini@1.3.8: {} @@ -10751,6 +11752,8 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 + is-arrayish@0.3.4: {} + is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -10775,10 +11778,18 @@ snapshots: is-unicode-supported@2.1.0: {} + is-url@1.2.4: {} + + isarray@1.0.0: {} + isexe@2.0.0: {} isstream@0.1.2: {} + jay-peg@1.1.1: + dependencies: + restructure: 3.0.2 + jiti@2.6.1: {} jose@6.2.2: {} @@ -10815,6 +11826,13 @@ snapshots: ms: 2.1.3 semver: 7.7.4 + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 @@ -10851,6 +11869,14 @@ snapshots: layout-base@2.0.1: {} + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lightningcss-android-arm64@1.32.0: optional: true @@ -10900,12 +11926,19 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + linebreak@1.1.0: + dependencies: + base64-js: 0.0.8 + unicode-trie: 2.0.0 + linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 linkifyjs@4.3.2: {} + listenercount@1.0.1: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -10916,20 +11949,40 @@ snapshots: lodash.defaults@4.2.0: {} + lodash.difference@4.5.0: {} + + lodash.escaperegexp@4.1.2: {} + + lodash.flatten@4.4.0: {} + + lodash.groupby@4.6.0: {} + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} + lodash.isequal@4.5.0: {} + + lodash.isfunction@3.0.9: {} + lodash.isinteger@4.0.4: {} + lodash.isnil@4.0.0: {} + lodash.isnumber@3.0.3: {} lodash.isplainobject@4.0.6: {} lodash.isstring@4.0.1: {} + lodash.isundefined@3.0.1: {} + lodash.once@4.1.1: {} + lodash.union@4.6.0: {} + + lodash.uniq@4.5.0: {} + lodash@4.17.23: {} long@5.3.2: {} @@ -10960,6 +12013,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + markdown-it@14.1.1: dependencies: argparse: 2.0.1 @@ -11146,6 +12203,8 @@ snapshots: mdurl@2.0.0: {} + media-engine@1.0.3: {} + media-typer@1.1.0: {} memory-pager@1.5.0: {} @@ -11421,18 +12480,41 @@ snapshots: dependencies: mime-db: 1.54.0 + mimic-response@2.1.0: {} + minimatch@10.2.4: dependencies: brace-expansion: 5.0.4 + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.13 + + minimatch@5.1.9: + dependencies: + brace-expansion: 2.0.3 + minimist@1.2.8: {} + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + minipass@7.1.3: {} + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + mkdirp@0.5.6: dependencies: minimist: 1.2.8 + mkdirp@1.0.4: {} + mlly@1.8.1: dependencies: acorn: 8.16.0 @@ -11497,8 +12579,7 @@ snapshots: dependencies: lru.min: 1.1.4 - nan@2.26.2: - optional: true + nan@2.26.2: {} nanoid@3.3.11: {} @@ -11543,6 +12624,10 @@ snapshots: node-domexception@1.0.0: {} + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + node-fetch@3.3.2: dependencies: data-uri-to-buffer: 4.0.1 @@ -11551,11 +12636,28 @@ snapshots: node-fs@0.1.7: {} + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-path@3.0.0: {} + + normalize-svg-path@1.1.0: + dependencies: + svg-arc-to-cubic-bezier: 3.2.0 + npm-run-path@6.0.0: dependencies: path-key: 4.0.0 unicorn-magic: 0.3.0 + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -11629,6 +12731,10 @@ snapshots: package-manager-detector@1.6.0: {} + pako@0.2.9: {} + + pako@1.0.11: {} + parse-database-url@0.3.0: dependencies: mongodb-uri: 0.9.7 @@ -11645,6 +12751,8 @@ snapshots: parse-ms@4.0.0: {} + parse-svg-path@0.1.2: {} + parse5-htmlparser2-tree-adapter@6.0.1: dependencies: parse5: 6.0.1 @@ -11667,6 +12775,8 @@ snapshots: path-expression-matcher@1.1.3: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -11738,6 +12848,8 @@ snapshots: path-data-parser: 0.1.0 points-on-curve: 0.2.0 + postcss-value-parser@4.2.0: {} + postcss@8.4.31: dependencies: nanoid: 3.3.11 @@ -11760,10 +12872,19 @@ snapshots: dependencies: xtend: 4.0.2 + pptxgenjs@3.12.0: + dependencies: + '@types/node': 18.19.130 + https: 1.0.0 + image-size: 1.2.1 + jszip: 3.10.1 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 + process-nextick-args@2.0.1: {} + prompt@1.3.0: dependencies: '@colors/colors': 1.5.0 @@ -11937,6 +13058,10 @@ snapshots: dependencies: side-channel: 1.1.0 + queue@6.0.2: + dependencies: + inherits: 2.0.4 + radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@radix-ui/primitive': 1.1.3 @@ -12092,6 +13217,26 @@ snapshots: dependencies: mute-stream: 0.0.8 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.9 + recharts-scale@0.4.5: dependencies: decimal.js-light: 2.5.1 @@ -12223,12 +13368,22 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + restructure@3.0.2: {} + retry@0.12.0: {} retry@0.13.1: {} revalidator@0.1.8: {} + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + robust-predicates@3.0.2: {} rollup@4.60.0: @@ -12285,14 +13440,24 @@ snapshots: rw@1.3.3: {} + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {} + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.25.0-rc-603e6108-20241029: {} + scheduler@0.27.0: {} semver@5.7.2: {} + semver@6.3.1: {} + semver@7.7.4: {} send@1.2.1: @@ -12324,6 +13489,8 @@ snapshots: set-cookie-parser@3.0.1: {} + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} sharp@0.34.5: @@ -12409,6 +13576,18 @@ snapshots: signal-exit@4.1.0: {} + simple-concat@1.0.1: {} + + simple-get@3.1.1: + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + sisteransi@1.0.5: {} smart-buffer@4.2.0: {} @@ -12500,6 +13679,14 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -12548,12 +13735,31 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-arc-to-cubic-bezier@3.2.0: {} + tailwind-merge@3.5.0: {} tailwindcss@4.2.2: {} tapable@2.3.0: {} + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -12562,6 +13768,8 @@ snapshots: dependencies: any-promise: 1.3.0 + tiny-inflate@1.0.3: {} + tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -12581,6 +13789,8 @@ snapshots: tinyspy@4.0.4: {} + tmp@0.2.5: {} + toidentifier@1.0.1: {} token-types@6.1.2: @@ -12596,10 +13806,14 @@ snapshots: '@tokenlens/helpers': 1.3.1 '@tokenlens/models': 1.3.0 + tr46@0.0.3: {} + tr46@5.1.1: dependencies: punycode: 2.3.1 + traverse@0.3.9: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -12658,10 +13872,22 @@ snapshots: uint8array-extras@1.5.0: {} + undici-types@5.26.5: {} + undici-types@6.21.0: {} undici@7.24.4: {} + unicode-properties@1.4.1: + dependencies: + base64-js: 1.5.1 + unicode-trie: 2.0.0 + + unicode-trie@2.0.0: + dependencies: + pako: 0.2.9 + tiny-inflate: 1.0.3 + unicorn-magic@0.3.0: {} unified@11.0.5: @@ -12709,6 +13935,19 @@ snapshots: unpipe@1.0.0: {} + unzipper@0.10.14: + dependencies: + big-integer: 1.6.52 + binary: 0.3.0 + bluebird: 3.4.7 + buffer-indexof-polyfill: 1.0.2 + duplexer2: 0.1.4 + fstream: 1.0.12 + graceful-fs: 4.2.11 + listenercount: 1.0.1 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.4): dependencies: react: 19.2.4 @@ -12736,10 +13975,14 @@ snapshots: dependencies: react: 19.2.4 + util-deprecate@1.0.2: {} + uuid@11.1.0: {} uuid@13.0.0: {} + uuid@8.3.2: {} + vary@1.1.2: {} vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): @@ -12783,6 +14026,12 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 + vite-compatible-readable-stream@3.6.1: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + vite-node@3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 @@ -12885,6 +14134,8 @@ snapshots: web-streams-polyfill@3.3.3: {} + webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} whatwg-url@14.2.0: @@ -12892,6 +14143,11 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + when@2.0.1: {} which-module@2.0.1: {} @@ -12905,6 +14161,10 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + winston@2.4.7: dependencies: async: 2.6.4 @@ -12930,12 +14190,16 @@ snapshots: ws@8.19.0: {} + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@4.0.3: {} y18n@5.0.8: {} + yallist@4.0.0: {} + yaml@2.8.2: {} yargs-parser@18.1.3: @@ -12988,6 +14252,14 @@ snapshots: yoctocolors@2.1.2: {} + yoga-layout@3.2.1: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + zod-to-json-schema@3.25.1(zod@4.3.6): dependencies: zod: 4.3.6