diff --git a/README.md b/README.md index dd326c8..464f2f4 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,16 @@ cp .dev.vars.example .dev.vars pnpm dev ``` +For a fully local browser session, including a local Iterate backend and a +project-session proxy, use the harness from the workspace-collaboration branch: + +```bash +OS_DIR=/path/to/iterate/apps/os ./scripts/dev-local.sh plannotator-local +``` + +Open the printed `/w/local-review` URL. Add or open a task, then switch it to +Review. Rerun the harness when its 15-minute local token expires. + `.dev.vars.example` points `OS_BASE_URL` at `https://os.iterate.com` — the develop-against-production loop below, which is the loop you usually want. Point it at a local os dev server (`http://localhost:`) to run fully diff --git a/package.json b/package.json index 163f109..ec5f727 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "@codemirror/state": "^6.7.1", "@codemirror/view": "^6.43.6", "@dnd-kit/react": "^0.5.0", + "@plannotator/core": "0.22.0", + "@plannotator/ui": "0.28.0", "@tanstack/react-router": "^1.170.10", "@tanstack/react-start": "^1.168.18", "capnweb": "npm:@iterate-com/capnweb@^0.10.0", @@ -38,13 +40,13 @@ "devDependencies": { "@cloudflare/vite-plugin": "1.43.0", "@cloudflare/workers-types": "^4.20260621.1", - "@tailwindcss/vite": "^4.3.2", + "@tailwindcss/vite": "4.3.2", "@types/node": "^24.12.4", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", "captun": "https://github.com/iterate/captun/releases/download/v0.0.3-websocket.6aa1207/captun-0.0.3.tgz", - "tailwindcss": "^4.3.2", + "tailwindcss": "4.3.2", "tw-animate-css": "^1.4.0", "typescript": "^5.9.2", "vite": "^8.0.16", diff --git a/patches/@plannotator__ui@0.28.0.patch b/patches/@plannotator__ui@0.28.0.patch new file mode 100644 index 0000000..215fa79 --- /dev/null +++ b/patches/@plannotator__ui@0.28.0.patch @@ -0,0 +1,222 @@ +diff --git a/components/InlineMarkdown.tsx b/components/InlineMarkdown.tsx +index d6b2a3ffcacf83a8f297e9f56f201fe0ec03f2d4..61b5fce9b0a0af9c0e21294fdcb71e1759265023 100644 +--- a/components/InlineMarkdown.tsx ++++ b/components/InlineMarkdown.tsx +@@ -1,6 +1,6 @@ + import React, { useState, useRef, useCallback, useEffect, useMemo } from "react"; + import { createPortal } from "react-dom"; +-import hljs from "highlight.js"; ++import * as hljs from "highlight.js"; + import { isCodeFilePath, isCodeFilePathStrict, CODE_PATH_BARE_REGEX, parseCodePath } from "@plannotator/core/code-file"; + import { transformPlainText } from "../utils/inlineTransforms"; + import { getImageSrc } from "./ImageThumbnail"; +@@ -9,6 +9,8 @@ import type { ValidationEntry } from "../hooks/useValidatedCodePaths"; + import { CodeFilePicker } from "./CodeFilePicker"; + import { normalizeMathTex, renderMathToHtml } from "./blocks/MathBlock"; + ++const highlighter = hljs.default; ++ + export interface DocPreviewResult { + contents?: string; + filepath?: string; +@@ -98,8 +100,8 @@ const CodeSnippetPreview: React.FC<{ + const lines = snippet.split('\n'); + return lines.map(line => { + try { +- if (lang) return hljs.highlight(line, { language: lang }).value; +- return hljs.highlightAuto(line).value; ++ if (lang) return highlighter.highlight(line, { language: lang }).value; ++ return highlighter.highlightAuto(line).value; + } catch { + return line.replace(/&/g, '&').replace(//g, '>'); + } +diff --git a/components/OpenInAppButton.tsx b/components/OpenInAppButton.tsx +index 28084e7496e765961f1143fbd1ab18ac7f93e3d0..059d17f042cda44e024c9b7d4fc008187dabcf0f 100644 +--- a/components/OpenInAppButton.tsx ++++ b/components/OpenInAppButton.tsx +@@ -59,8 +59,8 @@ let openInAppsPromise: Promise | null = null; + function loadOpenInApps(): Promise { + if (!openInAppsPromise) { + openInAppsPromise = fetch('/api/open-in/apps') +- .then((r) => r.json()) +- .then((data: OpenInAppsResponse) => ({ ++ .then((r) => r.json() as Promise) ++ .then((data) => ({ + available: !!data.available, + apps: Array.isArray(data.apps) ? data.apps : [], + })) +diff --git a/components/Viewer.tsx b/components/Viewer.tsx +index 42c24dcf35505d7a8baef0a3955e7d1fdca5b154..4fbf1d0832e43ff701c0ec335396c4018972ec73 100644 +--- a/components/Viewer.tsx ++++ b/components/Viewer.tsx +@@ -1,6 +1,6 @@ + import React, { useRef, useState, useEffect, useMemo, forwardRef, useImperativeHandle, useCallback } from 'react'; + import { createPortal } from 'react-dom'; +-import hljs from 'highlight.js'; ++import * as hljs from 'highlight.js'; + import { AnnotationType, type Block, type Annotation, type EditorMode, type InputMethod, type ImageAttachment, type ActionsLabelMode } from '../types'; + import { computeListIndices, groupBlocks, type Frontmatter } from '../utils/parser'; + import { buildHeadingSlugMap } from '../utils/slugify'; +@@ -14,6 +14,8 @@ import { useValidatedCodePaths } from '../hooks/useValidatedCodePaths'; + import { AnnotationToolbar } from './AnnotationToolbar'; + import { FloatingQuickLabelPicker } from './FloatingQuickLabelPicker'; + ++const highlighter = hljs.default; ++ + // Debug error boundary to catch silent toolbar crashes + class ToolbarErrorBoundary extends React.Component< + { children: React.ReactNode }, +@@ -444,7 +446,7 @@ export const Viewer = forwardRef(({ + const block = blocks.find(b => b.id === codeEl.closest('[data-block-id]')?.getAttribute('data-block-id')); + codeEl.removeAttribute('data-highlighted'); + codeEl.className = `hljs font-mono${block?.language ? ` language-${block.language}` : ''}`; +- hljs.highlightElement(codeEl); ++ highlighter.highlightElement(codeEl); + } + }); + +@@ -987,5 +989,3 @@ const ImageLightbox: React.FC<{ src: string; alt: string; onClose: () => void }> + + + +- +- +diff --git a/components/blocks/CodeBlock.tsx b/components/blocks/CodeBlock.tsx +index 2a5385c59251f3e2f0c8bdac91369f446d768a64..78efbd568afaca29b19f1e2d481dba999ef261a1 100644 +--- a/components/blocks/CodeBlock.tsx ++++ b/components/blocks/CodeBlock.tsx +@@ -1,8 +1,10 @@ + import React, { useState, useRef, useEffect, useCallback } from 'react'; +-import hljs from 'highlight.js'; ++import * as hljs from 'highlight.js'; + import 'highlight.js/styles/github-dark.css'; + import type { Block } from '../../types'; + ++const highlighter = hljs.default; ++ + interface CodeBlockProps { + block: Block; + onHover: (element: HTMLElement) => void; +@@ -21,7 +23,7 @@ export const CodeBlock: React.FC = ({ block, onHover, onLeave }) + // Reset any previous highlighting + codeRef.current.removeAttribute('data-highlighted'); + codeRef.current.className = `hljs font-mono${block.language ? ` language-${block.language}` : ''}`; +- hljs.highlightElement(codeRef.current); ++ highlighter.highlightElement(codeRef.current); + } + }, [block.content, block.language]); + +diff --git a/components/plan-diff/PlanCleanDiffView.tsx b/components/plan-diff/PlanCleanDiffView.tsx +index fbe3e12929e1c70bad756ed721e99265822316b0..d5faa3ec6e0ae00185a9c98a8e3a245ff6610bd7 100644 +--- a/components/plan-diff/PlanCleanDiffView.tsx ++++ b/components/plan-diff/PlanCleanDiffView.tsx +@@ -7,7 +7,7 @@ + */ + + import React, { useEffect, useRef, useState, useCallback } from "react"; +-import hljs from "highlight.js"; ++import * as hljs from "highlight.js"; + import { parseMarkdownToBlocks, computeListIndices } from "../../utils/parser"; + import { ListItemBody } from "../ListItemBody"; + import type { Block, Annotation, EditorMode, ImageAttachment } from "../../types"; +@@ -23,6 +23,8 @@ import { CommentPopover } from "../CommentPopover"; + import { FloatingQuickLabelPicker } from "../FloatingQuickLabelPicker"; + import { getIdentity } from "../../utils/identity"; + ++const highlighter = hljs.default; ++ + interface PlanCleanDiffViewProps { + blocks: PlanDiffBlock[]; + annotations?: Annotation[]; +@@ -700,7 +702,7 @@ const SimpleCodeBlock: React.FC<{ block: Block }> = ({ block }) => { + if (codeRef.current) { + codeRef.current.removeAttribute("data-highlighted"); + codeRef.current.className = `hljs font-mono${block.language ? ` language-${block.language}` : ""}`; +- hljs.highlightElement(codeRef.current); ++ highlighter.highlightElement(codeRef.current); + } + }, [block.content, block.language]); + +diff --git a/hooks/useAIChat.ts b/hooks/useAIChat.ts +index ec85fc28fc9d3df2c9671ac9fba9192d12b13b38..627102a686a029d8cdc28905064a9d01733c9215 100644 +--- a/hooks/useAIChat.ts ++++ b/hooks/useAIChat.ts +@@ -243,7 +243,7 @@ export function useAIChat({ + }, signal); + + if (!res.ok) { +- const data = await res.json().catch(() => ({ error: 'Failed to create AI session' })); ++ const data = await res.json().catch(() => ({ error: 'Failed to create AI session' })) as { error?: string }; + throw new Error(data.error || `HTTP ${res.status}`); + } + +@@ -334,7 +334,7 @@ export function useAIChat({ + }, controller.signal); + + if (!res.ok || !res.body) { +- const data = await res.json().catch(() => ({ error: 'Query failed' })); ++ const data = await res.json().catch(() => ({ error: 'Query failed' })) as { error?: string }; + throw new Error(data.error || `HTTP ${res.status}`); + } + +diff --git a/hooks/useExternalAnnotations.ts b/hooks/useExternalAnnotations.ts +index 6e4fe865cceca922fcc3324c243b909196c2f6b3..0c1a9b5bcacda198d485689b6a01e11843ff15f4 100644 +--- a/hooks/useExternalAnnotations.ts ++++ b/hooks/useExternalAnnotations.ts +@@ -68,7 +68,7 @@ function createDefaultTransport(): Ex + const res = await fetch(url); + if (res.status === 304) return null; // No changes + if (!res.ok) return null; +- const data = await res.json(); ++ const data = await res.json() as { annotations?: unknown; version?: unknown }; + // Skip (don't apply) on a malformed 200 — preserves existing annotations + // and the version cursor instead of clearing them, matching the + // pre-seam fetchSnapshot which only updated on well-formed payloads. +diff --git a/hooks/useFileBrowser.ts b/hooks/useFileBrowser.ts +index eb74ecdd145157edb67c04a493bde1c9ede537c0..6648b375eadb0a2dc2dd74676f8e6d497ae16ef3 100644 +--- a/hooks/useFileBrowser.ts ++++ b/hooks/useFileBrowser.ts +@@ -101,6 +101,12 @@ export interface FileTreeBackend { + watchTrees(paths: string[], onChange: (path: string) => void): (() => void) | undefined; + } + ++type FileTreeResponse = { ++ error?: string; ++ tree: VaultNode[]; ++ workspaceStatus?: WorkspaceStatusPayload; ++}; ++ + const defaultFileTreeBackend: FileTreeBackend = { + loadTree(dirPath) { + return fetch(`/api/reference/files?dirPath=${encodeURIComponent(dirPath)}`); +@@ -209,7 +215,7 @@ export function useFileBrowser(): UseFileBrowserReturn { + + try { + const res = await fileTreeBackend.loadTree(dirPath); +- const data = await res.json(); ++ const data = await res.json() as FileTreeResponse; + + if (!res.ok || data.error) { + const error = data.error || "Failed to load"; +@@ -314,7 +320,7 @@ export function useFileBrowser(): UseFileBrowserReturn { + + try { + const res = await fileTreeBackend.loadVaultTree(vaultPath); +- const data = await res.json(); ++ const data = await res.json() as FileTreeResponse; + + if (!res.ok || data.error) { + setDirs((prev) => +diff --git a/utils/upload.ts b/utils/upload.ts +index 317d1ccb8f3e65544b55b18df197b4777a49a736..58694ad8d67ceb76507c215c8ca716bbf57e2b5d 100644 +--- a/utils/upload.ts ++++ b/utils/upload.ts +@@ -31,7 +31,7 @@ const defaultUploadTransport: UploadTransport = { + const formData = new FormData(); + formData.append('file', file); + const res = await fetch('/api/upload', { method: 'POST', body: formData }); +- const data = await res.json(); ++ const data = await res.json() as UploadResult; + return { path: data.path, originalName: data.originalName }; + }, + }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f1d8b2..67df3b5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,17 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + '@opentui/core': 0.4.3 + '@opentui/react': 0.4.3 + '@tailwindcss/oxide': 4.3.2 + lightningcss: 1.32.0 + +patchedDependencies: + '@plannotator/ui@0.28.0': + hash: 2874e34359989695f812abcb58cd0672830ce9a48ebebbd770fb1d72db4fc11f + path: patches/@plannotator__ui@0.28.0.patch + importers: .: @@ -26,6 +37,12 @@ importers: '@dnd-kit/react': specifier: ^0.5.0 version: 0.5.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@plannotator/core': + specifier: 0.22.0 + version: 0.22.0 + '@plannotator/ui': + specifier: 0.28.0 + version: 0.28.0(patch_hash=2874e34359989695f812abcb58cd0672830ce9a48ebebbd770fb1d72db4fc11f)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@lezer/markdown@1.7.2)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.2)(typescript@5.9.3) '@tanstack/react-router': specifier: ^1.170.10 version: 1.170.18(react-dom@19.2.7(react@19.2.7))(react@19.2.7) @@ -82,8 +99,8 @@ importers: specifier: ^4.20260621.1 version: 4.20260702.1 '@tailwindcss/vite': - specifier: ^4.3.2 - version: 4.3.3(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) + specifier: 4.3.2 + version: 4.3.2(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) '@types/node': specifier: ^24.12.4 version: 24.13.3 @@ -100,8 +117,8 @@ importers: specifier: https://github.com/iterate/captun/releases/download/v0.0.3-websocket.6aa1207/captun-0.0.3.tgz version: https://github.com/iterate/captun/releases/download/v0.0.3-websocket.6aa1207/captun-0.0.3.tgz(@types/node@24.13.3)(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(ws@8.21.1) tailwindcss: - specifier: ^4.3.2 - version: 4.3.3 + specifier: 4.3.2 + version: 4.3.2 tw-animate-css: specifier: ^1.4.0 version: 1.4.0 @@ -123,6 +140,9 @@ importers: packages: + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -225,6 +245,12 @@ packages: '@types/react': optional: true + '@braintree/sanitize-url@7.1.2': + resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} + + '@chevrotain/types@11.1.2': + resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==} + '@clack/core@1.4.3': resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} engines: {node: '>= 20.12.0'} @@ -286,15 +312,51 @@ packages: '@cloudflare/workers-types@4.20260702.1': resolution: {integrity: sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA==} + '@codemirror/autocomplete@6.20.3': + resolution: {integrity: sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==} + '@codemirror/collab@6.1.1': resolution: {integrity: sha512-tkIn9Jguh98ie12dbBuba3lE8LHUkaMrIFuCVeVGhncSczFdKmX25vC12+58+yqQW5AXi3py6jWY0W+jelyglA==} '@codemirror/commands@6.10.4': resolution: {integrity: sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==} + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/lang-html@6.4.11': + resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} + + '@codemirror/lang-javascript@6.2.5': + resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} + + '@codemirror/lang-json@6.0.2': + resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} + + '@codemirror/lang-markdown@6.5.1': + resolution: {integrity: sha512-6re5avCNfyRMIoi3XNjbEfQM1vTeVD3JS3g/Fyegyso/eoANFM71Cyvbb66LDyYtQLMEcRFlzioywCqDo9SlLA==} + + '@codemirror/lang-python@6.2.1': + resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} + + '@codemirror/lang-yaml@6.1.3': + resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} + '@codemirror/language@6.12.4': resolution: {integrity: sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A==} + '@codemirror/legacy-modes@6.5.3': + resolution: {integrity: sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==} + + '@codemirror/lint@6.9.7': + resolution: {integrity: sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==} + + '@codemirror/merge@6.12.2': + resolution: {integrity: sha512-V8JvyAPjHbPupqP7BeMcsdsYCbyPij74jxIbaIJDORI+VZzW44zFmon8bF+oxGWvOKhcRmkiUMXd8MxHr3YA2w==} + + '@codemirror/search@6.7.1': + resolution: {integrity: sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA==} + '@codemirror/state@6.7.1': resolution: {integrity: sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A==} @@ -509,6 +571,18 @@ packages: '@floating-ui/utils@0.2.12': resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + '@fontsource-variable/geist-mono@5.2.7': + resolution: {integrity: sha512-ZKlZ5sjtalb2TwXKs400mAGDlt/+2ENLNySPx0wTz3bP3mWARCsUW+rpxzZc7e05d2qGch70pItt3K4qttbIYA==} + + '@fontsource-variable/inter@5.2.8': + resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@3.1.4': + resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==} + '@img/colour@1.1.0': resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} engines: {node: '>=18'} @@ -539,89 +613,105 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -805,15 +895,39 @@ packages: '@lezer/common@1.5.2': resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==} + '@lezer/css@1.3.4': + resolution: {integrity: sha512-N+tn9tej2hPvyKgHEApMOQfHczDJCwxrRFS3SPn9QjYN+uwHvEDnCgKRrb3mxDYxRS8sKMM8fhC3+lc04Abz5Q==} + '@lezer/highlight@1.2.3': resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + '@lezer/html@1.3.13': + resolution: {integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==} + + '@lezer/javascript@1.5.4': + resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==} + + '@lezer/json@1.0.3': + resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==} + '@lezer/lr@1.4.10': resolution: {integrity: sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==} + '@lezer/markdown@1.7.2': + resolution: {integrity: sha512-iTkYvoVcKt3WkeL7qUDyXHONZEwLio4wj8KTNi2dnjQEXBZKMV63BpQrPqfsM+OkvuRbiSTAcycYAsQzLhRNoQ==} + + '@lezer/python@1.1.19': + resolution: {integrity: sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ==} + + '@lezer/yaml@1.0.4': + resolution: {integrity: sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==} + '@marijn/find-cluster-break@1.0.3': resolution: {integrity: sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==} + '@mermaid-js/parser@1.2.0': + resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==} + '@napi-rs/wasm-runtime@1.1.6': resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} peerDependencies: @@ -943,53 +1057,55 @@ packages: resolution: {integrity: sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==} engines: {node: '>=20.0'} - '@opentui/core-darwin-arm64@0.4.5': - resolution: {integrity: sha512-8KUG0oRidnR+oW1RSZJ72/PhZLl+qRRMk5U/mieF4c0SJ5V3tYACpBZAKzQfHNd1f7QzD8FHZct1lPpQgtmkWg==} + '@opentui/core-darwin-arm64@0.4.3': + resolution: {integrity: sha512-p5+7AAxpxGuDGagyQfewKtmTFnN7THvTVY4FyKqUtJomNaHdQXPHztapNNzMx0DGWbwOUbVKzpL+yc3CZY3chQ==} cpu: [arm64] os: [darwin] - '@opentui/core-darwin-x64@0.4.5': - resolution: {integrity: sha512-R2bocsg55gwjOqCp/MWFgFYzRmsduKegB6nzgFAPCvAD/L5Jf30xpWJWFlSg3x8vxe1L9WJ84dfqa4M7mZZ3wA==} + '@opentui/core-darwin-x64@0.4.3': + resolution: {integrity: sha512-+fh0vEUE0lwVC7RW5ijYLRlTLp5NfvCRj8SzxDVd7IL2j2ssB6YXcfIbXq2EW7UGnrejwPRXf1tgUrIXW9KmOw==} cpu: [x64] os: [darwin] - '@opentui/core-linux-arm64-musl@0.4.5': - resolution: {integrity: sha512-ieqdyKI6EIYPalYAETB2wsdP83hr5Ifi+dFnBFUmdEEFHsoKwBmn2S7bsTOYlX7Bg03F4/YPIg+IvRpeC+cUJw==} + '@opentui/core-linux-arm64-musl@0.4.3': + resolution: {integrity: sha512-8p8g8/AEq/xFGpQ7XcIFKcAqjc0QwsZcv+Ll9RbCDpUA56FGH6jfLDir0KYTNTgYXJTIrBIENI9K46VuxMUMQA==} cpu: [arm64] os: [linux] + libc: [musl] - '@opentui/core-linux-arm64@0.4.5': - resolution: {integrity: sha512-R4MZ25a4CzOAGVjW9aj1hUfzQGVfCJwrwBDbNs2SXaIvzcZqkxCVtU4FoQ5LsaD0j/BdNQVg2CIfFkFsm1fDuQ==} + '@opentui/core-linux-arm64@0.4.3': + resolution: {integrity: sha512-gl6qA5QJy6u8Cbt7gOtHbhhfMZ4qQDb0kEwFXHcMGmbnKzz4OHoq74D6tNjyvSQB9saoC7C6C0tvn2DcJOuNog==} cpu: [arm64] os: [linux] - '@opentui/core-linux-x64-musl@0.4.5': - resolution: {integrity: sha512-mKVKcIcPiSVVZZsdPSBoWwoa2/TCeQAaMDeHF7PFw2kt5bTXZPP7xxWfRQLCNIcA1eaGl59UuwUWHDR2Ve548Q==} + '@opentui/core-linux-x64-musl@0.4.3': + resolution: {integrity: sha512-/QiFpCrpU2O7vy8QYmLIQYbvAtKDgmqcVjR7dGtqSzkiQk3ktNJoo5RozG7ueXnjung1Wp0nKldKxo2Csg/OrA==} cpu: [x64] os: [linux] + libc: [musl] - '@opentui/core-linux-x64@0.4.5': - resolution: {integrity: sha512-SNyuQoxMKI1vuJhgxSSW96adWM6LqFl2SoS3GM4tGeneGOanVVG2Y06PvlytXvF4cKik97t0rqkVMRetmOs93w==} + '@opentui/core-linux-x64@0.4.3': + resolution: {integrity: sha512-dXpJitiZdYE3hq2Pvx6e9I0uPQSOcnaLLp1pDgWAHv+3kvKSHEX//9Yr/pV/Ua6qqT7p+2D/K4vXNap/NKVo2w==} cpu: [x64] os: [linux] - '@opentui/core-win32-arm64@0.4.5': - resolution: {integrity: sha512-GHTTsqeR45q2Iek9Rb7ty+x/hAKn2jZ1ujlCgPR8LBKyF7h0E1dNFryoZ7ehMc3kJndP1sKn836IemKFqxuDdQ==} + '@opentui/core-win32-arm64@0.4.3': + resolution: {integrity: sha512-Mx2zuOjrhm/z2SDS6RExIyjP/SnN/8QhhagxURUw0jQi/NssGSeAllu1cBAFFnhobJL5QLTE4FU4CRhUK9svgg==} cpu: [arm64] os: [win32] - '@opentui/core-win32-x64@0.4.5': - resolution: {integrity: sha512-Y8T/yXCDGagRGiQrtmuB6AhRcPucKFs/Dre3v8kJwNYqDccI4FzUPKclZ7djfmRZNjl7JUqPhZZP/PwDpQocMg==} + '@opentui/core-win32-x64@0.4.3': + resolution: {integrity: sha512-NuoqvWKGXaYnmlqvu7Gg2lLI6yVMnS9OfWBvxp+7Q+McSgHFSTQmYBXaPpvQ8HikpQXE1nCeMPtuSG4PdZHe2w==} cpu: [x64] os: [win32] - '@opentui/core@0.4.5': - resolution: {integrity: sha512-JsgRTPkA6e+Vxmumxai6SElOSlRQkbzNKHlCfemlArRiLhfC1IZ9RXJo2QH4xSu+uBOWAM90uss73/pPlkdEig==} + '@opentui/core@0.4.3': + resolution: {integrity: sha512-rrJfAk13tALDqldYjhc78eWQ+aKq1iknJgffIOg3OwyZoqQo+p6gtuqyhmWvXIfQzlNUbpgpCPcxbXlhMnlaHQ==} peerDependencies: web-tree-sitter: 0.25.10 - '@opentui/react@0.4.5': - resolution: {integrity: sha512-n88Vx0cMmAu++/S14WscjvdcT46IDcxve02jMtcfHQ9j6cySRHfILfGEpOB7xxc8RpCwQceEyOjkKkfzPzm6Jg==} + '@opentui/react@0.4.3': + resolution: {integrity: sha512-HtC/+lMURaZlifiJNVsn84YqKMywXQmkeSNbUTlbbeS6YM6reahaacnZEYZdnEUgklO6+r/J1tG8UBhqO26X7Q==} peerDependencies: react: '>=19.2.0' react-devtools-core: ^7.0.1 @@ -1100,6 +1216,119 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@pierre/diffs@1.2.8': + resolution: {integrity: sha512-HVaWzZ1cW5GDKodivaPCN1hU05DGvoLiG/uvVBNZODD+qY2NTr36KYgATGhb79Vr8OCKNG3qATTWJEwbkMGfzA==} + peerDependencies: + react: ^18.3.1 || ^19.0.0 + react-dom: ^18.3.1 || ^19.0.0 + + '@pierre/theme@1.0.3': + resolution: {integrity: sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA==} + engines: {vscode: ^1.0.0} + + '@plannotator/atomic-editor@0.8.0': + resolution: {integrity: sha512-s4IaRrlFjluYvMVRS/XJjAaHVR5I/4yAxAFWlUHk74RE7W9BQO8lazWgYgNyRSYQtdlEZsJiPgzaDeOuocErWg==} + engines: {node: '>=18'} + peerDependencies: + '@codemirror/autocomplete': ^6.0.0 + '@codemirror/commands': ^6.0.0 + '@codemirror/lang-cpp': ^6.0.0 + '@codemirror/lang-css': ^6.0.0 + '@codemirror/lang-go': ^6.0.0 + '@codemirror/lang-html': ^6.0.0 + '@codemirror/lang-java': ^6.0.0 + '@codemirror/lang-javascript': ^6.0.0 + '@codemirror/lang-json': ^6.0.0 + '@codemirror/lang-markdown': ^6.0.0 + '@codemirror/lang-php': ^6.0.0 + '@codemirror/lang-python': ^6.0.0 + '@codemirror/lang-rust': ^6.0.0 + '@codemirror/lang-sql': ^6.0.0 + '@codemirror/lang-xml': ^6.0.0 + '@codemirror/lang-yaml': ^6.0.0 + '@codemirror/language': ^6.0.0 + '@codemirror/legacy-modes': ^6.0.0 + '@codemirror/merge': ^6.0.0 + '@codemirror/search': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/common': ^1.0.0 + '@lezer/highlight': ^1.0.0 + '@lezer/markdown': ^1.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + typescript: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + '@codemirror/lang-cpp': + optional: true + '@codemirror/lang-css': + optional: true + '@codemirror/lang-go': + optional: true + '@codemirror/lang-html': + optional: true + '@codemirror/lang-java': + optional: true + '@codemirror/lang-javascript': + optional: true + '@codemirror/lang-json': + optional: true + '@codemirror/lang-php': + optional: true + '@codemirror/lang-python': + optional: true + '@codemirror/lang-rust': + optional: true + '@codemirror/lang-sql': + optional: true + '@codemirror/lang-xml': + optional: true + '@codemirror/lang-yaml': + optional: true + '@codemirror/legacy-modes': + optional: true + typescript: + optional: true + + '@plannotator/core@0.22.0': + resolution: {integrity: sha512-ovIQ1Sm2f5UlpljBVmLk24zS0BHx4N+UxW6/9NUUUj3XGgM/vvOGPowuKkXgEzmRXxQHdBw2Fw3M5unYbs0Shg==} + + '@plannotator/markdown-editor@0.4.0': + resolution: {integrity: sha512-pXJj912NFY2KBUhQXusoTlGv169NGEDKLVo2bjTCkH+SPIzCMxQWwygdMvMzpNstsieZNDs6NY81fc+XBl5lCA==} + engines: {node: '>=20'} + peerDependencies: + '@codemirror/lang-javascript': ^6.0.0 + '@codemirror/lang-json': ^6.0.0 + '@codemirror/lang-python': ^6.0.0 + '@codemirror/lang-yaml': ^6.0.0 + '@codemirror/language': ^6.0.0 + '@codemirror/legacy-modes': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@plannotator/atomic-editor': ^0.8.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@codemirror/lang-javascript': + optional: true + '@codemirror/lang-json': + optional: true + '@codemirror/lang-python': + optional: true + '@codemirror/lang-yaml': + optional: true + '@codemirror/legacy-modes': + optional: true + + '@plannotator/ui@0.28.0': + resolution: {integrity: sha512-PhuO+ueKjrGJtw/EybegFsDDXP9mgf4Qb//KvRjjztNySmeTSd8GTb/cQSdgf8KXlpHaNuKV021woCAMU4Ctqg==} + peerDependencies: + react: ^19.2.3 + react-dom: ^19.2.3 + tailwindcss: ^4.1.18 + + '@plannotator/web-highlighter@0.8.1': + resolution: {integrity: sha512-FlteNOwRj9iNSY/AhFMtqOnVS4FvsACvTw6IiOM1y8iDyhiU/WeZOgjURENvIY+wuUaiS9DDFmg0PrHMyuMR1Q==} + '@poppinss/colors@4.1.6': resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} @@ -1147,36 +1376,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.1.5': resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.1.5': resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.1.5': resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.1.5': resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.1.5': resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.1.5': resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} @@ -1204,6 +1439,30 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@shikijs/core@3.23.0': + resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} + + '@shikijs/engine-javascript@3.23.0': + resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/transformers@3.23.0': + resolution: {integrity: sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@sindresorhus/is@7.2.0': resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} engines: {node: '>=18'} @@ -1214,65 +1473,69 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@tailwindcss/node@4.3.3': - resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + '@tailwindcss/node@4.3.2': + resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} - '@tailwindcss/oxide-android-arm64@4.3.3': - resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + '@tailwindcss/oxide-android-arm64@4.3.2': + resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.3.3': - resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + '@tailwindcss/oxide-darwin-arm64@4.3.2': + resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.3.3': - resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + '@tailwindcss/oxide-darwin-x64@4.3.2': + resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.3.3': - resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + '@tailwindcss/oxide-freebsd-x64@4.3.2': + resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': - resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': - resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.3.3': - resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.3.3': - resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.3.3': - resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.3.3': - resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1283,24 +1546,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': - resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.3.3': - resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.3.3': - resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + '@tailwindcss/oxide@4.3.2': + resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.3.3': - resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + '@tailwindcss/vite@4.3.2': + resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 @@ -1377,6 +1640,13 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@tanstack/react-table@8.21.3': + resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + '@tanstack/router-core@1.171.15': resolution: {integrity: sha512-IILCDcLaItMZQ2jEmCABHY1Nhjjn5XUvwpQp3e4Nmu+vfg0BgYFuu/QASz2SwE2ZNbVMrvt8X/wxa+Gg5aErxA==} engines: {node: '>=20.19'} @@ -1441,6 +1711,10 @@ packages: '@tanstack/store@0.9.3': resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} + '@tanstack/table-core@8.21.3': + resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} + engines: {node: '>=12'} + '@tanstack/virtual-file-routes@1.162.0': resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} engines: {node: '>=20.19'} @@ -1454,12 +1728,114 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.4': + resolution: {integrity: sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/node@22.20.1': resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} @@ -1474,9 +1850,21 @@ packages: '@types/react@19.2.17': resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@ungap/structured-clone@1.3.3': + resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} + + '@upsetjs/venn.js@2.0.0': + resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==} + '@vitejs/plugin-react@6.0.3': resolution: {integrity: sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1519,6 +1907,9 @@ packages: '@vitest/utils@4.1.10': resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + '@viz-js/viz@3.28.0': + resolution: {integrity: sha512-nPt+jbGHGgd7lUQLBT79/4lChIzeW44I+hFrscx18AnpNyX9vdRFVNwVbKz9eq+ACeKSm4bFQns17WhCW11eWQ==} + ansi-regex@6.2.2: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} @@ -1578,10 +1969,19 @@ packages: vite: optional: true + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + chardet@2.2.0: resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} @@ -1600,10 +2000,21 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@14.0.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + content-type@2.0.0: resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} engines: {node: '>=18'} @@ -1618,12 +2029,177 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + crelt@1.0.7: resolution: {integrity: sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==} csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.34.0: + resolution: {integrity: sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.14: + resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1633,10 +2209,24 @@ packages: supports-color: optional: true + delaunator@5.1.0: + resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + diff@8.0.4: resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} @@ -1645,14 +2235,17 @@ packages: resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} engines: {node: '>=0.3.1'} + dompurify@3.4.12: + resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==} + electron-to-chromium@1.5.393: resolution: {integrity: sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - enhanced-resolve@5.24.3: - resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} engines: {node: '>=10.13.0'} error-stack-parser-es@1.0.5: @@ -1661,6 +2254,9 @@ packages: es-module-lexer@2.3.1: resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-toolkit@1.49.0: + resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} @@ -1701,6 +2297,20 @@ packages: fetchdts@0.1.7: resolution: {integrity: sha512-YoZjBdafyLIop9lSxXVI33oLD5kN31q4Td+CasofLLYeLXRFeOsuOw0Uo+XNRi9PZlbfdlN2GmRtm4tCEQ9/KA==} + framer-motion@12.42.2: + resolution: {integrity: sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1727,10 +2337,40 @@ packages: crossws: optional: true + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + iconv-lite@0.7.3: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + isbot@5.2.1: resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==} engines: {node: '>=18'} @@ -1771,10 +2411,23 @@ packages: engines: {node: '>=6'} hasBin: true + katex@0.16.47: + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + hasBin: true + + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + lib0@0.2.117: resolution: {integrity: sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==} engines: {node: '>=16'} @@ -1786,107 +2439,57 @@ packages: cpu: [arm64] os: [android] - lightningcss-android-arm64@1.33.0: - resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - lightningcss-darwin-arm64@1.32.0: resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-arm64@1.33.0: - resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - lightningcss-darwin-x64@1.32.0: resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-darwin-x64@1.33.0: - resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - lightningcss-freebsd-x64@1.32.0: resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-freebsd-x64@1.33.0: - resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm-gnueabihf@1.33.0: - resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - - lightningcss-linux-arm64-gnu@1.33.0: - resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - - lightningcss-linux-arm64-musl@1.33.0: - resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - - lightningcss-linux-x64-gnu@1.33.0: - resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - - lightningcss-linux-x64-musl@1.33.0: - resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -1894,31 +2497,18 @@ packages: cpu: [arm64] os: [win32] - lightningcss-win32-arm64-msvc@1.33.0: - resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - lightningcss-win32-x64-msvc@1.32.0: resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss-win32-x64-msvc@1.33.0: - resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} - lightningcss@1.33.0: - resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} - engines: {node: '>= 12.0.0'} + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -1926,24 +2516,83 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru_map@0.4.1: + resolution: {integrity: sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==} + lucide-react@0.553.0: resolution: {integrity: sha512-BRgX5zrWmNy/lkVAe0dXBgd7XQdZ3HTf+Hwe3c9WK6dqgnj9h+hxV+MDncM88xDWlCq27+TKvHGE70ViODNILw==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + lucide-react@1.24.0: + resolution: {integrity: sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + marked@16.4.2: + resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} + engines: {node: '>= 20'} + hasBin: true + marked@17.0.1: resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==} engines: {node: '>= 20'} hasBin: true + marked@17.0.6: + resolution: {integrity: sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==} + engines: {node: '>= 20'} + hasBin: true + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mermaid@11.16.0: + resolution: {integrity: sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + miniflare@4.20260701.0: resolution: {integrity: sha512-L6eAAi6IKtyb/7J6L+YsH2vb1yBrJWKRXI293JYDiMl70+6nncdAgigex58w6WBd+CwvdMsqOyNyGs95Op5gWQ==} engines: {node: '>=22.0.0'} hasBin: true + motion-dom@12.42.2: + resolution: {integrity: sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==} + + motion-utils@12.39.0: + resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} + + motion@12.42.2: + resolution: {integrity: sha512-Atvv11yUKIid41cVrRBDVX5m8tF8kNpExRSlbpt6APClhDjtwQssgFHhQzejxw7/7YYbjHSPKBVbHo05BuJT5Q==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1973,20 +2622,35 @@ packages: resolution: {integrity: sha512-4+/OFSqOjoyULo7eN7EA97DE0Xydj/PW5aIckxqQIoFjFwqXKuFCvXUJObyJfBF9Khu4RL/jlDRI9FPaMGfPnw==} engines: {node: '>= 20'} + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + package-manager-detector@1.7.0: + resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==} + partyserver@0.5.8: resolution: {integrity: sha512-htgSwiBcBu9zIYLrsxBAOvdkjukHvncbTk0nDrJgfruvZ08rxtEN1Ab4T7j9osykP80Bq3zA2oWFd3ngc4Z9uw==} peerDependencies: '@cloudflare/workers-types': ^4.20260424.1 + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + path-to-regexp@6.3.0: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + perfect-freehand@1.2.3: + resolution: {integrity: sha512-bHZSfqDHGNlPpgH2yxXgPHlQSPpEbo+qg7li0M78J9vNAi2yjwLeA4x79BEQhX44lEWpCLSFCeRZwpw0niiXPA==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1994,6 +2658,12 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + postcss@8.5.20: resolution: {integrity: sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==} engines: {node: ^10 || ^12 || >=14} @@ -2003,6 +2673,9 @@ packages: engines: {node: '>=14'} hasBin: true + property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + radash@12.1.1: resolution: {integrity: sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA==} engines: {node: '>=14.18.0'} @@ -2029,9 +2702,21 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + reselect@5.2.0: resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} + robust-predicates@3.0.3: + resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} + rolldown@1.1.5: resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2040,6 +2725,12 @@ packages: rou3@0.8.1: resolution: {integrity: sha512-ePa+XGk00/3HuCqrEnK3LxJW7I0SdNg6EFzKUJG73hMAdDcOUC/i/aSz7LSDwLrGr33kal/rqOGydzwl6U7zBA==} + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -2073,6 +2764,9 @@ packages: resolution: {integrity: sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==} engines: {node: '>= 0.4'} + shiki@3.23.0: + resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -2091,6 +2785,9 @@ packages: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + srvx@0.11.22: resolution: {integrity: sha512-LqZxxBDMKuMAZzFzJnDCkFOrs9MZQZr0LvHiO/SuSZVdQaXD7xQ5UWTUxheJrQPve1qk9MG2B/yttUvJxw8egQ==} engines: {node: '>=20.16.0'} @@ -2106,6 +2803,9 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@7.1.2: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} @@ -2113,6 +2813,9 @@ packages: style-mod@4.1.3: resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + stylis@4.4.0: + resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==} + supports-color@10.2.2: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} engines: {node: '>=18'} @@ -2124,8 +2827,8 @@ packages: tailwind-merge@3.6.0: resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} - tailwindcss@4.3.3: - resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} @@ -2150,6 +2853,9 @@ packages: resolution: {integrity: sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==} engines: {node: '>=20'} + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + trpc-cli@0.14.1: resolution: {integrity: sha512-yXycwKWAu322fJGQqdh9fbEPTLjmqnwrpHiLnLNM+kPEwDxXlkH3gbO9iOTmN5CNOBo+8Uk+Tuae+XS8uANz/w==} engines: {node: '>=18'} @@ -2200,6 +2906,10 @@ packages: zod: optional: true + ts-dedent@2.3.0: + resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==} + engines: {node: '>=6.10'} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -2231,6 +2941,25 @@ packages: unenv@2.0.0-rc.24: resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + unique-username-generator@1.5.1: + resolution: {integrity: sha512-Q0pSKPyij4L7Tm6Bo3XsWeFG9qbyWTtwb3jTN+XgGhCFdlvQn6Fj0DCfYElw0kp/Xp7Jv1Q+CL+aA8S07RMChA==} + hasBin: true + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + universal-github-app-jwt@2.2.2: resolution: {integrity: sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw==} @@ -2281,6 +3010,16 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + uuid@14.0.1: + resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + hasBin: true + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + vite@8.1.5: resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2407,8 +3146,8 @@ packages: '@cloudflare/workers-types': optional: true - ws@7.5.13: - resolution: {integrity: sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==} + ws@7.5.12: + resolution: {integrity: sha512-1xGnbYN3zbog9CwuNDQULNRrTCLIn46/WmpR1f0w6PsCYQHkylZr5vkd6kfMZYV6pRnQkcPNRyiA8LsrNKyhpg==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2503,8 +3242,16 @@ packages: zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.7.0 + tinyexec: 1.2.4 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -2636,6 +3383,10 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 + '@braintree/sanitize-url@7.1.2': {} + + '@chevrotain/types@11.1.2': {} + '@clack/core@1.4.3': dependencies: fast-wrap-ansi: 0.2.2 @@ -2686,6 +3437,13 @@ snapshots: '@cloudflare/workers-types@4.20260702.1': {} + '@codemirror/autocomplete@6.20.3': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@codemirror/collab@6.1.1': dependencies: '@codemirror/state': 6.7.1 @@ -2697,6 +3455,69 @@ snapshots: '@codemirror/view': 6.43.6 '@lezer/common': 1.5.2 + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@lezer/common': 1.5.2 + '@lezer/css': 1.3.4 + + '@codemirror/lang-html@6.4.11': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/css': 1.3.4 + '@lezer/html': 1.3.13 + + '@codemirror/lang-javascript@6.2.5': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/lint': 6.9.7 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/javascript': 1.5.4 + + '@codemirror/lang-json@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/json': 1.0.3 + + '@codemirror/lang-markdown@6.5.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-html': 6.4.11 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/markdown': 1.7.2 + + '@codemirror/lang-python@6.2.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@lezer/common': 1.5.2 + '@lezer/python': 1.1.19 + + '@codemirror/lang-yaml@6.1.3': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@lezer/yaml': 1.0.4 + '@codemirror/language@6.12.4': dependencies: '@codemirror/state': 6.7.1 @@ -2706,6 +3527,30 @@ snapshots: '@lezer/lr': 1.4.10 style-mod: 4.1.3 + '@codemirror/legacy-modes@6.5.3': + dependencies: + '@codemirror/language': 6.12.4 + + '@codemirror/lint@6.9.7': + dependencies: + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + crelt: 1.0.7 + + '@codemirror/merge@6.12.2': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/highlight': 1.2.3 + style-mod: 4.1.3 + + '@codemirror/search@6.7.1': + dependencies: + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + crelt: 1.0.7 + '@codemirror/state@6.7.1': dependencies: '@marijn/find-cluster-break': 1.0.3 @@ -2876,6 +3721,18 @@ snapshots: '@floating-ui/utils@0.2.12': {} + '@fontsource-variable/geist-mono@5.2.7': {} + + '@fontsource-variable/inter@5.2.8': {} + + '@iconify/types@2.0.0': {} + + '@iconify/utils@3.1.4': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@iconify/types': 2.0.0 + import-meta-resolve: 4.2.0 + '@img/colour@1.1.0': {} '@img/sharp-darwin-arm64@0.34.5': @@ -3119,16 +3976,61 @@ snapshots: '@lezer/common@1.5.2': {} + '@lezer/css@1.3.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@lezer/highlight@1.2.3': dependencies: '@lezer/common': 1.5.2 + '@lezer/html@1.3.13': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/javascript@1.5.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/json@1.0.3': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@lezer/lr@1.4.10': dependencies: '@lezer/common': 1.5.2 + '@lezer/markdown@1.7.2': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + + '@lezer/python@1.1.19': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + + '@lezer/yaml@1.0.4': + dependencies: + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@marijn/find-cluster-break@1.0.3': {} + '@mermaid-js/parser@1.2.0': + dependencies: + '@chevrotain/types': 11.1.2 + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 @@ -3301,31 +4203,31 @@ snapshots: '@oozcitak/util@10.0.0': {} - '@opentui/core-darwin-arm64@0.4.5': + '@opentui/core-darwin-arm64@0.4.3': optional: true - '@opentui/core-darwin-x64@0.4.5': + '@opentui/core-darwin-x64@0.4.3': optional: true - '@opentui/core-linux-arm64-musl@0.4.5': + '@opentui/core-linux-arm64-musl@0.4.3': optional: true - '@opentui/core-linux-arm64@0.4.5': + '@opentui/core-linux-arm64@0.4.3': optional: true - '@opentui/core-linux-x64-musl@0.4.5': + '@opentui/core-linux-x64-musl@0.4.3': optional: true - '@opentui/core-linux-x64@0.4.5': + '@opentui/core-linux-x64@0.4.3': optional: true - '@opentui/core-win32-arm64@0.4.5': + '@opentui/core-win32-arm64@0.4.3': optional: true - '@opentui/core-win32-x64@0.4.5': + '@opentui/core-win32-x64@0.4.3': optional: true - '@opentui/core@0.4.5(typescript@5.9.3)(web-tree-sitter@0.25.10)': + '@opentui/core@0.4.3(typescript@5.9.3)(web-tree-sitter@0.25.10)': dependencies: bun-ffi-structs: 0.2.4(typescript@5.9.3) diff: 9.0.0 @@ -3334,20 +4236,20 @@ snapshots: strip-ansi: 7.1.2 web-tree-sitter: 0.25.10 optionalDependencies: - '@opentui/core-darwin-arm64': 0.4.5 - '@opentui/core-darwin-x64': 0.4.5 - '@opentui/core-linux-arm64': 0.4.5 - '@opentui/core-linux-arm64-musl': 0.4.5 - '@opentui/core-linux-x64': 0.4.5 - '@opentui/core-linux-x64-musl': 0.4.5 - '@opentui/core-win32-arm64': 0.4.5 - '@opentui/core-win32-x64': 0.4.5 + '@opentui/core-darwin-arm64': 0.4.3 + '@opentui/core-darwin-x64': 0.4.3 + '@opentui/core-linux-arm64': 0.4.3 + '@opentui/core-linux-arm64-musl': 0.4.3 + '@opentui/core-linux-x64': 0.4.3 + '@opentui/core-linux-x64-musl': 0.4.3 + '@opentui/core-win32-arm64': 0.4.3 + '@opentui/core-win32-x64': 0.4.3 transitivePeerDependencies: - typescript - '@opentui/react@0.4.5(react-devtools-core@7.0.1)(react@19.2.7)(typescript@5.9.3)(web-tree-sitter@0.25.10)(ws@8.19.0)': + '@opentui/react@0.4.3(react-devtools-core@7.0.1)(react@19.2.7)(typescript@5.9.3)(web-tree-sitter@0.25.10)(ws@8.19.0)': dependencies: - '@opentui/core': 0.4.5(typescript@5.9.3)(web-tree-sitter@0.25.10) + '@opentui/core': 0.4.3(typescript@5.9.3)(web-tree-sitter@0.25.10) react: 19.2.7 react-devtools-core: 7.0.1 react-reconciler: 0.33.0(react@19.2.7) @@ -3536,6 +4438,122 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@pierre/diffs@1.2.8(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@pierre/theme': 1.0.3 + '@shikijs/transformers': 3.23.0 + diff: 8.0.3 + hast-util-to-html: 9.0.5 + lru_map: 0.4.1 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + shiki: 3.23.0 + + '@pierre/theme@1.0.3': {} + + '@plannotator/atomic-editor@0.8.0(@codemirror/autocomplete@6.20.3)(@codemirror/commands@6.10.4)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-markdown@6.5.1)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/merge@6.12.2)(@codemirror/search@6.7.1)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)(@lezer/common@1.5.2)(@lezer/highlight@1.2.3)(@lezer/markdown@1.7.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3)': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/commands': 6.10.4 + '@codemirror/lang-markdown': 6.5.1 + '@codemirror/language': 6.12.4 + '@codemirror/merge': 6.12.2 + '@codemirror/search': 6.7.1 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/markdown': 1.7.2 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-html': 6.4.11 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/legacy-modes': 6.5.3 + typescript: 5.9.3 + + '@plannotator/core@0.22.0': {} + + '@plannotator/markdown-editor@0.4.0(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/state@6.7.1)(@plannotator/atomic-editor@0.8.0(@codemirror/autocomplete@6.20.3)(@codemirror/commands@6.10.4)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-markdown@6.5.1)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/merge@6.12.2)(@codemirror/search@6.7.1)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)(@lezer/common@1.5.2)(@lezer/highlight@1.2.3)(@lezer/markdown@1.7.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.1 + '@plannotator/atomic-editor': 0.8.0(@codemirror/autocomplete@6.20.3)(@codemirror/commands@6.10.4)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-markdown@6.5.1)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/merge@6.12.2)(@codemirror/search@6.7.1)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)(@lezer/common@1.5.2)(@lezer/highlight@1.2.3)(@lezer/markdown@1.7.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/legacy-modes': 6.5.3 + + '@plannotator/ui@0.28.0(patch_hash=2874e34359989695f812abcb58cd0672830ce9a48ebebbd770fb1d72db4fc11f)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@lezer/markdown@1.7.2)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.2)(typescript@5.9.3)': + dependencies: + '@base-ui/react': 1.6.0(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@codemirror/autocomplete': 6.20.3 + '@codemirror/commands': 6.10.4 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-markdown': 6.5.1 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/language': 6.12.4 + '@codemirror/legacy-modes': 6.5.3 + '@codemirror/merge': 6.12.2 + '@codemirror/search': 6.7.1 + '@codemirror/state': 6.7.1 + '@codemirror/view': 6.43.6 + '@fontsource-variable/geist-mono': 5.2.7 + '@fontsource-variable/inter': 5.2.8 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@pierre/diffs': 1.2.8(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@plannotator/atomic-editor': 0.8.0(@codemirror/autocomplete@6.20.3)(@codemirror/commands@6.10.4)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-markdown@6.5.1)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/merge@6.12.2)(@codemirror/search@6.7.1)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)(@lezer/common@1.5.2)(@lezer/highlight@1.2.3)(@lezer/markdown@1.7.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3) + '@plannotator/core': 0.22.0 + '@plannotator/markdown-editor': 0.4.0(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/state@6.7.1)(@plannotator/atomic-editor@0.8.0(@codemirror/autocomplete@6.20.3)(@codemirror/commands@6.10.4)(@codemirror/lang-css@6.3.1)(@codemirror/lang-html@6.4.11)(@codemirror/lang-javascript@6.2.5)(@codemirror/lang-json@6.0.2)(@codemirror/lang-markdown@6.5.1)(@codemirror/lang-python@6.2.1)(@codemirror/lang-yaml@6.1.3)(@codemirror/language@6.12.4)(@codemirror/legacy-modes@6.5.3)(@codemirror/merge@6.12.2)(@codemirror/search@6.7.1)(@codemirror/state@6.7.1)(@codemirror/view@6.43.6)(@lezer/common@1.5.2)(@lezer/highlight@1.2.3)(@lezer/markdown@1.7.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@plannotator/web-highlighter': 0.8.1 + '@tanstack/react-table': 8.21.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@viz-js/viz': 3.28.0 + class-variance-authority: 0.7.1 + clsx: 2.1.1 + diff: 8.0.4 + dompurify: 3.4.12 + highlight.js: 11.11.1 + katex: 0.16.47 + lucide-react: 1.24.0(react@19.2.7) + marked: 17.0.6 + mermaid: 11.16.0 + motion: 12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + perfect-freehand: 1.2.3 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + tailwind-merge: 3.6.0 + tailwindcss: 4.3.2 + unique-username-generator: 1.5.1 + transitivePeerDependencies: + - '@codemirror/lang-cpp' + - '@codemirror/lang-css' + - '@codemirror/lang-go' + - '@codemirror/lang-html' + - '@codemirror/lang-java' + - '@codemirror/lang-php' + - '@codemirror/lang-rust' + - '@codemirror/lang-sql' + - '@codemirror/lang-xml' + - '@date-fns/tz' + - '@emotion/is-prop-valid' + - '@lezer/markdown' + - '@types/react' + - date-fns + - typescript + + '@plannotator/web-highlighter@0.8.1': {} + '@poppinss/colors@4.1.6': dependencies: kleur: 4.1.5 @@ -3601,78 +4619,116 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} + '@shikijs/core@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/transformers@3.23.0': + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/types': 3.23.0 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/vscode-textmate@10.0.2': {} + '@sindresorhus/is@7.2.0': {} '@speed-highlight/core@1.2.17': {} '@standard-schema/spec@1.1.0': {} - '@tailwindcss/node@4.3.3': + '@tailwindcss/node@4.3.2': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.24.3 + enhanced-resolve: 5.21.6 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.3.3 + tailwindcss: 4.3.2 - '@tailwindcss/oxide-android-arm64@4.3.3': + '@tailwindcss/oxide-android-arm64@4.3.2': optional: true - '@tailwindcss/oxide-darwin-arm64@4.3.3': + '@tailwindcss/oxide-darwin-arm64@4.3.2': optional: true - '@tailwindcss/oxide-darwin-x64@4.3.3': + '@tailwindcss/oxide-darwin-x64@4.3.2': optional: true - '@tailwindcss/oxide-freebsd-x64@4.3.3': + '@tailwindcss/oxide-freebsd-x64@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.3.3': + '@tailwindcss/oxide-linux-x64-musl@4.3.2': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.3.3': + '@tailwindcss/oxide-wasm32-wasi@4.3.2': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': optional: true - '@tailwindcss/oxide@4.3.3': + '@tailwindcss/oxide@4.3.2': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.3 - '@tailwindcss/oxide-darwin-arm64': 4.3.3 - '@tailwindcss/oxide-darwin-x64': 4.3.3 - '@tailwindcss/oxide-freebsd-x64': 4.3.3 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 - '@tailwindcss/oxide-linux-x64-musl': 4.3.3 - '@tailwindcss/oxide-wasm32-wasi': 4.3.3 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 - - '@tailwindcss/vite@4.3.3(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': - dependencies: - '@tailwindcss/node': 4.3.3 - '@tailwindcss/oxide': 4.3.3 - tailwindcss: 4.3.3 + '@tailwindcss/oxide-android-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-x64': 4.3.2 + '@tailwindcss/oxide-freebsd-x64': 4.3.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 + + '@tailwindcss/vite@4.3.2(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + tailwindcss: 4.3.2 vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) '@tanstack/history@1.162.0': {} @@ -3774,6 +4830,12 @@ snapshots: react-dom: 19.2.7(react@19.2.7) use-sync-external-store: 1.6.0(react@19.2.7) + '@tanstack/react-table@8.21.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@tanstack/table-core': 8.21.3 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + '@tanstack/router-core@1.171.15': dependencies: '@tanstack/history': 1.162.0 @@ -3851,7 +4913,7 @@ snapshots: '@tanstack/router-utils': 1.162.2 '@tanstack/start-server-core': 1.169.17 exsolve: 1.1.0 - lightningcss: 1.33.0 + lightningcss: 1.32.0 pathe: 2.0.3 picomatch: 4.0.5 seroval: 1.5.6 @@ -3896,6 +4958,8 @@ snapshots: '@tanstack/store@0.9.3': {} + '@tanstack/table-core@8.21.3': {} + '@tanstack/virtual-file-routes@1.162.0': {} '@tybys/wasm-util@0.10.3': @@ -3910,10 +4974,137 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.4': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} + '@types/geojson@7946.0.16': {} + + '@types/hast@3.0.5': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + '@types/node@22.20.1': dependencies: undici-types: 6.21.0 @@ -3930,10 +5121,22 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/trusted-types@2.0.7': + optional: true + + '@types/unist@3.0.3': {} + '@types/ws@8.18.1': dependencies: '@types/node': 24.13.3 + '@ungap/structured-clone@1.3.3': {} + + '@upsetjs/venn.js@2.0.0': + optionalDependencies: + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + '@vitejs/plugin-react@6.0.3(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 @@ -3980,6 +5183,8 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@viz-js/viz@3.28.0': {} + ansi-regex@6.2.2: {} ansis@4.3.1: {} @@ -4041,8 +5246,14 @@ snapshots: - valibot - ws + ccount@2.0.1: {} + chai@6.2.2: {} + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + chardet@2.2.0: {} chokidar@5.0.0: @@ -4057,8 +5268,14 @@ snapshots: clsx@2.1.1: {} + comma-separated-tokens@2.0.3: {} + commander@14.0.3: {} + commander@7.2.0: {} + + commander@8.3.0: {} + content-type@2.0.0: {} convert-source-map@2.0.0: {} @@ -4067,25 +5284,235 @@ snapshots: cookie@1.1.1: {} + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + crelt@1.0.7: {} csstype@3.2.3: {} + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.0): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.34.0 + + cytoscape-fcose@2.2.0(cytoscape@3.34.0): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.34.0 + + cytoscape@3.34.0: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.1.0 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.14: + dependencies: + d3: 7.9.0 + lodash-es: 4.18.1 + + dayjs@1.11.21: {} + debug@4.4.3: dependencies: ms: 2.1.3 + delaunator@5.1.0: + dependencies: + robust-predicates: 3.0.3 + + dequal@2.0.3: {} + detect-libc@2.1.2: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@8.0.3: {} + diff@8.0.4: {} diff@9.0.0: {} + dompurify@3.4.12: + optionalDependencies: + '@types/trusted-types': 2.0.7 + electron-to-chromium@1.5.393: {} emoji-regex@10.6.0: {} - enhanced-resolve@5.24.3: + enhanced-resolve@5.21.6: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -4094,6 +5521,8 @@ snapshots: es-module-lexer@2.3.1: {} + es-toolkit@1.49.0: {} + esbuild@0.28.1: optionalDependencies: '@esbuild/aix-ppc64': 0.28.1 @@ -4149,6 +5578,15 @@ snapshots: fetchdts@0.1.7: {} + framer-motion@12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + motion-dom: 12.42.2 + motion-utils: 12.39.0 + tslib: 2.8.1 + optionalDependencies: + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + fsevents@2.3.3: optional: true @@ -4163,10 +5601,44 @@ snapshots: rou3: 0.8.1 srvx: 0.11.22 + hachure-fill@0.5.2: {} + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.5 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.2.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.5 + + highlight.js@11.11.1: {} + + html-void-elements@3.0.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 + import-meta-resolve@4.2.0: {} + + internmap@1.0.1: {} + + internmap@2.0.3: {} + isbot@5.2.1: {} isomorphic.js@0.2.5: {} @@ -4174,8 +5646,8 @@ snapshots: iterate@https://pkg.pr.new/iterate/iterate/iterate@b62c471f4(@tanstack/react-query@5.101.2(react@19.2.7))(react-devtools-core@7.0.1)(react@19.2.7)(typescript@5.9.3)(web-tree-sitter@0.25.10): dependencies: '@clack/prompts': 1.7.0 - '@opentui/core': 0.4.5(typescript@5.9.3)(web-tree-sitter@0.25.10) - '@opentui/react': 0.4.5(react-devtools-core@7.0.1)(react@19.2.7)(typescript@5.9.3)(web-tree-sitter@0.25.10)(ws@8.19.0) + '@opentui/core': 0.4.3(typescript@5.9.3)(web-tree-sitter@0.25.10) + '@opentui/react': 0.4.3(react-devtools-core@7.0.1)(react@19.2.7)(typescript@5.9.3)(web-tree-sitter@0.25.10)(ws@8.19.0) '@orpc/client': 1.13.14 '@orpc/server': 1.13.14(ws@8.19.0) '@tanstack/react-query': 5.101.2(react@19.2.7) @@ -4184,7 +5656,7 @@ snapshots: capnweb: '@iterate-com/capnweb@0.10.0' octokit: 5.0.5 react: 19.2.7 - trpc-cli: 0.15.1(@orpc/server@1.13.14(ws@8.19.0))(zod@4.3.6) + trpc-cli: 0.15.1(@orpc/server@1.13.14(ws@8.21.1))(zod@4.3.6) ws: 8.19.0 zod: 4.3.6 transitivePeerDependencies: @@ -4215,8 +5687,18 @@ snapshots: json5@2.2.3: {} + katex@0.16.47: + dependencies: + commander: 8.3.0 + + khroma@2.1.0: {} + kleur@4.1.5: {} + layout-base@1.0.2: {} + + layout-base@2.0.1: {} + lib0@0.2.117: dependencies: isomorphic.js: 0.2.5 @@ -4224,69 +5706,36 @@ snapshots: lightningcss-android-arm64@1.32.0: optional: true - lightningcss-android-arm64@1.33.0: - optional: true - lightningcss-darwin-arm64@1.32.0: optional: true - lightningcss-darwin-arm64@1.33.0: - optional: true - lightningcss-darwin-x64@1.32.0: optional: true - lightningcss-darwin-x64@1.33.0: - optional: true - lightningcss-freebsd-x64@1.32.0: optional: true - lightningcss-freebsd-x64@1.33.0: - optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: optional: true - lightningcss-linux-arm-gnueabihf@1.33.0: - optional: true - lightningcss-linux-arm64-gnu@1.32.0: optional: true - lightningcss-linux-arm64-gnu@1.33.0: - optional: true - lightningcss-linux-arm64-musl@1.32.0: optional: true - lightningcss-linux-arm64-musl@1.33.0: - optional: true - lightningcss-linux-x64-gnu@1.32.0: optional: true - lightningcss-linux-x64-gnu@1.33.0: - optional: true - lightningcss-linux-x64-musl@1.32.0: optional: true - lightningcss-linux-x64-musl@1.33.0: - optional: true - lightningcss-win32-arm64-msvc@1.32.0: optional: true - lightningcss-win32-arm64-msvc@1.33.0: - optional: true - lightningcss-win32-x64-msvc@1.32.0: optional: true - lightningcss-win32-x64-msvc@1.33.0: - optional: true - lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 @@ -4303,21 +5752,7 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 - lightningcss@1.33.0: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.33.0 - lightningcss-darwin-arm64: 1.33.0 - lightningcss-darwin-x64: 1.33.0 - lightningcss-freebsd-x64: 1.33.0 - lightningcss-linux-arm-gnueabihf: 1.33.0 - lightningcss-linux-arm64-gnu: 1.33.0 - lightningcss-linux-arm64-musl: 1.33.0 - lightningcss-linux-x64-gnu: 1.33.0 - lightningcss-linux-x64-musl: 1.33.0 - lightningcss-win32-arm64-msvc: 1.33.0 - lightningcss-win32-x64-msvc: 1.33.0 + lodash-es@4.18.1: {} lodash.debounce@4.0.8: {} @@ -4325,16 +5760,79 @@ snapshots: dependencies: yallist: 3.1.1 + lru_map@0.4.1: {} + lucide-react@0.553.0(react@19.2.7): dependencies: react: 19.2.7 + lucide-react@1.24.0(react@19.2.7): + dependencies: + react: 19.2.7 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + marked@16.4.2: {} + marked@17.0.1: {} + marked@17.0.6: {} + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.3 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mermaid@11.16.0: + dependencies: + '@braintree/sanitize-url': 7.1.2 + '@iconify/utils': 3.1.4 + '@mermaid-js/parser': 1.2.0 + '@types/d3': 7.4.3 + '@upsetjs/venn.js': 2.0.0 + cytoscape: 3.34.0 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.0) + cytoscape-fcose: 2.2.0(cytoscape@3.34.0) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.14 + dayjs: 1.11.21 + dompurify: 3.4.12 + es-toolkit: 1.49.0 + katex: 0.16.47 + khroma: 2.1.0 + marked: 16.4.2 + roughjs: 4.6.6 + stylis: 4.4.0 + ts-dedent: 2.3.0 + uuid: 14.0.1 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + miniflare@4.20260701.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -4347,6 +5845,20 @@ snapshots: - bufferutil - utf-8-validate + motion-dom@12.42.2: + dependencies: + motion-utils: 12.39.0 + + motion-utils@12.39.0: {} + + motion@12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + framer-motion: 12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + tslib: 2.8.1 + optionalDependencies: + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + ms@2.1.3: {} mute-stream@3.0.0: {} @@ -4373,21 +5885,42 @@ snapshots: '@octokit/types': 16.0.0 '@octokit/webhooks': 14.2.0 + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + openapi-types@12.1.3: {} + package-manager-detector@1.7.0: {} + partyserver@0.5.8(@cloudflare/workers-types@4.20260702.1): dependencies: '@cloudflare/workers-types': 4.20260702.1 nanoid: 5.1.16 + path-data-parser@0.1.0: {} + path-to-regexp@6.3.0: {} pathe@2.0.3: {} + perfect-freehand@1.2.3: {} + picocolors@1.1.1: {} picomatch@4.0.5: {} + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + postcss@8.5.20: dependencies: nanoid: 3.3.16 @@ -4396,12 +5929,14 @@ snapshots: prettier@3.9.5: {} + property-information@7.2.0: {} + radash@12.1.1: {} react-devtools-core@7.0.1: dependencies: shell-quote: 1.10.0 - ws: 7.5.13 + ws: 7.5.12 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4420,8 +5955,20 @@ snapshots: readdirp@5.0.0: {} + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + reselect@5.2.0: {} + robust-predicates@3.0.3: {} + rolldown@1.1.5: dependencies: '@oxc-project/types': 0.139.0 @@ -4445,6 +5992,15 @@ snapshots: rou3@0.8.1: {} + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + + rw@1.3.3: {} + safer-buffer@2.1.2: {} scheduler@0.27.0: {} @@ -4492,6 +6048,17 @@ snapshots: shell-quote@1.10.0: {} + shiki@3.23.0: + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/engine-javascript': 3.23.0 + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + siginfo@2.0.0: {} signal-exit@4.1.0: {} @@ -4502,6 +6069,8 @@ snapshots: source-map@0.7.6: {} + space-separated-tokens@2.0.2: {} + srvx@0.11.22: {} stackback@0.0.2: {} @@ -4514,19 +6083,26 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.1.2 + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@7.1.2: dependencies: ansi-regex: 6.2.2 style-mod@4.1.3: {} + stylis@4.4.0: {} + supports-color@10.2.2: {} tagged-tag@1.0.0: {} tailwind-merge@3.6.0: {} - tailwindcss@4.3.3: {} + tailwindcss@4.3.2: {} tapable@2.3.3: {} @@ -4543,6 +6119,8 @@ snapshots: toad-cache@3.7.4: {} + trim-lines@3.0.1: {} + trpc-cli@0.14.1(@orpc/server@1.14.8(ws@8.21.1))(zod@4.4.3): dependencies: commander: 14.0.3 @@ -4550,13 +6128,15 @@ snapshots: '@orpc/server': 1.14.8(ws@8.21.1) zod: 4.4.3 - trpc-cli@0.15.1(@orpc/server@1.13.14(ws@8.19.0))(zod@4.3.6): + trpc-cli@0.15.1(@orpc/server@1.13.14(ws@8.21.1))(zod@4.3.6): dependencies: commander: 14.0.3 optionalDependencies: '@orpc/server': 1.13.14(ws@8.19.0) zod: 4.3.6 + ts-dedent@2.3.0: {} + tslib@2.8.1: {} tw-animate-css@1.4.0: {} @@ -4579,6 +6159,31 @@ snapshots: dependencies: pathe: 2.0.3 + unique-username-generator@1.5.1: {} + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + universal-github-app-jwt@2.2.2: {} universal-user-agent@7.0.3: {} @@ -4603,9 +6208,21 @@ snapshots: dependencies: react: 19.2.7 + uuid@14.0.1: {} + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0): dependencies: - lightningcss: 1.33.0 + lightningcss: 1.32.0 picomatch: 4.0.5 postcss: 8.5.20 rolldown: 1.1.5 @@ -4684,7 +6301,7 @@ snapshots: - bufferutil - utf-8-validate - ws@7.5.13: {} + ws@7.5.12: {} ws@8.19.0: {} @@ -4745,3 +6362,5 @@ snapshots: zod@4.3.6: {} zod@4.4.3: {} + + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ecf9409..07126e8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,4 +2,14 @@ # caught and unpublished within days) and never accept weakened trust # signals on update. minimumReleaseAge: 10080 + +overrides: + '@opentui/core': 0.4.3 + '@opentui/react': 0.4.3 + '@tailwindcss/oxide': 4.3.2 + lightningcss: 1.32.0 + +patchedDependencies: + '@plannotator/ui@0.28.0': patches/@plannotator__ui@0.28.0.patch + trustPolicy: no-downgrade diff --git a/scripts/dev-local.sh b/scripts/dev-local.sh index b1f427f..8a09d52 100755 --- a/scripts/dev-local.sh +++ b/scripts/dev-local.sh @@ -53,5 +53,5 @@ nohup node "$TASKS_DIR/scripts/local-proxy.mjs" "$PROXY_PORT" "$TASKS_PORT" "$PR > /tmp/tasks-proxy.log 2>&1 & sleep 0.5 echo -echo "open: http://localhost:$PROXY_PORT (token expires in 15 min — rerun to refresh)" +echo "open: http://localhost:$PROXY_PORT/w/local-review (token expires in 15 min — rerun to refresh)" echo "probes: node scripts/probe-rpc.mjs http://localhost:$TASKS_PORT $PROJECT_ID " diff --git a/src/components/workspace-task-review.tsx b/src/components/workspace-task-review.tsx new file mode 100644 index 0000000..fc2bf88 --- /dev/null +++ b/src/components/workspace-task-review.tsx @@ -0,0 +1,82 @@ +import { useMemo } from "react"; +import { Viewer } from "@plannotator/ui/components/Viewer"; +import { AnnotationPanel } from "@plannotator/ui/components/AnnotationPanel"; +import { ThemeProvider } from "@plannotator/ui/components/ThemeProvider"; +import { exportAnnotations, parseMarkdownToBlocks } from "@plannotator/ui/utils/parser"; +import { annotateFileFeedback } from "@plannotator/core/feedback-templates"; +import type { Annotation } from "@plannotator/ui/types"; +import { useWorkspaceAnnotations } from "../lib/workspace-annotations-client.ts"; +import "@plannotator/ui/styles.css"; + +export function WorkspaceTaskReview({ + checkoutId, + repoPath, + path, + markdown, + selectedAnnotationId, + onSelectAnnotation, +}: { + checkoutId: string; + repoPath: string; + path: string; + markdown: string; + selectedAnnotationId: string | null; + onSelectAnnotation: (id: string | null) => void; +}) { + const review = useWorkspaceAnnotations(checkoutId, repoPath, path); + const blocks = useMemo(() => parseMarkdownToBlocks(markdown), [markdown]); + + const remove = (id: string) => { + if (selectedAnnotationId === id) onSelectAnnotation(null); + void review.remove(id); + }; + + return ( + +
+
+

+ {review.status === "live" + ? `${review.annotations.length} annotations · live` + : "connecting review…"} +

+ {review.error === null ? null : ( +

+ review sync failed: {review.error} +

+ )} + void review.add(annotation)} + onSelectAnnotation={onSelectAnnotation} + selectedAnnotationId={selectedAnnotationId} + mode="selection" + taterMode={false} + disableCodePathValidation={true} + allowImages={false} + gridEnabled={true} + maxWidth={900} + copyLabel="Copy task" + /> +
+ onSelectAnnotation(id)} + onDelete={remove} + onEdit={(id, updates: Partial) => void review.update(id, updates)} + selectedId={selectedAnnotationId} + sharingEnabled={true} + width={300} + onQuickCopy={async () => { + const feedback = exportAnnotations(blocks, review.annotations, [], "Task review", "task"); + await navigator.clipboard.writeText(annotateFileFeedback(feedback, { filePath: path })); + }} + /> +
+
+ ); +} diff --git a/src/components/workspace-task-sheet.tsx b/src/components/workspace-task-sheet.tsx index 8904f70..a1ea833 100644 --- a/src/components/workspace-task-sheet.tsx +++ b/src/components/workspace-task-sheet.tsx @@ -1,4 +1,5 @@ import { lazy, Suspense, useState } from "react"; +import { ClientOnly } from "@tanstack/react-router"; import { RotateCcwIcon, Trash2Icon } from "lucide-react"; import { Input } from "../ui/input.tsx"; import { Sheet, SheetContent, SheetHeader, SheetTitle } from "../ui/sheet.tsx"; @@ -33,6 +34,12 @@ const WorkspaceTaskEditor = lazy(() => })), ); +const WorkspaceTaskReview = lazy(() => + import("./workspace-task-review.tsx").then((module) => ({ + default: module.WorkspaceTaskReview, + })), +); + /** * The task detail sheet on the WORKSPACE lane: the shared collab-editor * state machine (rebase model over the vessel WS) with the redline layers @@ -55,6 +62,10 @@ export function WorkspaceTaskSheet({ onRevert, onDelete, onClose, + view, + selectedAnnotationId, + onSelectAnnotation, + onViewChange, }: { task: BoardTask | null; checkoutId: string; @@ -75,6 +86,10 @@ export function WorkspaceTaskSheet({ onRevert: () => void; onDelete: () => void; onClose: () => void; + view: "edit" | "review"; + selectedAnnotationId: string | null; + onSelectAnnotation: (id: string | null) => void; + onViewChange: (view: "edit" | "review") => void; }) { return ( (open ? undefined : onClose())}> @@ -100,6 +115,10 @@ export function WorkspaceTaskSheet({ onChangeLabels={onChangeLabels} onRevert={onRevert} onDelete={onDelete} + view={view} + selectedAnnotationId={selectedAnnotationId} + onSelectAnnotation={onSelectAnnotation} + onViewChange={onViewChange} /> )} @@ -123,6 +142,10 @@ function SheetBody({ onChangeLabels, onRevert, onDelete, + view, + selectedAnnotationId, + onSelectAnnotation, + onViewChange, }: { task: BoardTask; checkoutId: string; @@ -142,6 +165,10 @@ function SheetBody({ onChangeLabels: (labels: string[]) => void; onRevert: () => void; onDelete: () => void; + view: "edit" | "review"; + selectedAnnotationId: string | null; + onSelectAnnotation: (id: string | null) => void; + onViewChange: (view: "edit" | "review") => void; }) { const [status, setStatus] = useState("connecting…"); // The path is editable in place; SheetBody is keyed by task.path, so a @@ -198,6 +225,24 @@ function SheetBody({ {pathError !== null &&

{pathError}

}
+
+ + +
- {status} + {view === "edit" ? ( + {status} + ) : null} {changeStatus === undefined ? null : (
- Loading editor…

} - > - -
+ {view === "edit" ? ( + Loading editor…

} + > + +
+ ) : ( + Loading review…

} + > + Loading review…

} + > + +
+
+ )} ); } diff --git a/src/lib/tasks-api.ts b/src/lib/tasks-api.ts index 3e884f0..532e409 100644 --- a/src/lib/tasks-api.ts +++ b/src/lib/tasks-api.ts @@ -1,4 +1,6 @@ +import type { Annotation } from "@plannotator/ui/types"; import type { CommitResult, TaskChangeSummary } from "../state.ts"; +import type { WorkspaceAnnotationSnapshot } from "./workspace-annotations.ts"; /** * The vessel's ONE public API: a Cap'n Web WebSocket session at `/api`. @@ -142,6 +144,11 @@ export interface TasksWorkspace { processEventBatch: (batch: { events: WorkspaceStreamEvent[] }) => unknown, afterOffset?: number, ): Promise<{ ping?(): Promise | boolean; unsubscribe(): void }>; + /** Plannotator review state, durably folded from this workspace's stream. */ + annotations(filePath: string): Promise; + addAnnotation(filePath: string, annotation: Annotation): Promise; + updateAnnotation(filePath: string, id: string, updates: Partial): Promise; + removeAnnotation(filePath: string, id: string): Promise; /** Every task file in the merged view (board seed). */ files(): Promise>; /** Filesystem trio with the platform gateway's semantics: live sessions diff --git a/src/lib/use-checkout.ts b/src/lib/use-checkout.ts index 5b679ec..f2cb3d5 100644 --- a/src/lib/use-checkout.ts +++ b/src/lib/use-checkout.ts @@ -5,6 +5,7 @@ import { newWebSocketRpcSession } from "capnweb"; import type { CommitResult } from "../state.ts"; import type { CheckoutIndexEntry, TasksApi, TasksUser } from "./tasks-api.ts"; import { registerCollaborator } from "./checkout-shared.ts"; +import { waitForWebSocketOpen } from "./websocket-ready.ts"; export type CheckoutStatus = "connecting" | "connected" | "ready" | "disconnected"; @@ -113,34 +114,38 @@ const docVersions = new WeakMap(); * token in browser land), shared by every op on the page, and redialed once * when a call finds the session broken. */ -function dialTasksApi() { +async function dialTasksApi() { const url = new URL("/api", window.location.href); url.protocol = url.protocol === "https:" ? "wss:" : "ws:"; - const session = newWebSocketRpcSession(url.toString()); - return { session, project: session.authenticate() }; + const socket = new WebSocket(url); + await waitForWebSocketOpen(socket); + const session = newWebSocketRpcSession(socket); + return { project: session.authenticate(), session, socket }; } let liveApi: ReturnType | null = null; export async function withProject( - operation: (project: ReturnType["project"]) => PromiseLike, + operation: ( + project: Awaited>["project"], + ) => PromiseLike, ): Promise { liveApi ??= dialTasksApi(); + const current = liveApi; + let api: Awaited; try { - return await operation(liveApi.project); - } catch (firstError) { - try { - (liveApi.session as { [Symbol.dispose]?: () => void })[Symbol.dispose]?.(); - } catch { - // a broken session may already be gone - } - liveApi = dialTasksApi(); - try { - return await operation(liveApi.project); - } catch (secondError) { - liveApi = null; - throw secondError ?? firstError; - } + api = await current; + } catch (cause) { + if (liveApi === current) liveApi = null; + throw cause; + } + try { + return await operation(api.project); + } catch (cause) { + // Application errors belong to their caller. Only a transport that is + // observably no longer OPEN invalidates the shared connection. + if (api.socket.readyState !== WebSocket.OPEN && liveApi === current) liveApi = null; + throw cause; } } diff --git a/src/lib/websocket-ready.test.ts b/src/lib/websocket-ready.test.ts new file mode 100644 index 0000000..9877cae --- /dev/null +++ b/src/lib/websocket-ready.test.ts @@ -0,0 +1,38 @@ +import { expect, test, vi } from "vitest"; +import { waitForWebSocketOpen } from "./websocket-ready.ts"; + +test("waits for the browser WebSocket before RPC authentication starts", async () => { + const socket = new ControllableSocket(); + const authenticate = vi.fn(); + + const ready = waitForWebSocketOpen(socket).then(authenticate); + await Promise.resolve(); + expect(authenticate).not.toHaveBeenCalled(); + + socket.open(); + await ready; + expect(authenticate).toHaveBeenCalledOnce(); +}); + +test("surfaces a socket that closes before opening", async () => { + const socket = new ControllableSocket(); + const ready = waitForWebSocketOpen(socket); + + socket.close(); + + await expect(ready).rejects.toThrow("WebSocket closed before opening"); +}); + +class ControllableSocket extends EventTarget { + readyState = 0; + + open() { + this.readyState = 1; + this.dispatchEvent(new Event("open")); + } + + close() { + this.readyState = 3; + this.dispatchEvent(new Event("close")); + } +} diff --git a/src/lib/websocket-ready.ts b/src/lib/websocket-ready.ts new file mode 100644 index 0000000..2d37d84 --- /dev/null +++ b/src/lib/websocket-ready.ts @@ -0,0 +1,38 @@ +type WebSocketReadyTarget = { + readyState: number; + addEventListener(type: string, listener: EventListener): void; + removeEventListener(type: string, listener: EventListener): void; +}; + +/** Native browser WebSockets reject send() while CONNECTING. Cap'n Web can + * pipeline RPC calls once attached, but authentication must start only after + * the transport itself reaches OPEN. */ +export function waitForWebSocketOpen(socket: WebSocketReadyTarget): Promise { + if (socket.readyState === 1) return Promise.resolve(); + if (socket.readyState > 1) { + return Promise.reject(new Error("WebSocket closed before opening")); + } + + return new Promise((resolve, reject) => { + const cleanup = () => { + socket.removeEventListener("open", onOpen); + socket.removeEventListener("close", onClose); + socket.removeEventListener("error", onError); + }; + const onOpen = () => { + cleanup(); + resolve(); + }; + const onClose = () => { + cleanup(); + reject(new Error("WebSocket closed before opening")); + }; + const onError = () => { + cleanup(); + reject(new Error("WebSocket failed before opening")); + }; + socket.addEventListener("open", onOpen); + socket.addEventListener("close", onClose); + socket.addEventListener("error", onError); + }); +} diff --git a/src/lib/workspace-annotations-client.ts b/src/lib/workspace-annotations-client.ts new file mode 100644 index 0000000..037bf36 --- /dev/null +++ b/src/lib/workspace-annotations-client.ts @@ -0,0 +1,202 @@ +import { useMemo, useSyncExternalStore } from "react"; +import type { Annotation } from "@plannotator/ui/types"; +import { configurePlannotatorUI } from "@plannotator/ui/configure"; +import { whoami, withProject } from "./use-checkout.ts"; +import type { + TasksUser, + TasksWorkspace, + WorkspaceStreamEvent, +} from "./tasks-api.ts"; +import { isWorkspaceAnnotationEventForPath } from "./workspace-annotations.ts"; + +let verifiedIdentity = "iterate user"; + +configurePlannotatorUI({ + identityProvider: { + getIdentity: () => verifiedIdentity, + isCurrentUser: (author) => author === verifiedIdentity, + isEditable: () => false, + }, + storageBackend: window.localStorage, +}); + +type AnnotationState = { + annotations: Annotation[]; + error: string | null; + status: "connecting" | "live"; + version: number; +}; + +const SERVER_STATE: AnnotationState = { + annotations: [], + error: null, + status: "connecting", + version: 0, +}; + +export function useWorkspaceAnnotations( + checkoutId: string, + repoPath: string, + filePath: string, +) { + const store = useMemo( + () => new WorkspaceAnnotationsStore(checkoutId, repoPath, filePath), + [checkoutId, repoPath, filePath], + ); + const state = useSyncExternalStore(store.subscribe, store.snapshot, () => SERVER_STATE); + return { ...state, add: store.add, remove: store.remove, update: store.update }; +} + +class WorkspaceAnnotationsStore { + readonly #checkoutId: string; + readonly #repoPath: string; + readonly #filePath: string; + readonly #listeners = new Set<() => void>(); + #state: AnnotationState = SERVER_STATE; + #active = false; + #poll: ReturnType | null = null; + #subscription: { unsubscribe(): void } | null = null; + + constructor(checkoutId: string, repoPath: string, filePath: string) { + this.#checkoutId = checkoutId; + this.#repoPath = repoPath; + this.#filePath = filePath; + } + + snapshot = (): AnnotationState => this.#state; + + subscribe = (listener: () => void): (() => void) => { + this.#listeners.add(listener); + if (this.#listeners.size === 1) this.#start(); + return () => { + this.#listeners.delete(listener); + if (this.#listeners.size === 0) this.#stop(); + }; + }; + + add = async (annotation: Annotation): Promise => { + try { + const created = await this.#lane((workspace) => + workspace.addAnnotation(this.#filePath, annotation), + ); + this.#set({ + ...this.#state, + annotations: [ + ...this.#state.annotations.filter((current) => current.id !== created.id), + created, + ], + error: null, + }); + } catch (cause) { + this.#fail(cause); + } + }; + + update = async (id: string, updates: Partial): Promise => { + const before = this.#state.annotations; + this.#set({ + ...this.#state, + annotations: before.map((annotation) => + annotation.id === id ? { ...annotation, ...updates, id } : annotation, + ), + }); + try { + await this.#lane((workspace) => workspace.updateAnnotation(this.#filePath, id, updates)); + } catch (cause) { + this.#set({ ...this.#state, annotations: before }); + this.#fail(cause); + } + }; + + remove = async (id: string): Promise => { + const before = this.#state.annotations; + this.#set({ + ...this.#state, + annotations: before.filter((annotation) => annotation.id !== id), + }); + try { + await this.#lane((workspace) => workspace.removeAnnotation(this.#filePath, id)); + } catch (cause) { + this.#set({ ...this.#state, annotations: before }); + this.#fail(cause); + } + }; + + #start(): void { + this.#active = true; + void Promise.all([this.#refresh(), whoami()]).then(([, user]) => { + if (!this.#active) return; + verifiedIdentity = userLabel(user); + this.#set({ ...this.#state, status: "live" }); + void this.#connect(); + }).catch((cause) => this.#fail(cause)); + this.#poll = setInterval(() => void this.#refresh(), 2_000); + } + + #stop(): void { + this.#active = false; + if (this.#poll !== null) clearInterval(this.#poll); + this.#poll = null; + try { + this.#subscription?.unsubscribe(); + } catch { + // The Cap'n Web session may already have closed. + } + this.#subscription = null; + } + + async #connect(): Promise { + try { + const handle = await this.#lane((workspace) => + workspace.subscribeEvents( + (batch) => this.#onEvents(batch.events), + this.#state.version, + ), + ); + if (!this.#active) handle.unsubscribe(); + else this.#subscription = handle; + } catch (cause) { + this.#fail(cause); + } + } + + #onEvents(events: WorkspaceStreamEvent[]): void { + if (!this.#active) return; + if (events.some((event) => isWorkspaceAnnotationEventForPath(event, this.#filePath))) { + void this.#refresh(); + } + } + + async #refresh(): Promise { + try { + const next = await this.#lane((workspace) => workspace.annotations(this.#filePath)); + if (!this.#active || next.version < this.#state.version) return; + this.#set({ ...next, error: null, status: "live" }); + } catch (cause) { + this.#fail(cause); + } + } + + #lane(operation: (workspace: TasksWorkspace) => Promise): Promise { + return withProject((project) => + operation(project.workspace(this.#checkoutId, this.#repoPath)), + ); + } + + #fail(cause: unknown): void { + if (!this.#active) return; + this.#set({ + ...this.#state, + error: cause instanceof Error ? cause.message : String(cause), + }); + } + + #set(state: AnnotationState): void { + this.#state = state; + for (const listener of this.#listeners) listener(); + } +} + +function userLabel(user: TasksUser): string { + return user.name || user.email || user.userId || "agent"; +} diff --git a/src/lib/workspace-annotations.test.ts b/src/lib/workspace-annotations.test.ts new file mode 100644 index 0000000..dc67c22 --- /dev/null +++ b/src/lib/workspace-annotations.test.ts @@ -0,0 +1,55 @@ +import { expect, it } from "vitest"; +import { workspaceAnnotationSnapshot } from "./workspace-annotations.ts"; + +it("folds one task's durable review events into its current annotation snapshot", () => { + const first = annotation({ id: "ann-1", text: "Please make this measurable." }); + const otherTask = annotation({ id: "ann-other", text: "Unrelated." }); + + expect( + workspaceAnnotationSnapshot( + [ + event(1, "annotation-added", "tasks/launch.md", { annotation: first }), + event(2, "annotation-added", "tasks/other.md", { annotation: otherTask }), + event(3, "annotation-updated", "tasks/launch.md", { + id: first.id, + updates: { text: "Please add a concrete success metric." }, + }), + event(4, "annotation-added", "tasks/launch.md", { + annotation: annotation({ id: "ann-2", text: "Keep this paragraph." }), + }), + event(5, "annotation-removed", "tasks/launch.md", { id: first.id }), + ], + "tasks/launch.md", + ), + ).toMatchObject({ + annotations: [{ id: "ann-2", text: "Keep this paragraph." }], + version: 5, + }); +}); + +function annotation(input: { id: string; text: string }) { + return { + ...input, + author: "Ada", + blockId: "block-1", + createdA: 1, + endOffset: 4, + originalText: "ship", + startOffset: 0, + type: "COMMENT" as const, + }; +} + +function event( + offset: number, + operation: "annotation-added" | "annotation-updated" | "annotation-removed", + path: string, + fields: Record, +) { + return { + createdAt: `2026-07-22T10:00:0${offset}.000Z`, + offset, + payload: { path, ...fields }, + type: `events.iterate.com/tasks/plannotator/${operation}`, + }; +} diff --git a/src/lib/workspace-annotations.ts b/src/lib/workspace-annotations.ts new file mode 100644 index 0000000..5f2e4cc --- /dev/null +++ b/src/lib/workspace-annotations.ts @@ -0,0 +1,130 @@ +import type { Annotation } from "@plannotator/ui/types"; +import type { WorkspaceStreamEvent } from "./tasks-api.ts"; + +export const WORKSPACE_ANNOTATION_EVENT_PREFIX = + "events.iterate.com/tasks/plannotator/"; + +export type WorkspaceAnnotationSnapshot = { + annotations: Annotation[]; + version: number; +}; + +export type WorkspaceAnnotationAppend = { + payload: Record; + type: string; +}; + +/** Small public interface over the workspace stream's annotation journal. */ +export class WorkspaceAnnotationJournal { + readonly #append: (...events: WorkspaceAnnotationAppend[]) => Promise; + readonly #getEvents: () => Promise; + readonly #verifiedAuthor: string; + + constructor(input: { + append: (...events: WorkspaceAnnotationAppend[]) => Promise; + getEvents: () => Promise; + verifiedAuthor: string; + }) { + this.#append = input.append; + this.#getEvents = input.getEvents; + this.#verifiedAuthor = input.verifiedAuthor; + } + + async snapshot(filePath: string): Promise { + return workspaceAnnotationSnapshot(await this.#getEvents(), filePath); + } + + async add(filePath: string, annotation: Annotation): Promise { + if (annotation.id.trim() === "") throw new Error("annotation id is required"); + const created = { ...annotation, author: this.#verifiedAuthor, createdA: Date.now() }; + await this.#append({ + payload: { annotation: created, path: normalizePath(filePath) }, + type: `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-added`, + }); + return created; + } + + async update(filePath: string, id: string, updates: Partial): Promise { + if (id.trim() === "") throw new Error("annotation id is required"); + const { author: _author, id: _id, ...accepted } = updates; + await this.#append({ + payload: { id, path: normalizePath(filePath), updates: accepted }, + type: `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-updated`, + }); + } + + async remove(filePath: string, id: string): Promise { + if (id.trim() === "") throw new Error("annotation id is required"); + await this.#append({ + payload: { id, path: normalizePath(filePath) }, + type: `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-removed`, + }); + } +} + +/** Fold the workspace's durable annotation journal for one document. */ +export function workspaceAnnotationSnapshot( + events: WorkspaceStreamEvent[], + filePath: string, +): WorkspaceAnnotationSnapshot { + const annotations = new Map(); + const targetPath = normalizePath(filePath); + let version = 0; + + for (const event of [...events].sort((left, right) => left.offset - right.offset)) { + version = Math.max(version, event.offset); + if (!event.type.startsWith(WORKSPACE_ANNOTATION_EVENT_PREFIX)) continue; + const payload = record(event.payload); + if (normalizePath(string(payload.path)) !== targetPath) continue; + + if (event.type === `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-added`) { + const annotation = annotationValue(payload.annotation); + if (annotation !== null) annotations.set(annotation.id, annotation); + continue; + } + const id = string(payload.id); + if (id === "") continue; + if (event.type === `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-removed`) { + annotations.delete(id); + continue; + } + if (event.type === `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-updated`) { + const current = annotations.get(id); + if (current !== undefined) { + annotations.set(id, { ...current, ...record(payload.updates), id }); + } + } + } + + return { + annotations: [...annotations.values()].sort( + (left, right) => left.createdA - right.createdA || left.id.localeCompare(right.id), + ), + version, + }; +} + +export function isWorkspaceAnnotationEventForPath( + event: WorkspaceStreamEvent, + filePath: string, +): boolean { + if (!event.type.startsWith(WORKSPACE_ANNOTATION_EVENT_PREFIX)) return false; + return normalizePath(string(record(event.payload).path)) === normalizePath(filePath); +} + +function annotationValue(value: unknown): Annotation | null { + const candidate = record(value); + return string(candidate.id) === "" ? null : (candidate as unknown as Annotation); +} + +function normalizePath(path: string): string { + return path.replace(/^\/+/, ""); +} + +function record(value: unknown): Record { + return typeof value === "object" && value !== null ? (value as Record) : {}; +} + +function string(value: unknown): string { + return typeof value === "string" ? value : ""; +} diff --git a/src/routes/w.$checkoutId.tsx b/src/routes/w.$checkoutId.tsx index 69b238b..3220f50 100644 --- a/src/routes/w.$checkoutId.tsx +++ b/src/routes/w.$checkoutId.tsx @@ -43,6 +43,7 @@ import { */ export const Route = createFileRoute("/w/$checkoutId")({ validateSearch: (search: Record) => ({ + annotation: typeof search.annotation === "string" ? search.annotation : "", group: search.group === "none" || search.group === "label" ? (search.group as "none" | "label") @@ -50,6 +51,7 @@ export const Route = createFileRoute("/w/$checkoutId")({ q: typeof search.q === "string" ? search.q : "", repo: typeof search.repo === "string" ? search.repo : DEFAULT_REPO_PATH, task: typeof search.task === "string" ? search.task : "", + view: search.view === "review" ? ("review" as const) : ("edit" as const), }), component: WorkspaceBoardPage, }); @@ -209,7 +211,7 @@ function WorkspaceBoardPage() { renamingRef.current = true; void board .renameTask(task.path, nextPath, transform(sourceOf(task)), transform, () => { - if (wasOpen) patchSearch({ task: nextPath }); + if (wasOpen) patchSearch({ annotation: "", task: nextPath }); }) .finally(() => { renamingRef.current = false; @@ -285,7 +287,7 @@ function WorkspaceBoardPage() { .renameTask(draftPath, target, source, (final) => final, () => { renamedDraftRef.current = true; setDraftPath(target); - patchSearch({ task: target }); + patchSearch({ annotation: "", task: target }); }) .finally(() => { renamingRef.current = false; @@ -312,7 +314,7 @@ function WorkspaceBoardPage() { // must not read as accepted. return await board.renameTask(task.path, nextPath, sourceOf(task), (final) => final, () => { setDraftPath((current) => (current === task.path ? nextPath : current)); - if (wasOpen) patchSearch({ task: nextPath }); + if (wasOpen) patchSearch({ annotation: "", task: nextPath }); }); } finally { renamingRef.current = false; @@ -403,7 +405,7 @@ function WorkspaceBoardPage() { recentByPath={new Map()} onMove={moveTask} onAdd={addTask} - onOpen={(path) => patchSearch({ task: path })} + onOpen={(path) => patchSearch({ annotation: "", task: path })} /> )} openTask === null ? Promise.resolve(null) : renameTask(openTask, nextPath) } + view={search.view} + selectedAnnotationId={search.annotation || null} + onSelectAnnotation={(id) => patchSearch({ annotation: id || "" })} + onViewChange={(view) => { + if (view === "review" && openTask !== null) { + const editor = editorApiRef.current; + if (editor !== null && editor.path === openTask.path) { + board.reflectLiveContent(openTask.path, editor.source()); + } + } + patchSearch({ annotation: "", view }); + }} editorEpoch={editorEpoch} editorApiRef={editorApiRef} focusHeadline={ @@ -453,10 +467,10 @@ function WorkspaceBoardPage() { onDelete={() => { if (openTask !== null) { board.deleteTask(openTask.path); - patchSearch({ task: "" }); + patchSearch({ annotation: "", task: "" }); } }} - onClose={() => patchSearch({ task: "" })} + onClose={() => patchSearch({ annotation: "", task: "" })} /> ); diff --git a/src/rpc-api.annotations.test.ts b/src/rpc-api.annotations.test.ts new file mode 100644 index 0000000..626853f --- /dev/null +++ b/src/rpc-api.annotations.test.ts @@ -0,0 +1,47 @@ +import { expect, it } from "vitest"; +import { AnnotationType } from "@plannotator/ui/types"; +import { + WORKSPACE_ANNOTATION_EVENT_PREFIX, + WorkspaceAnnotationJournal, +} from "./lib/workspace-annotations.ts"; + +it("stamps a new review annotation with the verified Iterate user", async () => { + const recorded: unknown[] = []; + const journal = new WorkspaceAnnotationJournal({ + append: async (...events) => { + recorded.push(...events); + }, + getEvents: async () => [], + verifiedAuthor: "Ada", + }); + + const created = await journal.add( + "/tasks/launch.md", + annotation({ author: "Mallory" }), + ); + + expect(created).toMatchObject({ author: "Ada", id: "ann-1" }); + expect(recorded).toMatchObject([ + { + payload: { + annotation: { author: "Ada", id: "ann-1" }, + path: "tasks/launch.md", + }, + type: `${WORKSPACE_ANNOTATION_EVENT_PREFIX}annotation-added`, + }, + ]); +}); + +function annotation(input: { author: string }) { + return { + ...input, + blockId: "block-1", + createdA: 1, + endOffset: 4, + id: "ann-1", + originalText: "ship", + startOffset: 0, + text: "Please make this measurable.", + type: AnnotationType.COMMENT, + }; +} diff --git a/src/rpc-api.ts b/src/rpc-api.ts index 5aa9237..a8867cc 100644 --- a/src/rpc-api.ts +++ b/src/rpc-api.ts @@ -1,5 +1,6 @@ import { RpcTarget } from "capnweb"; import { getServerByName } from "partyserver"; +import type { Annotation } from "@plannotator/ui/types"; import type { AppEnv } from "./env.ts"; import { ProjectDial } from "./checkout-do.ts"; import type { CommitResult, TaskChangeSummary } from "./state.ts"; @@ -19,6 +20,12 @@ import type { TasksWorkspace, } from "./lib/tasks-api.ts"; import { DEFAULT_REPO_PATH, isCheckoutId, normalizeRepoPath } from "./lib/checkout-shared.ts"; +import { + WorkspaceAnnotationJournal, + type WorkspaceAnnotationAppend, + type WorkspaceAnnotationSnapshot, +} from "./lib/workspace-annotations.ts"; +import { isTaskFilePath } from "./tasks-model.ts"; const AUTH_COOKIE = "iterate-project-auth"; @@ -119,6 +126,10 @@ export class TasksProjectApi extends RpcTarget implements TasksProject { } async whoami(): Promise { + return this.#verifiedUser(); + } + + #verifiedUser(): TasksUser { if (this.#credential.type !== "project-app-session") { return { userId: null, email: null, name: null, image: null }; } @@ -163,7 +174,7 @@ export class TasksProjectApi extends RpcTarget implements TasksProject { if (!isCheckoutId(checkoutId) || normalized === null) { throw new Error("bad checkout id or repo path"); } - return new TasksWorkspaceApi(this.#dial, checkoutId, normalized); + return new TasksWorkspaceApi(this.#dial, checkoutId, normalized, this.#verifiedUser()); } [Symbol.dispose](): void { @@ -312,13 +323,15 @@ export class TasksWorkspaceApi extends RpcTarget implements TasksWorkspace { readonly #dial: ProjectDial; readonly #checkoutId: string; readonly #repoPath: string; + readonly #user: TasksUser; #created = false; - constructor(dial: ProjectDial, checkoutId: string, repoPath: string) { + constructor(dial: ProjectDial, checkoutId: string, repoPath: string, user: TasksUser) { super(); this.#dial = dial; this.#checkoutId = checkoutId; this.#repoPath = repoPath; + this.#user = user; } get #workspacePath(): string { @@ -442,6 +455,73 @@ export class TasksWorkspaceApi extends RpcTarget implements TasksWorkspace { }); } + async annotations(filePath: string): Promise { + const path = this.#taskPath(filePath); + await this.#withWorkspace((ws) => ws.exists("/")); + return this.#annotationJournal().snapshot(path); + } + + async addAnnotation(filePath: string, annotation: Annotation): Promise { + const path = this.#taskPath(filePath); + await this.#withWorkspace((ws) => ws.exists("/")); + return this.#annotationJournal().add(path, annotation); + } + + async updateAnnotation( + filePath: string, + id: string, + updates: Partial, + ): Promise { + const path = this.#taskPath(filePath); + await this.#withWorkspace((ws) => ws.exists("/")); + return this.#annotationJournal().update(path, id, updates); + } + + async removeAnnotation(filePath: string, id: string): Promise { + const path = this.#taskPath(filePath); + await this.#withWorkspace((ws) => ws.exists("/")); + return this.#annotationJournal().remove(path, id); + } + + #annotationJournal(): WorkspaceAnnotationJournal { + const verifiedAuthor = this.#user.name || this.#user.email || this.#user.userId || "agent"; + return new WorkspaceAnnotationJournal({ + append: async (...events: WorkspaceAnnotationAppend[]) => { + await this.#dial.withProject(async (project) => { + const stream = ( + project as unknown as { + streams: { + get(path: string): { append(...items: WorkspaceAnnotationAppend[]): Promise }; + }; + } + ).streams.get(this.#workspacePath); + await stream.append(...events); + }); + }, + getEvents: () => this.#workspaceEvents(), + verifiedAuthor, + }); + } + + async #workspaceEvents(): Promise { + return this.#dial.withProject(async (project) => { + const stream = ( + project as unknown as { + streams: { + get(path: string): { getEvents(args: object): Promise }; + }; + } + ).streams.get(this.#workspacePath); + return stream.getEvents({ includeEphemeral: false }); + }); + } + + #taskPath(filePath: string): string { + const path = filePath.replace(/^\/+/, ""); + if (!isTaskFilePath(path)) throw new Error("annotations require a task markdown path"); + return path; + } + /** Every task file in the merged view, path → content (board seed). * PoC shape: fine for boards of hundreds; the real fix for gigantic repos * is a platform-side filtered snapshot (the workspace equivalent of the diff --git a/tasks/complete/2026-07-22-add-plannotator-review.md b/tasks/complete/2026-07-22-add-plannotator-review.md new file mode 100644 index 0000000..74df69f --- /dev/null +++ b/tasks/complete/2026-07-22-add-plannotator-review.md @@ -0,0 +1,65 @@ +--- +status: complete +size: large +base: collab-poc +--- + +# Add multiplayer Plannotator review to workspace tasks + +## Status + +Complete. Workspace task sheets now have an Iterate-backed Plannotator review mode with durable, +live annotations, verified authors, and browser proof across two isolated reviewers. The existing +collaborative editor remains intact; upstream package size/source-mode cost is noted below. + +## Outcome + +The workspace-backed task sheet offers an Edit/Review switch. Review renders the task with +Plannotator's published document UI and lets project members attach comments or deletion +suggestions to selected text. Review annotations are durable, live multiplayer state backed by +the checkout's Iterate workspace stream. The existing collaborative editor remains the source +of task markdown. + +## Decisions + +- Build on `collab-poc`; the checkout is already an Iterate workspace and agents keep using the + standard workspace API. +- Consume `@plannotator/ui` and `@plannotator/core`; do not copy or reimplement their document UI. +- Store annotation mutations as namespaced durable events on the workspace stream. Fold those + events for snapshots and replay from the snapshot offset for race-free live subscription. +- Scope every annotation to a workspace-relative task path. Renaming a task does not silently + move its review history in this slice; the old path's history remains auditable. +- Stamp annotation authors in the vessel from the already-verified Iterate session, ignoring a + client-supplied author. +- Keep task markdown editing in the existing collaborative CodeMirror lane. Review mode reads its + live reflected content and annotations verify restored text after document drift. +- Load Plannotator only in the browser: its package-level configuration is not SSR-safe. +- Images and AI are out of scope; their UI affordances stay disabled. + +## Checklist + +- [x] Add the Plannotator packages, styles, and a client-only review surface. *Pinned the published packages and lazy-loaded the review-only bundle.* +- [x] Add a public workspace annotation API backed by durable stream events. *`TasksWorkspace` now appends and folds namespaced Plannotator events on the workspace stream.* +- [x] Prove a snapshot folds add/update/remove events for one task without leaking another task's annotations. *Covered by `workspace-annotations.test.ts`.* +- [x] Prove the browser transport cannot spoof the verified annotation author. *The journal spec submits Mallory and observes server-stamped Ada.* +- [x] Add Review/Edit switching to the workspace task sheet without replacing the live editor. *The selected view and annotation live in route search state.* +- [x] Show live annotations in Plannotator's Viewer and AnnotationPanel, including edit/delete. *Viewer selection, global comments, panel edits, deletes, and agent-feedback copy are wired.* +- [x] Verify typecheck, tests, production build, and a two-browser local multiplayer flow. *All static checks pass; the built Worker proved live create/edit/delete, refresh durability, and exact-text comments on localhost.* + +## Implementation log + +- 2026-07-22: Chose the existing workspace stream as the annotation journal. This avoids a second + storage system and makes review activity visible in the checkout's existing event audit sheet. +- 2026-07-22: Added a browser WebSocket OPEN barrier after localhost exposed the collab PoC's + startup race. Application errors no longer dispose the shared Cap'n Web session for every caller. +- 2026-07-22: Patched `@plannotator/ui@0.28.0` locally for TypeScript 5.9 response typing and its + `highlight.js` ESM/CJS boundary; the patch is explicit in `patches/` and can be dropped after an + upstream release contains equivalent fixes. +- 2026-07-22: Verified the built Worker at localhost with two isolated headed browsers. One browser + saw the other's new and edited annotations without reload; refresh restored durable state; a + selected-text comment retained the exact quote `Select this sentence` and the verified author. +- 2026-07-22: Pointed the fully-local harness at `/w/local-review` and documented the command so + reviewers land on the workspace-backed lane that contains Review mode. +- 2026-07-22: Plannotator's rich Viewer remains a lazy ~1 MB gzip chunk and its published source + makes Vite's first source-mode review compile expensive. Edit/board startup is unaffected; a + slimmer upstream document-only entrypoint would be the clean follow-up.