From 7a2f2cb99c50038e932f898838ab60715c4e47d6 Mon Sep 17 00:00:00 2001 From: nexxeln <95541290+nexxeln@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:54:40 +0000 Subject: [PATCH 1/5] use latest graph and remove old graph (#604) --- .../components/content-cards/google-docs.tsx | 2 +- apps/web/components/content-cards/note.tsx | 2 +- apps/web/components/content-cards/tweet.tsx | 2 +- apps/web/components/content-cards/website.tsx | 2 +- apps/web/components/graph-dialog.tsx | 2 +- apps/web/components/masonry-memory-list.tsx | 2 +- apps/web/components/memories-utils/index.tsx | 2 +- apps/web/components/memory-list-view.tsx | 2 +- apps/web/lib/document-icon.tsx | 2 +- apps/web/package.json | 1 + bun.lock | 639 +------------- .../{memory-graph/constants.ts => colors.ts} | 52 +- packages/ui/memory-graph/controls.tsx | 67 -- packages/ui/memory-graph/graph-canvas.tsx | 762 ----------------- .../ui/memory-graph/graph-webgl-canvas.tsx | 794 ------------------ .../ui/memory-graph/hooks/use-graph-data.ts | 304 ------- .../hooks/use-graph-interactions.ts | 564 ------------- packages/ui/memory-graph/index.ts | 19 - packages/ui/memory-graph/legend.tsx | 311 ------- .../ui/memory-graph/loading-indicator.tsx | 44 - packages/ui/memory-graph/memory-graph.tsx | 458 ---------- .../ui/memory-graph/navigation-controls.tsx | 67 -- .../ui/memory-graph/node-detail-panel.tsx | 268 ------ packages/ui/memory-graph/spaces-dropdown.tsx | 120 --- packages/ui/memory-graph/types.ts | 122 --- 25 files changed, 46 insertions(+), 4564 deletions(-) rename packages/ui/{memory-graph/constants.ts => colors.ts} (55%) delete mode 100644 packages/ui/memory-graph/controls.tsx delete mode 100644 packages/ui/memory-graph/graph-canvas.tsx delete mode 100644 packages/ui/memory-graph/graph-webgl-canvas.tsx delete mode 100644 packages/ui/memory-graph/hooks/use-graph-data.ts delete mode 100644 packages/ui/memory-graph/hooks/use-graph-interactions.ts delete mode 100644 packages/ui/memory-graph/index.ts delete mode 100644 packages/ui/memory-graph/legend.tsx delete mode 100644 packages/ui/memory-graph/loading-indicator.tsx delete mode 100644 packages/ui/memory-graph/memory-graph.tsx delete mode 100644 packages/ui/memory-graph/navigation-controls.tsx delete mode 100644 packages/ui/memory-graph/node-detail-panel.tsx delete mode 100644 packages/ui/memory-graph/spaces-dropdown.tsx delete mode 100644 packages/ui/memory-graph/types.ts diff --git a/apps/web/components/content-cards/google-docs.tsx b/apps/web/components/content-cards/google-docs.tsx index 6b44a0642..aa7da8cda 100644 --- a/apps/web/components/content-cards/google-docs.tsx +++ b/apps/web/components/content-cards/google-docs.tsx @@ -16,7 +16,7 @@ import { } from "@repo/ui/components/alert-dialog" import { ExternalLink, FileText, Brain, Trash2 } from "lucide-react" import { cn } from "@lib/utils" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import { getPastelBackgroundColor } from "../memories-utils" interface GoogleDocsCardProps { diff --git a/apps/web/components/content-cards/note.tsx b/apps/web/components/content-cards/note.tsx index 5fd6f740c..ea0e362cb 100644 --- a/apps/web/components/content-cards/note.tsx +++ b/apps/web/components/content-cards/note.tsx @@ -12,7 +12,7 @@ import { AlertDialogTrigger, } from "@repo/ui/components/alert-dialog" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import { Brain, ExternalLink, Trash2 } from "lucide-react" import { cn } from "@lib/utils" import { useState } from "react" diff --git a/apps/web/components/content-cards/tweet.tsx b/apps/web/components/content-cards/tweet.tsx index b25997708..adab61348 100644 --- a/apps/web/components/content-cards/tweet.tsx +++ b/apps/web/components/content-cards/tweet.tsx @@ -26,7 +26,7 @@ import { AlertDialogTrigger, } from "@repo/ui/components/alert-dialog" import { Brain, Trash2 } from "lucide-react" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import { getPastelBackgroundColor } from "../memories-utils" type MyTweetProps = { diff --git a/apps/web/components/content-cards/website.tsx b/apps/web/components/content-cards/website.tsx index fed79f4ad..b14b7a9f2 100644 --- a/apps/web/components/content-cards/website.tsx +++ b/apps/web/components/content-cards/website.tsx @@ -16,7 +16,7 @@ import { ExternalLink, Trash2 } from "lucide-react" import { useState } from "react" import { cn } from "@lib/utils" import { getPastelBackgroundColor } from "../memories-utils" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" interface WebsiteCardProps { title: string diff --git a/apps/web/components/graph-dialog.tsx b/apps/web/components/graph-dialog.tsx index 8849d4ce0..efc1c05b1 100644 --- a/apps/web/components/graph-dialog.tsx +++ b/apps/web/components/graph-dialog.tsx @@ -6,7 +6,7 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import { useInfiniteQuery } from "@tanstack/react-query" import { useCallback, useEffect, useMemo, useState } from "react" import type { z } from "zod" -import { MemoryGraph } from "@repo/ui/memory-graph" +import { MemoryGraph } from "@supermemory/memory-graph" import { Dialog, DialogContent } from "@repo/ui/components/dialog" import { ConnectAIModal } from "@/components/connect-ai-modal" import { AddMemoryView } from "@/components/views/add-memory" diff --git a/apps/web/components/masonry-memory-list.tsx b/apps/web/components/masonry-memory-list.tsx index 1a29093fa..1ffd2130a 100644 --- a/apps/web/components/masonry-memory-list.tsx +++ b/apps/web/components/masonry-memory-list.tsx @@ -2,7 +2,7 @@ import { useIsMobile } from "@hooks/use-mobile" import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import { Sparkles } from "lucide-react" import { Masonry, useInfiniteLoader } from "masonic" import { memo, useCallback, useMemo, useState } from "react" diff --git a/apps/web/components/memories-utils/index.tsx b/apps/web/components/memories-utils/index.tsx index fca4d3678..01f457815 100644 --- a/apps/web/components/memories-utils/index.tsx +++ b/apps/web/components/memories-utils/index.tsx @@ -1,4 +1,4 @@ -import type { DocumentWithMemories } from "@ui/memory-graph/types" +import type { DocumentWithMemories } from "@supermemory/memory-graph" export const formatDate = (date: string | Date) => { const dateObj = new Date(date) diff --git a/apps/web/components/memory-list-view.tsx b/apps/web/components/memory-list-view.tsx index 6fc80afa1..f8869fd38 100644 --- a/apps/web/components/memory-list-view.tsx +++ b/apps/web/components/memory-list-view.tsx @@ -15,7 +15,7 @@ import { AlertDialogTitle, AlertDialogTrigger, } from "@repo/ui/components/alert-dialog" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import { useVirtualizer } from "@tanstack/react-virtual" import { Brain, ExternalLink, Sparkles, Trash2 } from "lucide-react" diff --git a/apps/web/lib/document-icon.tsx b/apps/web/lib/document-icon.tsx index edeaf76b1..2fe2ff9a9 100644 --- a/apps/web/lib/document-icon.tsx +++ b/apps/web/lib/document-icon.tsx @@ -1,5 +1,5 @@ import { MCPIcon } from "@/components/menu" -import { colors } from "@repo/ui/memory-graph/constants" +import { colors } from "@repo/ui/colors" import { GoogleDocs, MicrosoftWord, diff --git a/apps/web/package.json b/apps/web/package.json index 96b461a88..c141118a7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,7 @@ "@ai-sdk/google": "^2.0.0-beta.13", "@ai-sdk/react": "2.0.0-beta.24", "@better-fetch/fetch": "^1.1.18", + "@supermemory/memory-graph": "workspace:*", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", diff --git a/bun.lock b/bun.lock index 80a3ab523..e2f3047a6 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "supermemory", @@ -100,21 +101,6 @@ "typescript": "^5", }, }, - "apps/raycast-extension": { - "name": "supermemory", - "dependencies": { - "@raycast/api": "^1.103.2", - "@raycast/utils": "^1.17.0", - }, - "devDependencies": { - "@raycast/eslint-config": "^2.0.4", - "@types/node": "22.13.10", - "@types/react": "19.0.10", - "eslint": "^9.22.0", - "prettier": "^3.5.3", - "typescript": "^5.8.2", - }, - }, "apps/web": { "name": "@repo/web", "version": "0.1.0", @@ -146,6 +132,7 @@ "@react-router/node": "^7.6.2", "@react-router/serve": "^7.6.2", "@sentry/nextjs": "^10.22.0", + "@supermemory/memory-graph": "workspace:*", "@tailwindcss/typography": "^0.5.16", "@tanstack/react-form": "^1.12.4", "@tanstack/react-query": "^5.81.2", @@ -261,7 +248,7 @@ }, "packages/tools": { "name": "@supermemory/tools", - "version": "1.3.11", + "version": "1.3.12", "dependencies": { "@ai-sdk/anthropic": "^2.0.25", "@ai-sdk/openai": "^2.0.23", @@ -724,24 +711,6 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - - "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], - - "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], - - "@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="], - - "@eslint/js": ["@eslint/js@9.39.1", "", {}, "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw=="], - - "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], - - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], - "@essentials/memoize-one": ["@essentials/memoize-one@1.1.0", "", {}, "sha512-HMkuIkKNe0EWSUpZhlaq9+5Yp47YhrMhxLMnXTRnEyE5N4xKLspAvMGjUFdi794VnEF1EcOZFS8rdROeujrgag=="], "@essentials/one-key-map": ["@essentials/one-key-map@1.2.0", "", {}, "sha512-C2H7zHVcsoipDv4VKY5uUcv5ilsK+uEgEj+WeOdN5oz/Qj1/OZIzCdle90gDzj0xnGQrmZ9qDujwD7AkBb5k9A=="], @@ -768,14 +737,6 @@ "@hono/zod-validator": ["@hono/zod-validator@0.7.3", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-uYGdgVib3RlGD698WR5dVM0zB3UuPY5vHKXffGUbUh7r4xY+mFIhF3/v4AcQVLrU5CQdBso8BJr4wuVoCrjTuQ=="], - "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], - - "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], @@ -998,14 +959,6 @@ "@npmcli/promise-spawn": ["@npmcli/promise-spawn@6.0.2", "", { "dependencies": { "which": "^3.0.0" } }, "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg=="], - "@oclif/core": ["@oclif/core@4.8.0", "", { "dependencies": { "ansi-escapes": "^4.3.2", "ansis": "^3.17.0", "clean-stack": "^3.0.1", "cli-spinners": "^2.9.2", "debug": "^4.4.3", "ejs": "^3.1.10", "get-package-type": "^0.1.0", "indent-string": "^4.0.0", "is-wsl": "^2.2.0", "lilconfig": "^3.1.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "string-width": "^4.2.3", "supports-color": "^8", "tinyglobby": "^0.2.14", "widest-line": "^3.1.0", "wordwrap": "^1.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-jteNUQKgJHLHFbbz806aGZqf+RJJ7t4gwF4MYa8fCwCxQ8/klJNWc0MvaJiBebk7Mc+J39mdlsB4XraaCKznFw=="], - - "@oclif/plugin-autocomplete": ["@oclif/plugin-autocomplete@3.2.39", "", { "dependencies": { "@oclif/core": "^4", "ansis": "^3.16.0", "debug": "^4.4.1", "ejs": "^3.1.10" } }, "sha512-OwAZNnSpuDjKyhAwoOJkFWxGswPFKBB4hpNIMsj6PUtbKwGBPmD+2wGGPgTsDioVwLmUELSb2bZ+1dxHfvXmvg=="], - - "@oclif/plugin-help": ["@oclif/plugin-help@6.2.36", "", { "dependencies": { "@oclif/core": "^4" } }, "sha512-NBQIg5hEMhvdbi4mSrdqRGl5XJ0bqTAHq6vDCCCDXUcfVtdk3ZJbSxtRVWyVvo9E28vwqu6MZyHOJylevqcHbA=="], - - "@oclif/plugin-not-found": ["@oclif/plugin-not-found@3.2.73", "", { "dependencies": { "@inquirer/prompts": "^7.10.1", "@oclif/core": "^4.8.0", "ansis": "^3.17.0", "fast-levenshtein": "^3.0.0" } }, "sha512-2bQieTGI9XNFe9hKmXQjJmHV5rZw+yn7Rud1+C5uLEo8GaT89KZbiLTJgL35tGILahy/cB6+WAs812wjw7TK6w=="], - "@octokit/auth-token": ["@octokit/auth-token@5.1.2", "", {}, "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw=="], "@octokit/core": ["@octokit/core@6.1.6", "", { "dependencies": { "@octokit/auth-token": "^5.0.0", "@octokit/graphql": "^8.2.2", "@octokit/request": "^9.2.3", "@octokit/request-error": "^6.1.8", "@octokit/types": "^14.0.0", "before-after-hook": "^3.0.2", "universal-user-agent": "^7.0.0" } }, "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA=="], @@ -1246,14 +1199,6 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - "@raycast/api": ["@raycast/api@1.103.10", "", { "dependencies": { "@oclif/core": "^4.5.4", "@oclif/plugin-autocomplete": "^3.2.35", "@oclif/plugin-help": "^6.2.33", "@oclif/plugin-not-found": "^3.2.68", "@types/node": "22.13.10", "@types/react": "19.0.10", "esbuild": "^0.25.10", "react": "19.0.0" }, "peerDependencies": { "react-devtools": "6.1.1" }, "optionalPeers": ["react-devtools"], "bin": { "ray": "bin/run.js" } }, "sha512-FOxqq47+YVCo4+Eq8eU8+esoLNwcxHHBVhw/JmZwsViTqMB3DF8WorXL+ZwrXW/8srruuzyyx9+ACyRdZ+zbSg=="], - - "@raycast/eslint-config": ["@raycast/eslint-config@2.1.1", "", { "dependencies": { "@eslint/js": "^9.36.0", "@raycast/eslint-plugin": "^2.1.1", "eslint-config-prettier": "^10.1.8", "globals": "^16.4.0", "typescript-eslint": "^8.45.0" }, "peerDependencies": { "eslint": ">=8.23.0", "prettier": ">=2", "typescript": ">=4" } }, "sha512-W0kxF+FJ+BYQn0EKIV739j2ZrHEtjo/LclsoZgUWg3t364Dq75XKcjqYFYx+59/DBaamY0amdajlfuDAf6veAg=="], - - "@raycast/eslint-plugin": ["@raycast/eslint-plugin@2.1.1", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.1" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-r2gs8uIlNp6I2mLOyN/kReGlvigzEeuyQPl4yw7nwLy8Zxjfjhg8txMViaBux8juBWBxbSWq/IfW6ZA50oeOHQ=="], - - "@raycast/utils": ["@raycast/utils@1.19.1", "", { "dependencies": { "cross-fetch": "^3.1.6", "dequal": "^2.0.3", "object-hash": "^3.0.0", "signal-exit": "^4.0.2", "stream-chain": "^2.2.5", "stream-json": "^1.8.0" }, "peerDependencies": { "@raycast/api": ">=1.69.0" } }, "sha512-/udUGcTZCgZZwzesmjBkqG5naQZTD/ZLHbqRwkWcF+W97vf9tr9raxKyQjKsdZ17OVllw2T3sHBQsVUdEmCm2g=="], - "@react-email/render": ["@react-email/render@1.1.2", "", { "dependencies": { "html-to-text": "^9.0.5", "prettier": "^3.5.3", "react-promise-suspense": "^0.3.4" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-RnRehYN3v9gVlNMehHPHhyp2RQo7+pSkHDtXPvg3s0GbzM9SQMW4Qrf8GRNvtpLC4gsI+Wt0VatNRUFqjvevbw=="], "@react-hook/debounce": ["@react-hook/debounce@3.0.0", "", { "dependencies": { "@react-hook/latest": "^1.0.2" }, "peerDependencies": { "react": ">=16.8" } }, "sha512-ir/kPrSfAzY12Gre0sOHkZ2rkEmM4fS5M5zFxCi4BnCeXh2nvx9Ujd+U4IGpKCuPA+EQD0pg1eK2NGLvfWejag=="], @@ -1868,26 +1813,6 @@ "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.48.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/type-utils": "8.48.1", "@typescript-eslint/utils": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.48.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.48.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA=="], - - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.48.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.48.1", "@typescript-eslint/types": "^8.48.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1" } }, "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w=="], - - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.48.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/utils": "8.48.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@8.48.1", "", {}, "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.48.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.48.1", "@typescript-eslint/tsconfig-utils": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4", "minimatch": "^9.0.4", "semver": "^7.6.0", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.48.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q=="], - "@typescript/vfs": ["@typescript/vfs@1.6.1", "", { "dependencies": { "debug": "^4.1.1" }, "peerDependencies": { "typescript": "*" } }, "sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], @@ -2002,7 +1927,7 @@ "ai-gateway-provider": ["ai-gateway-provider@0.0.11", "", { "dependencies": { "@ai-sdk/provider": "^1.1.3", "@ai-sdk/provider-utils": "^2.2.8", "ai": "^4.3.16" } }, "sha512-OrovxjYP+yowh4/OEsd/cYkvNx7s0mhBRXBO9RLyN8i803jlxyLlWZ1OAbiGL5FET3cnI8pYb8TrFMmZQT9yZQ=="], - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], @@ -2018,7 +1943,7 @@ "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], - "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + "ansi-escapes": ["ansi-escapes@7.1.1", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q=="], "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], @@ -2232,7 +2157,7 @@ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], - "clean-stack": ["clean-stack@3.0.1", "", { "dependencies": { "escape-string-regexp": "4.0.0" } }, "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg=="], + "clean-stack": ["clean-stack@4.2.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg=="], "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], @@ -2324,8 +2249,6 @@ "cosmiconfig": ["cosmiconfig@9.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="], - "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], @@ -2440,8 +2363,6 @@ "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - "deep-object-diff": ["deep-object-diff@1.1.9", "", {}, "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], @@ -2546,8 +2467,6 @@ "efrt": ["efrt@2.7.0", "", {}, "sha512-/RInbCy1d4P6Zdfa+TMVsf/ufZVotat5hCw3QXmWtjU+3pFEOvOQ7ibo3aIxyCJw2leIeAMjmPj+1SLJiCpdrQ=="], - "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.228", "", {}, "sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA=="], "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="], @@ -2620,27 +2539,17 @@ "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="], - "eslint": ["eslint@9.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g=="], - - "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], - - "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - - "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + "eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], - "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="], @@ -2690,7 +2599,7 @@ "fast-content-type-parse": ["fast-content-type-parse@2.0.1", "", {}, "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q=="], - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], "fast-equals": ["fast-equals@5.3.2", "", {}, "sha512-6rxyATwPCkaFIL3JLqw8qXqMpIZ942pTX/tbQFkRsDGblS8tNGtlUauA/+mt6RUfqn/4MoEr+WDkYoIQbibWuQ=="], @@ -2700,10 +2609,6 @@ "fast-json-patch": ["fast-json-patch@3.1.1", "", {}, "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ=="], - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - "fast-memoize": ["fast-memoize@2.5.2", "", {}, "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="], "fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="], @@ -2712,8 +2617,6 @@ "fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], - "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], @@ -2728,14 +2631,10 @@ "fflate": ["fflate@0.4.8", "", {}, "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="], - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - "file-selector": ["file-selector@2.1.2", "", { "dependencies": { "tslib": "^2.7.0" } }, "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig=="], "file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="], - "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], - "filesize": ["filesize@11.0.13", "", {}, "sha512-mYJ/qXKvREuO0uH8LTQJ6v7GsUvVOguqxg2VTwQUkyTPXXRRWPdjuUPVqdBrJQhvci48OHlNGRnux+Slr2Rnvw=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -2746,10 +2645,6 @@ "firefox-profile": ["firefox-profile@4.7.0", "", { "dependencies": { "adm-zip": "~0.5.x", "fs-extra": "^11.2.0", "ini": "^4.1.3", "minimist": "^1.2.8", "xml2js": "^0.6.2" }, "bin": { "firefox-profile": "lib/cli.js" } }, "sha512-aGApEu5bfCNbA4PGUZiRJAIU6jKmghV2UVdklXAofnNtiDjqYw0czLS46W7IfFqVKgKhFB8Ao2YoNGHY4BoIMQ=="], - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], - - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], - "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], @@ -2808,8 +2703,6 @@ "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], - "get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="], - "get-port": ["get-port@5.1.1", "", {}, "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ=="], "get-port-please": ["get-port-please@3.2.0", "", {}, "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A=="], @@ -2832,13 +2725,13 @@ "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], "global-directory": ["global-directory@4.0.1", "", { "dependencies": { "ini": "4.1.1" } }, "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q=="], - "globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="], + "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], @@ -2856,8 +2749,6 @@ "grad-school": ["grad-school@0.0.5", "", {}, "sha512-rXunEHF9M9EkMydTBux7+IryYXEZinRk6g8OBOGDBzo/qWJjhTxy86i5q7lQYpCLHN8Sqv1XX3OIOc7ka2gtvQ=="], - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], - "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], "growly": ["growly@1.3.0", "", {}, "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw=="], @@ -2982,9 +2873,7 @@ "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -3130,8 +3019,6 @@ "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - "jake": ["jake@10.9.4", "", { "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", "picocolors": "^1.1.1" }, "bin": { "jake": "bin/cli.js" } }, "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA=="], - "javascript-stringify": ["javascript-stringify@2.1.0", "", {}, "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg=="], "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], @@ -3162,12 +3049,10 @@ "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "json-schema-walker": ["json-schema-walker@2.0.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.1.0", "clone": "^2.1.2" } }, "sha512-nXN2cMky0Iw7Af28w061hmxaPDaML5/bQD9nwm1lOoIKEGjHcRGxqWe4MfrkYThYAPjSUhmsp4bJNoLAyVn9Xw=="], - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonc-parser": ["jsonc-parser@2.2.1", "", {}, "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="], @@ -3214,8 +3099,6 @@ "leven": ["leven@4.1.0", "", {}, "sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew=="], - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - "libsodium": ["libsodium@0.7.15", "", {}, "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw=="], "libsodium-wrappers": ["libsodium-wrappers@0.7.15", "", { "dependencies": { "libsodium": "^0.7.15" } }, "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ=="], @@ -3506,8 +3389,6 @@ "nanostores": ["nanostores@1.0.1", "", {}, "sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw=="], - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], @@ -3600,8 +3481,6 @@ "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], "os-paths": ["os-paths@7.4.0", "", { "optionalDependencies": { "fsevents": "*" } }, "sha512-Ux1J4NUqC6tZayBqLN1kUlDAEvLiQlli/53sSddU4IN+h+3xxnv2HmRSMpVSvr1hvJzotfMs3ERvETGK+f4OwA=="], @@ -3746,8 +3625,6 @@ "preact": ["preact@10.27.2", "", {}, "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg=="], - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], "printable-characters": ["printable-characters@1.0.42", "", {}, "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="], @@ -3788,8 +3665,6 @@ "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "pupa": ["pupa@3.3.0", "", { "dependencies": { "escape-goat": "^4.0.0" } }, "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA=="], "puppeteer": ["puppeteer@22.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.3.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1312386", "puppeteer-core": "22.15.0" }, "bin": { "puppeteer": "lib/esm/puppeteer/node/cli.js" } }, "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q=="], @@ -4060,7 +3935,7 @@ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "simple-eval": ["simple-eval@1.0.1", "", { "dependencies": { "jsep": "^1.3.6" } }, "sha512-LH7FpTAkeD+y5xQC4fzS+tFtaNlvt3Ib1zKzvhjv/Y+cioV4zIuw4IZr2yhRLu67CWL7FR9/6KXKnjRoZTvGGQ=="], @@ -4136,10 +4011,6 @@ "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], - "stream-chain": ["stream-chain@2.2.5", "", {}, "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="], - - "stream-json": ["stream-json@1.9.1", "", { "dependencies": { "stream-chain": "^2.2.5" } }, "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw=="], - "streamdown": ["streamdown@1.3.0", "", { "dependencies": { "clsx": "^2.1.1", "harden-react-markdown": "^1.0.5", "katex": "^0.16.22", "lucide-react": "^0.542.0", "marked": "^16.2.1", "mermaid": "^11.11.0", "react-markdown": "^10.1.0", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-math": "^6.0.0", "shiki": "^3.12.2", "tailwind-merge": "^3.3.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-vFZdoWKUeagzKwGGOcEqkV1fcgXOJOQqrNBor5/hbaAE/e/ULxZoIHHJJd5KEuaSddCM9KuYtIuZi3WSttXTEA=="], "streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="], @@ -4168,7 +4039,7 @@ "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="], @@ -4192,11 +4063,11 @@ "suffix-thumb": ["suffix-thumb@5.0.2", "", {}, "sha512-I5PWXAFKx3FYnI9a+dQMWNqTxoRt6vdBdb0O+BJ1sxXCWtSoQCusc13E58f+9p4MYx/qCnEMkD5jac6K2j3dgA=="], - "supermemory": ["supermemory@workspace:apps/raycast-extension"], + "supermemory": ["supermemory@3.10.0", "", {}, "sha512-xUTn6ElIIXwizj80ELDFgXjAcBpV9LtNz7kWl+PVQfVzFHM2lOguFHaDx6GoWuWW2GpnE3ikkKPCsKpvHFgqgg=="], "supermemory-browser-extension": ["supermemory-browser-extension@workspace:apps/browser-extension"], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], @@ -4270,8 +4141,6 @@ "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], - "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], @@ -4306,8 +4175,6 @@ "twoslash-protocol": ["twoslash-protocol@0.3.4", "", {}, "sha512-HHd7lzZNLUvjPzG/IE6js502gEzLC1x7HaO1up/f72d8G8ScWAs9Yfa97igelQRDl5h9tGcdFsRp+lNVre1EeQ=="], - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], @@ -4324,8 +4191,6 @@ "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], - "typescript-eslint": ["typescript-eslint@8.48.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.48.1", "@typescript-eslint/parser": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/utils": "8.48.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A=="], - "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], "uhyphen": ["uhyphen@0.2.0", "", {}, "sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA=="], @@ -4390,8 +4255,6 @@ "update-notifier": ["update-notifier@7.3.1", "", { "dependencies": { "boxen": "^8.0.1", "chalk": "^5.3.0", "configstore": "^7.0.0", "is-in-ci": "^1.0.0", "is-installed-globally": "^1.0.0", "is-npm": "^6.0.0", "latest-version": "^9.0.0", "pupa": "^3.1.0", "semver": "^7.6.3", "xdg-basedir": "^5.1.0" } }, "sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA=="], - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "urijs": ["urijs@1.19.11", "", {}, "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="], "urlpattern-polyfill": ["urlpattern-polyfill@10.1.0", "", {}, "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw=="], @@ -4490,10 +4353,6 @@ "winreg": ["winreg@0.0.12", "", {}, "sha512-typ/+JRmi7RqP1NanzFULK36vczznSNN8kWVA9vIqXyv8GhghUlwhGp1Xj3Nms1FsPcNnsQrJOR10N58/nQ9hQ=="], - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - - "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], - "workerd": ["workerd@1.20250617.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250617.0", "@cloudflare/workerd-darwin-arm64": "1.20250617.0", "@cloudflare/workerd-linux-64": "1.20250617.0", "@cloudflare/workerd-linux-arm64": "1.20250617.0", "@cloudflare/workerd-windows-64": "1.20250617.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Uv6p0PYUHp/W/aWfUPLkZVAoAjapisM27JJlwcX9wCPTfCfnuegGOxFMvvlYpmNaX4YCwEdLCwuNn3xkpSkuZw=="], "wrangler": ["wrangler@4.22.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.3.3", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250617.4", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.17", "workerd": "1.20250617.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250617.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-m8qVO3YxhUTII+4U889G/f5UuLSvMkUkCNatupV2f/SJ+iqaWtP1QbuQII8bs2J/O4rqxsz46Wu2S50u7tKB5Q=="], @@ -4594,8 +4453,6 @@ "@alcalzone/ansi-tokenize/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], - "@asyncapi/parser/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "@asyncapi/parser/node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="], "@aws-crypto/ie11-detection/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], @@ -4790,17 +4647,7 @@ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - - "@eslint/eslintrc/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "@eslint/eslintrc/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "@iconify/utils/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], + "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], @@ -4834,8 +4681,6 @@ "@mintlify/link-rot/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="], - "@mintlify/openapi-parser/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "@mintlify/openapi-parser/ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], "@mintlify/prebuild/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="], @@ -4860,60 +4705,28 @@ "@npmcli/promise-spawn/which": ["which@3.0.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg=="], - "@oclif/core/ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], - - "@oclif/core/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - - "@oclif/core/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - - "@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "@oclif/core/widest-line": ["widest-line@3.1.0", "", { "dependencies": { "string-width": "^4.0.0" } }, "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg=="], - - "@oclif/core/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "@oclif/plugin-autocomplete/ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], - - "@oclif/plugin-not-found/@inquirer/prompts": ["@inquirer/prompts@7.10.1", "", { "dependencies": { "@inquirer/checkbox": "^4.3.2", "@inquirer/confirm": "^5.1.21", "@inquirer/editor": "^4.2.23", "@inquirer/expand": "^4.0.23", "@inquirer/input": "^4.3.1", "@inquirer/number": "^3.0.23", "@inquirer/password": "^4.0.23", "@inquirer/rawlist": "^4.1.11", "@inquirer/search": "^3.2.2", "@inquirer/select": "^4.4.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg=="], - - "@oclif/plugin-not-found/ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], - - "@oclif/plugin-not-found/fast-levenshtein": ["fast-levenshtein@3.0.0", "", { "dependencies": { "fastest-levenshtein": "^1.0.7" } }, "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ=="], - "@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], "@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], + "@openapi-contrib/openapi-schema-to-json-schema/fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "@opennextjs/aws/express": ["express@5.0.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.0.1", "content-disposition": "^1.0.0", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "^1.2.1", "debug": "4.3.6", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "^2.0.0", "fresh": "2.0.0", "http-errors": "2.0.0", "merge-descriptors": "^2.0.0", "methods": "~1.1.2", "mime-types": "^3.0.0", "on-finished": "2.4.1", "once": "1.4.0", "parseurl": "~1.3.3", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "router": "^2.0.0", "safe-buffer": "5.2.1", "send": "^1.1.0", "serve-static": "^2.1.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "^2.0.0", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ=="], "@opennextjs/cloudflare/glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="], "@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="], - "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], - "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.57.2", "", { "dependencies": { "@opentelemetry/api-logs": "0.57.2", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg=="], "@puppeteer/browsers/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@raycast/api/@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], - - "@raycast/api/@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="], - - "@raycast/api/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], - - "@raycast/api/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], - "@react-router/dev/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], "@react-router/dev/react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], "@react-router/dev/valibot": ["valibot@0.41.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng=="], - "@repo/docs/supermemory": ["supermemory@3.10.0", "", {}, "sha512-xUTn6ElIIXwizj80ELDFgXjAcBpV9LtNz7kWl+PVQfVzFHM2lOguFHaDx6GoWuWW2GpnE3ikkKPCsKpvHFgqgg=="], - "@repo/docs/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "@repo/web/@ai-sdk/google": ["@ai-sdk/google@2.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.10" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6LyuUrCZuiULg0rUV+kT4T2jG19oUntudorI4ttv1ARkSbwl8A39ue3rA487aDDy6fUScdbGFiV5Yv/o4gidVA=="], @@ -4938,12 +4751,6 @@ "@sentry/bundler-plugin-core/magic-string": ["magic-string@0.30.8", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ=="], - "@sindresorhus/slugify/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - - "@sindresorhus/transliterate/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - - "@stoplight/better-ajv-errors/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "@stoplight/better-ajv-errors/leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], "@stoplight/json/safe-stable-stringify": ["safe-stable-stringify@1.1.1", "", {}, "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw=="], @@ -4954,12 +4761,8 @@ "@stoplight/spectral-core/@stoplight/types": ["@stoplight/types@13.6.0", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ=="], - "@stoplight/spectral-core/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "@stoplight/spectral-core/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "@stoplight/spectral-functions/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "@stoplight/spectral-parsers/@stoplight/types": ["@stoplight/types@14.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g=="], "@stoplight/yaml/@stoplight/types": ["@stoplight/types@14.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g=="], @@ -5014,10 +4817,6 @@ "@types/bun/bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - "@vanilla-extract/integration/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], @@ -5026,23 +4825,15 @@ "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "aggregate-error/clean-stack": ["clean-stack@4.2.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg=="], - - "aggregate-error/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], - "ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-T1gZ76gEIwffep6MWI0QNy9jgoybUHE7TRaHB5k54K8mF91ciGFlbtCGxDYhMH3nCRergKwYFIDeFF0hJSIQHQ=="], "ai-gateway-provider/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], "ai-gateway-provider/ai": ["ai@4.3.19", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/react": "1.2.12", "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["react"] }, "sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q=="], - "ajv-draft-04/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - - "ajv-errors/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "ajv/fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - "ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - - "ajv-keywords/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "ajv-keywords/fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "alchemy/@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.5", "", { "peerDependencies": { "unenv": "2.0.0-rc.21", "workerd": "^1.20250924.0" }, "optionalPeers": ["workerd"] }, "sha512-eB3UAIVhrvY+CMZrRXS/bAv5kWdNiH+dgwu+1M1S7keDeonxkfKIGVIrhcCLTkcqYlN30MPURPuVFUEzIWuuvg=="], @@ -5052,8 +4843,6 @@ "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], - "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "atmn/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], @@ -5074,6 +4863,8 @@ "c12/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], + "chrome-launcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "chrome-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "chromium-bidi/urlpattern-polyfill": ["urlpattern-polyfill@10.0.0", "", {}, "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg=="], @@ -5126,18 +4917,14 @@ "esast-util-from-js/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "eslint/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "escodegen/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - "espree/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], "estree-util-build-jsx/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "estree-util-to-js/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], - "execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "express/cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -5148,16 +4935,14 @@ "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "favicons/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], "fetch-blob/web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], - "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], - "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "fx-runner/commander": ["commander@2.9.0", "", { "dependencies": { "graceful-readlink": ">= 1.0.0" } }, "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A=="], @@ -5188,16 +4973,10 @@ "http-proxy-agent/agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - "ink/ansi-escapes": ["ansi-escapes@7.1.1", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q=="], - "ink/cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="], - "ink/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], - "ink/react-reconciler": ["react-reconciler@0.32.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ=="], - "ink/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "is-online/got": ["got@12.6.1", "", { "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", "http2-wrapper": "^2.1.10", "lowercase-keys": "^3.0.0", "p-cancelable": "^3.0.0", "responselike": "^3.0.0" } }, "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ=="], "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], @@ -5208,12 +4987,6 @@ "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], - "log-update/ansi-escapes": ["ansi-escapes@7.1.1", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q=="], - - "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - - "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "memory-graph-playground/@types/node": ["@types/node@20.19.25", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ=="], "memory-graph-playground/next": ["next@16.0.3", "", { "dependencies": { "@next/env": "16.0.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.3", "@next/swc-darwin-x64": "16.0.3", "@next/swc-linux-arm64-gnu": "16.0.3", "@next/swc-linux-arm64-musl": "16.0.3", "@next/swc-linux-x64-gnu": "16.0.3", "@next/swc-linux-x64-musl": "16.0.3", "@next/swc-win32-arm64-msvc": "16.0.3", "@next/swc-win32-x64-msvc": "16.0.3", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-Ka0/iNBblPFcIubTA1Jjh6gvwqfjrGq1Y2MTI5lbjeLIAfmC+p5bQmojpRZqgHHVu5cG4+qdIiwXiBSm/8lZ3w=="], @@ -5286,8 +5059,6 @@ "rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], - "react-promise-suspense/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], - "react-reconciler/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], "readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], @@ -5296,6 +5067,8 @@ "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + "restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.41", "", {}, "sha512-ycMEPrS3StOIeb87BT3/+bu+blEtyvwQ4zmo2IcJQy0Rd1DAAhKksA0iUZ3MYSpJtjlPhg0Eo6mvVS6ggPhRbw=="], "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], @@ -5304,8 +5077,6 @@ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "schema-utils/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], @@ -5352,12 +5123,6 @@ "sucrase/lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - "supermemory/@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], - - "supermemory/@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="], - - "supermemory/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "supermemory-browser-extension/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "terser/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], @@ -5374,8 +5139,6 @@ "unimport/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "unimport/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "unimport/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "unimport/unplugin": ["unplugin@2.3.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw=="], @@ -5396,12 +5159,8 @@ "web-ext-run/pino": ["pino@9.7.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg=="], - "web-ext-run/strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], - "webpack/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], - "webpack/json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -5438,8 +5197,6 @@ "@aklinker1/rollup-plugin-visualizer/yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - "@asyncapi/parser/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], @@ -5664,10 +5421,6 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - - "@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -5684,6 +5437,8 @@ "@mintlify/common/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + "@mintlify/common/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "@mintlify/common/tailwindcss/jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], "@mintlify/common/tailwindcss/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], @@ -5694,16 +5449,12 @@ "@mintlify/link-rot/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], - "@mintlify/openapi-parser/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@mintlify/prebuild/unist-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "@mintlify/prebuild/unist-util-visit/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], "@mintlify/prebuild/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], - "@mintlify/previewing/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "@mintlify/previewing/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "@mintlify/previewing/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], @@ -5736,36 +5487,6 @@ "@node-minify/core/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], - "@oclif/core/is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], - - "@oclif/core/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/core/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox": ["@inquirer/checkbox@4.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm": ["@inquirer/confirm@5.1.21", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor": ["@inquirer/editor@4.2.23", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/external-editor": "^1.0.3", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand": ["@inquirer/expand@4.0.23", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input": ["@inquirer/input@4.3.1", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number": ["@inquirer/number@3.0.23", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password": ["@inquirer/password@4.0.23", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist": ["@inquirer/rawlist@4.1.11", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search": ["@inquirer/search@3.2.2", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select": ["@inquirer/select@4.4.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w=="], - "@octokit/plugin-paginate-rest/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], "@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], @@ -5812,58 +5533,6 @@ "@puppeteer/browsers/yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - "@raycast/api/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - - "@raycast/api/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "@raycast/api/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "@raycast/api/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "@raycast/api/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "@raycast/api/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "@raycast/api/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "@raycast/api/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "@raycast/api/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "@raycast/api/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "@raycast/api/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "@raycast/api/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "@raycast/api/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "@raycast/api/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "@raycast/api/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "@raycast/api/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "@raycast/api/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "@raycast/api/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "@raycast/api/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "@raycast/api/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "@raycast/api/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "@raycast/api/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "@raycast/api/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "@raycast/api/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - - "@raycast/api/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - - "@raycast/api/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@repo/web/@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-T1gZ76gEIwffep6MWI0QNy9jgoybUHE7TRaHB5k54K8mF91ciGFlbtCGxDYhMH3nCRergKwYFIDeFF0hJSIQHQ=="], "@repo/web/@biomejs/biome/@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4LECm4kc3If0JISai4c3KWQzukoUdpxy4fRzlrPcrdMSRFksR9ZoXK7JBcPuLBmd2SoT4/d7CQS33VnZpgBjew=="], @@ -5900,14 +5569,8 @@ "@sentry/bundler-plugin-core/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], - "@stoplight/better-ajv-errors/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "@stoplight/spectral-core/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@stoplight/spectral-core/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "@stoplight/spectral-functions/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "@supermemory/tools/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.11", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4hgHj89VqyOHzGaV85TkcgvO8WjecVF35TOUVg+C56vnzpWSgdIZu/ZWZNdZ6BTrv8y0N1toBWW7XcWiRRicLg=="], "@tailwindcss/vite/@tailwindcss/node/lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], @@ -5990,18 +5653,8 @@ "@wxt-dev/module-react/@vitejs/plugin-react/react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], - "aggregate-error/clean-stack/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "ai-gateway-provider/ai/@ai-sdk/react": ["@ai-sdk/react@1.2.12", "", { "dependencies": { "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/ui-utils": "1.2.11", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["zod"] }, "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g=="], - "ajv-draft-04/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "ajv-errors/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "alchemy/@cloudflare/unenv-preset/unenv": ["unenv@2.0.0-rc.21", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.7", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" } }, "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A=="], "alchemy/@cloudflare/unenv-preset/workerd": ["workerd@1.20250927.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250927.0", "@cloudflare/workerd-darwin-arm64": "1.20250927.0", "@cloudflare/workerd-linux-64": "1.20250927.0", "@cloudflare/workerd-linux-arm64": "1.20250927.0", "@cloudflare/workerd-windows-64": "1.20250927.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-6kyAGPGYNvn5mbpCJJ48VebN7QGSrvU/WJXgd4EQz20PyqjJAxHcEGGAJ+0Da0u/ewrN1+6fuMKQ1ALLBPiTWg=="], @@ -6034,6 +5687,8 @@ "cli-highlight/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], "cli-highlight/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -6060,10 +5715,6 @@ "enquirer/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "eslint/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "eslint/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "favicons/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], @@ -6208,8 +5859,6 @@ "publish-browser-extension/ora/stdin-discarder": ["stdin-discarder@0.1.0", "", { "dependencies": { "bl": "^5.0.0" } }, "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ=="], - "schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "socket.io-adapter/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], @@ -6220,16 +5869,12 @@ "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "supermemory/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "terser-webpack-plugin/terser/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "terser-webpack-plugin/terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "unimport/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], - "unplugin/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "unplugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], @@ -6282,8 +5927,6 @@ "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -6382,64 +6025,6 @@ "@mintlify/scraping/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "@oclif/core/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/external-editor": ["@inquirer/external-editor@1.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], - "@opennextjs/aws/express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "@opennextjs/aws/express/body-parser/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], @@ -6638,58 +6223,6 @@ "@mintlify/scraping/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/external-editor/chardet": ["chardet@2.1.1", "", {}, "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/external-editor/iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - "@opennextjs/aws/express/body-parser/raw-body/iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], "@puppeteer/browsers/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -6741,107 +6274,5 @@ "cli-highlight/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "cli-highlight/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "publish-browser-extension/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/checkbox/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/confirm/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/editor/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/expand/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/input/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/number/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/password/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/rawlist/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/search/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@oclif/plugin-not-found/@inquirer/prompts/@inquirer/select/@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], } } diff --git a/packages/ui/memory-graph/constants.ts b/packages/ui/colors.ts similarity index 55% rename from packages/ui/memory-graph/constants.ts rename to packages/ui/colors.ts index 23193601b..369a64975 100644 --- a/packages/ui/memory-graph/constants.ts +++ b/packages/ui/colors.ts @@ -47,54 +47,4 @@ export const colors = { extends: "rgba(16, 185, 129, 0.5)", // green derives: "rgba(147, 197, 253, 0.5)", // blue }, -}; - -export const LAYOUT_CONSTANTS = { - centerX: 400, - centerY: 300, - clusterRadius: 300, // Memory "bubble" size around a doc - smaller bubble - spaceSpacing: 1600, // How far apart the *spaces* (groups of docs) sit - push spaces way out - documentSpacing: 1000, // How far the first doc in a space sits from its space-centre - push docs way out - minDocDist: 900, // Minimum distance two documents in the **same space** are allowed to be - sets repulsion radius - memoryClusterRadius: 300, -}; - -// Graph view settings -export const GRAPH_SETTINGS = { - console: { - initialZoom: 0.8, // Higher zoom for console - better overview - initialPanX: 0, - initialPanY: 0, - }, - consumer: { - initialZoom: 0.5, // Changed from 0.1 to 0.5 for better initial visibility - initialPanX: 400, // Pan towards center to compensate for larger layout - initialPanY: 300, // Pan towards center to compensate for larger layout - }, -}; - -// Responsive positioning for different app variants -export const POSITIONING = { - console: { - legend: { - desktop: "bottom-4 right-4", - mobile: "bottom-4 right-4", - }, - loadingIndicator: "top-20 right-4", - - spacesSelector: "top-4 left-4", - viewToggle: "", // Not used in console - nodeDetail: "top-4 right-4", - }, - consumer: { - legend: { - desktop: "top-18 right-4", - mobile: "bottom-[180px] left-4", - }, - loadingIndicator: "top-20 right-4", - - spacesSelector: "", // Hidden in consumer - viewToggle: "top-4 right-4", // Consumer has view toggle - nodeDetail: "top-4 right-4", - }, -}; +} diff --git a/packages/ui/memory-graph/controls.tsx b/packages/ui/memory-graph/controls.tsx deleted file mode 100644 index 899d239a9..000000000 --- a/packages/ui/memory-graph/controls.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { cn } from "@repo/lib/utils"; -import { Button } from "@repo/ui/components/button"; -import { GlassMenuEffect } from "@repo/ui/other/glass-effect"; -import { Move, ZoomIn, ZoomOut } from "lucide-react"; -import { memo } from "react"; -import type { ControlsProps } from "./types"; - -export const Controls = memo( - ({ onZoomIn, onZoomOut, onResetView, variant = "console" }) => { - // Use explicit classes - controls positioning not defined in constants - // Using a reasonable default position - const getPositioningClasses = () => { - if (variant === "console") { - return "bottom-4 left-4"; - } - if (variant === "consumer") { - return "bottom-20 right-4"; - } - return ""; - }; - - return ( -
- {/* Glass effect background */} - - -
-
- - - -
-
-
- ); - }, -); - -Controls.displayName = "Controls"; diff --git a/packages/ui/memory-graph/graph-canvas.tsx b/packages/ui/memory-graph/graph-canvas.tsx deleted file mode 100644 index c4623c854..000000000 --- a/packages/ui/memory-graph/graph-canvas.tsx +++ /dev/null @@ -1,762 +0,0 @@ -"use client"; - -import { - memo, - useCallback, - useEffect, - useLayoutEffect, - useMemo, - useRef, -} from "react"; -import { colors } from "./constants"; -import type { - DocumentWithMemories, - GraphCanvasProps, - GraphNode, - MemoryEntry, -} from "./types"; - -export const GraphCanvas = memo( - ({ - nodes, - edges, - panX, - panY, - zoom, - width, - height, - onNodeHover, - onNodeClick, - onNodeDragStart, - onNodeDragMove, - onNodeDragEnd, - onPanStart, - onPanMove, - onPanEnd, - onWheel, - onDoubleClick, - onTouchStart, - onTouchMove, - onTouchEnd, - draggingNodeId, - highlightDocumentIds, - }) => { - const canvasRef = useRef(null); - const animationRef = useRef(0); - const startTimeRef = useRef(Date.now()); - const mousePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); - const currentHoveredNode = useRef(null); - - // Initialize start time once - useEffect(() => { - startTimeRef.current = Date.now(); - }, []); - - // Efficient hit detection - const getNodeAtPosition = useCallback( - (x: number, y: number): string | null => { - // Check from top-most to bottom-most: memory nodes are drawn after documents - for (let i = nodes.length - 1; i >= 0; i--) { - const node = nodes[i]!; - const screenX = node.x * zoom + panX; - const screenY = node.y * zoom + panY; - const nodeSize = node.size * zoom; - - const dx = x - screenX; - const dy = y - screenY; - const distance = Math.sqrt(dx * dx + dy * dy); - - if (distance <= nodeSize / 2) { - return node.id; - } - } - return null; - }, - [nodes, panX, panY, zoom], - ); - - // Handle mouse events - const handleMouseMove = useCallback( - (e: React.MouseEvent) => { - const canvas = canvasRef.current; - if (!canvas) return; - - const rect = canvas.getBoundingClientRect(); - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - - mousePos.current = { x, y }; - - const nodeId = getNodeAtPosition(x, y); - if (nodeId !== currentHoveredNode.current) { - currentHoveredNode.current = nodeId; - onNodeHover(nodeId); - } - - // Handle node dragging - if (draggingNodeId) { - onNodeDragMove(e); - } - }, - [getNodeAtPosition, onNodeHover, draggingNodeId, onNodeDragMove], - ); - - const handleMouseDown = useCallback( - (e: React.MouseEvent) => { - const canvas = canvasRef.current; - if (!canvas) return; - - const rect = canvas.getBoundingClientRect(); - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - - const nodeId = getNodeAtPosition(x, y); - if (nodeId) { - // When starting a node drag, prevent initiating pan - e.stopPropagation(); - onNodeDragStart(nodeId, e); - return; - } - onPanStart(e); - }, - [getNodeAtPosition, onNodeDragStart, onPanStart], - ); - - const handleClick = useCallback( - (e: React.MouseEvent) => { - const canvas = canvasRef.current; - if (!canvas) return; - - const rect = canvas.getBoundingClientRect(); - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - - const nodeId = getNodeAtPosition(x, y); - if (nodeId) { - onNodeClick(nodeId); - } - }, - [getNodeAtPosition, onNodeClick], - ); - - // Professional rendering function with LOD - const render = useCallback(() => { - const canvas = canvasRef.current; - if (!canvas) return; - - const ctx = canvas.getContext("2d"); - if (!ctx) return; - - const currentTime = Date.now(); - const _elapsed = currentTime - startTimeRef.current; - - // Level-of-detail optimization based on zoom - const useSimplifiedRendering = zoom < 0.3; - - // Clear canvas - ctx.clearRect(0, 0, width, height); - - // Set high quality rendering - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = "high"; - - // Draw minimal background grid - ctx.strokeStyle = "rgba(148, 163, 184, 0.03)"; // Very subtle grid - ctx.lineWidth = 1; - const gridSpacing = 100 * zoom; - const offsetX = panX % gridSpacing; - const offsetY = panY % gridSpacing; - - // Simple, clean grid lines - for (let x = offsetX; x < width; x += gridSpacing) { - ctx.beginPath(); - ctx.moveTo(x, 0); - ctx.lineTo(x, height); - ctx.stroke(); - } - for (let y = offsetY; y < height; y += gridSpacing) { - ctx.beginPath(); - ctx.moveTo(0, y); - ctx.lineTo(width, y); - ctx.stroke(); - } - - // Create node lookup map - const nodeMap = new Map(nodes.map((node) => [node.id, node])); - - // Draw enhanced edges with sophisticated styling - ctx.lineCap = "round"; - edges.forEach((edge) => { - const sourceNode = nodeMap.get(edge.source); - const targetNode = nodeMap.get(edge.target); - - if (sourceNode && targetNode) { - const sourceX = sourceNode.x * zoom + panX; - const sourceY = sourceNode.y * zoom + panY; - const targetX = targetNode.x * zoom + panX; - const targetY = targetNode.y * zoom + panY; - - // Enhanced viewport culling with edge type considerations - if ( - sourceX < -100 || - sourceX > width + 100 || - targetX < -100 || - targetX > width + 100 - ) { - return; - } - - // Skip very weak connections when zoomed out for performance - if (useSimplifiedRendering) { - if ( - edge.edgeType === "doc-memory" && - edge.visualProps.opacity < 0.3 - ) { - return; // Skip very weak doc-memory edges when zoomed out - } - } - - // Enhanced connection styling based on edge type - let connectionColor = colors.connection.weak; - let dashPattern: number[] = []; - let opacity = edge.visualProps.opacity; - let lineWidth = Math.max(1, edge.visualProps.thickness * zoom); - - if (edge.edgeType === "doc-memory") { - // Doc-memory: Solid thin lines, subtle - dashPattern = []; - connectionColor = colors.connection.memory; - opacity = 0.9; - lineWidth = 1; - } else if (edge.edgeType === "doc-doc") { - // Doc-doc: Thick dashed lines with strong similarity emphasis - dashPattern = useSimplifiedRendering ? [] : [10, 5]; // Solid lines when zoomed out - opacity = Math.max(0, edge.similarity * 0.5); - lineWidth = Math.max(1, edge.similarity * 2); // Thicker for stronger similarity - - if (edge.similarity > 0.85) - connectionColor = colors.connection.strong; - else if (edge.similarity > 0.725) - connectionColor = colors.connection.medium; - } else if (edge.edgeType === "version") { - // Version chains: Double line effect with relation-specific colors - dashPattern = []; - connectionColor = edge.color || colors.relations.updates; - opacity = 0.8; - lineWidth = 2; - } - - ctx.strokeStyle = connectionColor; - ctx.lineWidth = lineWidth; - ctx.globalAlpha = opacity; - ctx.setLineDash(dashPattern); - - if (edge.edgeType === "version") { - // Special double-line rendering for version chains - // First line (outer) - ctx.lineWidth = 3; - ctx.globalAlpha = opacity * 0.3; - ctx.beginPath(); - ctx.moveTo(sourceX, sourceY); - ctx.lineTo(targetX, targetY); - ctx.stroke(); - - // Second line (inner) - ctx.lineWidth = 1; - ctx.globalAlpha = opacity; - ctx.beginPath(); - ctx.moveTo(sourceX, sourceY); - ctx.lineTo(targetX, targetY); - ctx.stroke(); - } else { - // Simplified lines when zoomed out, curved when zoomed in - if (useSimplifiedRendering) { - // Straight lines for performance - ctx.beginPath(); - ctx.moveTo(sourceX, sourceY); - ctx.lineTo(targetX, targetY); - ctx.stroke(); - } else { - // Regular curved line for doc-memory and doc-doc - const midX = (sourceX + targetX) / 2; - const midY = (sourceY + targetY) / 2; - const dx = targetX - sourceX; - const dy = targetY - sourceY; - const distance = Math.sqrt(dx * dx + dy * dy); - const controlOffset = - edge.edgeType === "doc-memory" - ? 15 - : Math.min(30, distance * 0.2); - - ctx.beginPath(); - ctx.moveTo(sourceX, sourceY); - ctx.quadraticCurveTo( - midX + controlOffset * (dy / distance), - midY - controlOffset * (dx / distance), - targetX, - targetY, - ); - ctx.stroke(); - } - } - - // Subtle arrow head for version edges - if (edge.edgeType === "version") { - const angle = Math.atan2(targetY - sourceY, targetX - sourceX); - const arrowLength = Math.max(6, 8 * zoom); // Shorter, more subtle - const arrowWidth = Math.max(8, 12 * zoom); - - // Calculate arrow position offset from node edge - const nodeRadius = (targetNode.size * zoom) / 2; - const offsetDistance = nodeRadius + 2; - const arrowX = targetX - Math.cos(angle) * offsetDistance; - const arrowY = targetY - Math.sin(angle) * offsetDistance; - - ctx.save(); - ctx.translate(arrowX, arrowY); - ctx.rotate(angle); - ctx.setLineDash([]); - - // Simple outlined arrow (not filled) - ctx.strokeStyle = connectionColor; - ctx.lineWidth = Math.max(1, 1.5 * zoom); - ctx.globalAlpha = opacity; - - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.lineTo(-arrowLength, arrowWidth / 2); - ctx.moveTo(0, 0); - ctx.lineTo(-arrowLength, -arrowWidth / 2); - ctx.stroke(); - - ctx.restore(); - } - } - }); - - ctx.globalAlpha = 1; - ctx.setLineDash([]); - - // Prepare highlight set from provided document IDs (customId or internal) - const highlightSet = new Set(highlightDocumentIds ?? []); - - // Draw nodes with enhanced styling and LOD optimization - nodes.forEach((node) => { - const screenX = node.x * zoom + panX; - const screenY = node.y * zoom + panY; - const nodeSize = node.size * zoom; - - // Enhanced viewport culling - const margin = nodeSize + 50; - if ( - screenX < -margin || - screenX > width + margin || - screenY < -margin || - screenY > height + margin - ) { - return; - } - - const isHovered = currentHoveredNode.current === node.id; - const isDragging = node.isDragging; - const isHighlightedDocument = (() => { - if (node.type !== "document" || highlightSet.size === 0) return false; - const doc = node.data as DocumentWithMemories; - if (doc.customId && highlightSet.has(doc.customId)) return true; - return highlightSet.has(doc.id); - })(); - - if (node.type === "document") { - // Enhanced glassmorphism document styling - const docWidth = nodeSize * 1.4; - const docHeight = nodeSize * 0.9; - - // Multi-layer glass effect - ctx.fillStyle = isDragging - ? colors.document.accent - : isHovered - ? colors.document.secondary - : colors.document.primary; - ctx.globalAlpha = 1; - - // Enhanced border with subtle glow - ctx.strokeStyle = isDragging - ? colors.document.glow - : isHovered - ? colors.document.accent - : colors.document.border; - ctx.lineWidth = isDragging ? 3 : isHovered ? 2 : 1; - - // Rounded rectangle with enhanced styling - const radius = useSimplifiedRendering ? 6 : 12; - ctx.beginPath(); - ctx.roundRect( - screenX - docWidth / 2, - screenY - docHeight / 2, - docWidth, - docHeight, - radius, - ); - ctx.fill(); - ctx.stroke(); - - // Subtle inner highlight for glass effect (skip when zoomed out) - if (!useSimplifiedRendering && (isHovered || isDragging)) { - ctx.strokeStyle = "rgba(255, 255, 255, 0.1)"; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.roundRect( - screenX - docWidth / 2 + 1, - screenY - docHeight / 2 + 1, - docWidth - 2, - docHeight - 2, - radius - 1, - ); - ctx.stroke(); - } - - // Highlight ring for search hits - if (isHighlightedDocument) { - ctx.save(); - ctx.globalAlpha = 0.9; - ctx.strokeStyle = colors.accent.primary; - ctx.lineWidth = 3; - ctx.setLineDash([6, 4]); - const ringPadding = 10; - ctx.beginPath(); - ctx.roundRect( - screenX - docWidth / 2 - ringPadding, - screenY - docHeight / 2 - ringPadding, - docWidth + ringPadding * 2, - docHeight + ringPadding * 2, - radius + 6, - ); - ctx.stroke(); - ctx.setLineDash([]); - ctx.restore(); - } - } else { - // Enhanced memory styling with status indicators - const mem = node.data as MemoryEntry; - const isForgotten = - mem.isForgotten || - (mem.forgetAfter && - new Date(mem.forgetAfter).getTime() < Date.now()); - const isLatest = mem.isLatest; - - // Check if memory is expiring soon (within 7 days) - const expiringSoon = - mem.forgetAfter && - !isForgotten && - new Date(mem.forgetAfter).getTime() - Date.now() < - 1000 * 60 * 60 * 24 * 7; - - // Check if memory is new (created within last 24 hours) - const isNew = - !isForgotten && - new Date(mem.createdAt).getTime() > - Date.now() - 1000 * 60 * 60 * 24; - - // Determine colors based on status - let fillColor = colors.memory.primary; - let borderColor = colors.memory.border; - let glowColor = colors.memory.glow; - - if (isForgotten) { - fillColor = colors.status.forgotten; - borderColor = "rgba(220,38,38,0.3)"; - glowColor = "rgba(220,38,38,0.2)"; - } else if (expiringSoon) { - borderColor = colors.status.expiring; - glowColor = colors.accent.amber; - } else if (isNew) { - borderColor = colors.status.new; - glowColor = colors.accent.emerald; - } - - if (isDragging) { - fillColor = colors.memory.accent; - borderColor = glowColor; - } else if (isHovered) { - fillColor = colors.memory.secondary; - } - - const radius = nodeSize / 2; - - ctx.fillStyle = fillColor; - ctx.globalAlpha = isLatest ? 1 : 0.4; - ctx.strokeStyle = borderColor; - ctx.lineWidth = isDragging ? 3 : isHovered ? 2 : 1.5; - - if (useSimplifiedRendering) { - // Simple circles when zoomed out for performance - ctx.beginPath(); - ctx.arc(screenX, screenY, radius, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - } else { - // HEXAGONAL memory nodes when zoomed in - const sides = 6; - ctx.beginPath(); - for (let i = 0; i < sides; i++) { - const angle = (i * 2 * Math.PI) / sides - Math.PI / 2; // Start from top - const x = screenX + radius * Math.cos(angle); - const y = screenY + radius * Math.sin(angle); - if (i === 0) { - ctx.moveTo(x, y); - } else { - ctx.lineTo(x, y); - } - } - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - - // Inner highlight for glass effect - if (isHovered || isDragging) { - ctx.strokeStyle = "rgba(147, 197, 253, 0.3)"; - ctx.lineWidth = 1; - const innerRadius = radius - 2; - ctx.beginPath(); - for (let i = 0; i < sides; i++) { - const angle = (i * 2 * Math.PI) / sides - Math.PI / 2; - const x = screenX + innerRadius * Math.cos(angle); - const y = screenY + innerRadius * Math.sin(angle); - if (i === 0) { - ctx.moveTo(x, y); - } else { - ctx.lineTo(x, y); - } - } - ctx.closePath(); - ctx.stroke(); - } - } - - // Status indicators overlay (always preserve these as required) - if (isForgotten) { - // Cross for forgotten memories - ctx.strokeStyle = "rgba(220,38,38,0.4)"; - ctx.lineWidth = 2; - const r = nodeSize * 0.25; - ctx.beginPath(); - ctx.moveTo(screenX - r, screenY - r); - ctx.lineTo(screenX + r, screenY + r); - ctx.moveTo(screenX + r, screenY - r); - ctx.lineTo(screenX - r, screenY + r); - ctx.stroke(); - } else if (isNew) { - // Small dot for new memories - ctx.fillStyle = colors.status.new; - ctx.beginPath(); - ctx.arc( - screenX + nodeSize * 0.25, - screenY - nodeSize * 0.25, - Math.max(2, nodeSize * 0.15), // Scale with node size, minimum 2px - 0, - 2 * Math.PI, - ); - ctx.fill(); - } - } - - // Enhanced hover glow effect (skip when zoomed out for performance) - if (!useSimplifiedRendering && (isHovered || isDragging)) { - const glowColor = - node.type === "document" - ? colors.document.glow - : colors.memory.glow; - - ctx.strokeStyle = glowColor; - ctx.lineWidth = 1; - ctx.setLineDash([3, 3]); - ctx.globalAlpha = 0.6; - - ctx.beginPath(); - const glowSize = nodeSize * 0.7; - if (node.type === "document") { - ctx.roundRect( - screenX - glowSize, - screenY - glowSize / 1.4, - glowSize * 2, - glowSize * 1.4, - 15, - ); - } else { - // Hexagonal glow for memory nodes - const glowRadius = glowSize; - const sides = 6; - for (let i = 0; i < sides; i++) { - const angle = (i * 2 * Math.PI) / sides - Math.PI / 2; - const x = screenX + glowRadius * Math.cos(angle); - const y = screenY + glowRadius * Math.sin(angle); - if (i === 0) { - ctx.moveTo(x, y); - } else { - ctx.lineTo(x, y); - } - } - ctx.closePath(); - } - ctx.stroke(); - ctx.setLineDash([]); - } - }); - - ctx.globalAlpha = 1; - }, [nodes, edges, panX, panY, zoom, width, height, highlightDocumentIds]); - - // Change-based rendering instead of continuous animation - const lastRenderParams = useRef(""); - - // Create a render key that changes when visual state changes - const renderKey = useMemo(() => { - const nodePositions = nodes - .map( - (n) => - `${n.id}:${n.x}:${n.y}:${n.isDragging ? "1" : "0"}:${currentHoveredNode.current === n.id ? "1" : "0"}`, - ) - .join("|"); - const highlightKey = (highlightDocumentIds ?? []).join("|"); - return `${nodePositions}-${edges.length}-${panX}-${panY}-${zoom}-${width}-${height}-${highlightKey}`; - }, [ - nodes, - edges.length, - panX, - panY, - zoom, - width, - height, - highlightDocumentIds, - ]); - - // Only render when something actually changed - useEffect(() => { - if (renderKey !== lastRenderParams.current) { - lastRenderParams.current = renderKey; - render(); - } - }, [renderKey, render]); - - // Cleanup any existing animation frames - useEffect(() => { - return () => { - if (animationRef.current) { - cancelAnimationFrame(animationRef.current); - } - }; - }, []); - - // Add native wheel event listener to prevent browser zoom - useEffect(() => { - const canvas = canvasRef.current; - if (!canvas) return; - - const handleNativeWheel = (e: WheelEvent) => { - e.preventDefault(); - e.stopPropagation(); - - // Call the onWheel handler with a synthetic-like event - onWheel({ - deltaY: e.deltaY, - deltaX: e.deltaX, - clientX: e.clientX, - clientY: e.clientY, - currentTarget: canvas, - nativeEvent: e, - preventDefault: () => {}, - stopPropagation: () => {}, - } as React.WheelEvent); - }; - - // Add listener with passive: false to ensure preventDefault works - canvas.addEventListener("wheel", handleNativeWheel, { passive: false }); - - // Also prevent gesture events for touch devices - const handleGesture = (e: Event) => { - e.preventDefault(); - }; - - canvas.addEventListener("gesturestart", handleGesture, { - passive: false, - }); - canvas.addEventListener("gesturechange", handleGesture, { - passive: false, - }); - canvas.addEventListener("gestureend", handleGesture, { passive: false }); - - return () => { - canvas.removeEventListener("wheel", handleNativeWheel); - canvas.removeEventListener("gesturestart", handleGesture); - canvas.removeEventListener("gesturechange", handleGesture); - canvas.removeEventListener("gestureend", handleGesture); - }; - }, [onWheel]); - - // High-DPI handling -------------------------------------------------- - const dpr = - typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1; - - useLayoutEffect(() => { - const canvas = canvasRef.current; - if (!canvas) return; - - // upscale backing store - canvas.style.width = `${width}px`; - canvas.style.height = `${height}px`; - canvas.width = width * dpr; - canvas.height = height * dpr; - - const ctx = canvas.getContext("2d"); - ctx?.scale(dpr, dpr); - }, [width, height, dpr]); - // ----------------------------------------------------------------------- - - return ( - { - if (draggingNodeId) { - onNodeDragEnd(); - } else { - onPanEnd(); - } - }} - onMouseMove={(e) => { - handleMouseMove(e); - if (!draggingNodeId) { - onPanMove(e); - } - }} - onMouseUp={() => { - if (draggingNodeId) { - onNodeDragEnd(); - } else { - onPanEnd(); - } - }} - onTouchStart={onTouchStart} - onTouchMove={onTouchMove} - onTouchEnd={onTouchEnd} - ref={canvasRef} - style={{ - cursor: draggingNodeId - ? "grabbing" - : currentHoveredNode.current - ? "grab" - : "move", - touchAction: "none", - userSelect: "none", - WebkitUserSelect: "none", - }} - width={width} - /> - ); - }, -); - -GraphCanvas.displayName = "GraphCanvas"; diff --git a/packages/ui/memory-graph/graph-webgl-canvas.tsx b/packages/ui/memory-graph/graph-webgl-canvas.tsx deleted file mode 100644 index af13eefc7..000000000 --- a/packages/ui/memory-graph/graph-webgl-canvas.tsx +++ /dev/null @@ -1,794 +0,0 @@ -"use client"; - -import { Application, extend } from "@pixi/react"; -import { Container as PixiContainer, Graphics as PixiGraphics } from "pixi.js"; -import { memo, useCallback, useEffect, useMemo, useRef } from "react"; -import { colors } from "./constants"; -import type { GraphCanvasProps, MemoryEntry } from "./types"; - -// Register Pixi Graphics and Container so they can be used as JSX elements -extend({ Graphics: PixiGraphics, Container: PixiContainer }); - -export const GraphWebGLCanvas = memo( - ({ - nodes, - edges, - panX, - panY, - zoom, - width, - height, - onNodeHover, - onNodeClick, - onNodeDragStart, - onNodeDragMove, - onNodeDragEnd, - onPanStart, - onPanMove, - onPanEnd, - onWheel, - onDoubleClick, - onTouchStart, - onTouchMove, - onTouchEnd, - draggingNodeId, - }) => { - const containerRef = useRef(null); - const isPanningRef = useRef(false); - const currentHoveredRef = useRef(null); - const pointerDownPosRef = useRef<{ x: number; y: number } | null>(null); - const pointerMovedRef = useRef(false); - // World container that is transformed instead of redrawing every pan/zoom - const worldContainerRef = useRef(null); - - // Throttled wheel handling ------------------------------------------- - const pendingWheelDeltaRef = useRef<{ dx: number; dy: number }>({ - dx: 0, - dy: 0, - }); - const wheelRafRef = useRef(null); - // Removed bitmap caching due to black-screen issues – throttle already boosts zoom performance - - // Persistent graphics refs - const gridG = useRef(null); - const edgesG = useRef(null); - const docsG = useRef(null); - const memsG = useRef(null); - - // ---------- Zoom bucket (reduces redraw frequency) ---------- - const zoomBucket = useMemo(() => Math.round(zoom * 4) / 4, [zoom]); - - // Redraw layers only when their data changes ---------------------- - useEffect(() => { - if (gridG.current) drawGrid(gridG.current); - }, [panX, panY, zoom, width, height]); - - useEffect(() => { - if (edgesG.current) drawEdges(edgesG.current); - }, [edgesG.current, edges, nodes, zoomBucket]); - - useEffect(() => { - if (docsG.current) drawDocuments(docsG.current); - }, [docsG.current, nodes, zoomBucket]); - - useEffect(() => { - if (memsG.current) drawMemories(memsG.current); - }, [memsG.current, nodes, zoomBucket]); - - // Apply pan & zoom via world transform instead of geometry rebuilds - useEffect(() => { - if (worldContainerRef.current) { - worldContainerRef.current.position.set(panX, panY); - worldContainerRef.current.scale.set(zoom); - } - }, [panX, panY, zoom]); - - // No bitmap caching – nothing to clean up - - /* ---------- Helpers ---------- */ - const getNodeAtPosition = useCallback( - (clientX: number, clientY: number): string | null => { - const rect = containerRef.current?.getBoundingClientRect(); - if (!rect) return null; - - const localX = clientX - rect.left; - const localY = clientY - rect.top; - - const worldX = (localX - panX) / zoom; - const worldY = (localY - panY) / zoom; - - for (const node of nodes) { - if (node.type === "document") { - const halfW = (node.size * 1.4) / 2; - const halfH = (node.size * 0.9) / 2; - if ( - worldX >= node.x - halfW && - worldX <= node.x + halfW && - worldY >= node.y - halfH && - worldY <= node.y + halfH - ) { - return node.id; - } - } else if (node.type === "memory") { - const r = node.size / 2; - const dx = worldX - node.x; - const dy = worldY - node.y; - if (dx * dx + dy * dy <= r * r) { - return node.id; - } - } - } - return null; - }, - [nodes, panX, panY, zoom], - ); - - /* ---------- Grid drawing ---------- */ - const drawGrid = useCallback( - (g: PixiGraphics) => { - g.clear(); - - const gridColor = 0x94a3b8; // rgb(148,163,184) - const gridAlpha = 0.03; - const gridSpacing = 100 * zoom; - - // panning offsets - const offsetX = panX % gridSpacing; - const offsetY = panY % gridSpacing; - - g.lineStyle(1, gridColor, gridAlpha); - - // vertical lines - for (let x = offsetX; x < width; x += gridSpacing) { - g.moveTo(x, 0); - g.lineTo(x, height); - } - - // horizontal lines - for (let y = offsetY; y < height; y += gridSpacing) { - g.moveTo(0, y); - g.lineTo(width, y); - } - - // Stroke to render grid lines - g.stroke(); - }, - [panX, panY, zoom, width, height], - ); - - /* ---------- Color parsing ---------- */ - const toHexAlpha = (input: string): { hex: number; alpha: number } => { - if (!input) return { hex: 0xffffff, alpha: 1 }; - const str = input.trim().toLowerCase(); - // rgba() or rgb() - const rgbaMatch = str - .replace(/\s+/g, "") - .match(/rgba?\((\d+),(\d+),(\d+)(?:,(\d*\.?\d+))?\)/i); - if (rgbaMatch) { - const r = Number.parseInt(rgbaMatch[1] || "0"); - const g = Number.parseInt(rgbaMatch[2] || "0"); - const b = Number.parseInt(rgbaMatch[3] || "0"); - const a = - rgbaMatch[4] !== undefined ? Number.parseFloat(rgbaMatch[4]) : 1; - return { hex: (r << 16) + (g << 8) + b, alpha: a }; - } - // #rrggbb or #rrggbbaa - if (str.startsWith("#")) { - const hexBody = str.slice(1); - if (hexBody.length === 6) { - return { hex: Number.parseInt(hexBody, 16), alpha: 1 }; - } - if (hexBody.length === 8) { - const rgb = Number.parseInt(hexBody.slice(0, 6), 16); - const aByte = Number.parseInt(hexBody.slice(6, 8), 16); - return { hex: rgb, alpha: aByte / 255 }; - } - } - // 0xRRGGBB - if (str.startsWith("0x")) { - return { hex: Number.parseInt(str, 16), alpha: 1 }; - } - return { hex: 0xffffff, alpha: 1 }; - }; - - const drawDocuments = useCallback( - (g: PixiGraphics) => { - g.clear(); - - nodes.forEach((node) => { - if (node.type !== "document") return; - - // World-space coordinates – container transform handles pan/zoom - const screenX = node.x; - const screenY = node.y; - const nodeSize = node.size; - - const docWidth = nodeSize * 1.4; - const docHeight = nodeSize * 0.9; - - // Choose colors similar to canvas version - const fill = node.isDragging - ? colors.document.accent - : node.isHovered - ? colors.document.secondary - : colors.document.primary; - - const strokeCol = node.isDragging - ? colors.document.glow - : node.isHovered - ? colors.document.accent - : colors.document.border; - - const { hex: fillHex, alpha: fillAlpha } = toHexAlpha(fill); - const { hex: strokeHex, alpha: strokeAlpha } = toHexAlpha(strokeCol); - - // Stroke first then fill for proper shape borders - const docStrokeWidth = - (node.isDragging ? 3 : node.isHovered ? 2 : 1) / zoom; - g.lineStyle(docStrokeWidth, strokeHex, strokeAlpha); - g.beginFill(fillHex, fillAlpha); - - const radius = zoom < 0.3 ? 6 : 12; - g.drawRoundedRect( - screenX - docWidth / 2, - screenY - docHeight / 2, - docWidth, - docHeight, - radius, - ); - g.endFill(); - - // Inner highlight for glass effect (match GraphCanvas) - if (zoom >= 0.3 && (node.isHovered || node.isDragging)) { - const { hex: hlHex } = toHexAlpha("#ffffff"); - // Inner highlight stroke width constant - const innerStroke = 1 / zoom; - g.lineStyle(innerStroke, hlHex, 0.1); - g.drawRoundedRect( - screenX - docWidth / 2 + 1, - screenY - docHeight / 2 + 1, - docWidth - 2, - docHeight - 2, - radius - 1, - ); - g.stroke(); - } - }); - }, - [nodes, zoom], - ); - - /* ---------- Memories layer ---------- */ - const drawMemories = useCallback( - (g: PixiGraphics) => { - g.clear(); - - nodes.forEach((node) => { - if (node.type !== "memory") return; - - const mem = node.data as MemoryEntry; - const screenX = node.x; - const screenY = node.y; - const nodeSize = node.size; - - const radius = nodeSize / 2; - - // status checks - const isForgotten = - mem?.isForgotten || - (mem?.forgetAfter && - new Date(mem.forgetAfter).getTime() < Date.now()); - const isLatest = mem?.isLatest; - const expiringSoon = - mem?.forgetAfter && - !isForgotten && - new Date(mem.forgetAfter).getTime() - Date.now() < - 1000 * 60 * 60 * 24 * 7; - const isNew = - !isForgotten && - new Date(mem?.createdAt).getTime() > - Date.now() - 1000 * 60 * 60 * 24; - - // colours - let fillColor = colors.memory.primary; - let borderColor = colors.memory.border; - let glowColor = colors.memory.glow; - - if (isForgotten) { - fillColor = colors.status.forgotten; - borderColor = "rgba(220,38,38,0.3)"; - glowColor = "rgba(220,38,38,0.2)"; - } else if (expiringSoon) { - borderColor = colors.status.expiring; - glowColor = colors.accent.amber; - } else if (isNew) { - borderColor = colors.status.new; - glowColor = colors.accent.emerald; - } - - if (node.isDragging) { - fillColor = colors.memory.accent; - borderColor = glowColor; - } else if (node.isHovered) { - fillColor = colors.memory.secondary; - } - - const { hex: fillHex, alpha: fillAlpha } = toHexAlpha(fillColor); - const { hex: borderHex, alpha: borderAlpha } = - toHexAlpha(borderColor); - - // Match canvas behavior: multiply by isLatest global alpha - const globalAlpha = isLatest ? 1 : 0.4; - const finalFillAlpha = globalAlpha * fillAlpha; - const finalStrokeAlpha = globalAlpha * borderAlpha; - // Stroke first then fill for visible border - const memStrokeW = - (node.isDragging ? 3 : node.isHovered ? 2 : 1.5) / zoom; - g.lineStyle(memStrokeW, borderHex, finalStrokeAlpha); - g.beginFill(fillHex, finalFillAlpha); - - if (zoom < 0.3) { - // simplified circle when zoomed out - g.drawCircle(screenX, screenY, radius); - } else { - // hexagon - const sides = 6; - const points: number[] = []; - for (let i = 0; i < sides; i++) { - const angle = (i * 2 * Math.PI) / sides - Math.PI / 2; - points.push(screenX + radius * Math.cos(angle)); - points.push(screenY + radius * Math.sin(angle)); - } - g.drawPolygon(points); - } - - g.endFill(); - - // Status overlays (forgotten / new) – match GraphCanvas visuals - if (isForgotten) { - const { hex: crossHex, alpha: crossAlpha } = toHexAlpha( - "rgba(220,38,38,0.4)", - ); - // Cross/ dot overlay stroke widths constant - const overlayStroke = 2 / zoom; - g.lineStyle(overlayStroke, crossHex, globalAlpha * crossAlpha); - const rCross = nodeSize * 0.25; - g.moveTo(screenX - rCross, screenY - rCross); - g.lineTo(screenX + rCross, screenY + rCross); - g.moveTo(screenX + rCross, screenY - rCross); - g.lineTo(screenX - rCross, screenY + rCross); - g.stroke(); - } else if (isNew) { - const { hex: dotHex, alpha: dotAlpha } = toHexAlpha( - colors.status.new, - ); - // Dot scales with node (GraphCanvas behaviour) - const dotRadius = Math.max(2, nodeSize * 0.15); - g.beginFill(dotHex, globalAlpha * dotAlpha); - g.drawCircle( - screenX + nodeSize * 0.25, - screenY - nodeSize * 0.25, - dotRadius, - ); - g.endFill(); - } - }); - }, - [nodes, zoom], - ); - - /* ---------- Edges layer ---------- */ - // Helper: draw dashed quadratic curve to approximate canvas setLineDash - const drawDashedQuadratic = useCallback( - ( - g: PixiGraphics, - sx: number, - sy: number, - cx: number, - cy: number, - tx: number, - ty: number, - dash = 10, - gap = 5, - ) => { - // Sample the curve and accumulate lines per dash to avoid overdraw - const curveLength = Math.sqrt((sx - tx) ** 2 + (sy - ty) ** 2); - const totalSamples = Math.max( - 20, - Math.min(120, Math.floor(curveLength / 10)), - ); - let prevX = sx; - let prevY = sy; - let distanceSinceToggle = 0; - let drawSegment = true; - let hasActiveDash = false; - let dashStartX = sx; - let dashStartY = sy; - - for (let i = 1; i <= totalSamples; i++) { - const t = i / totalSamples; - const mt = 1 - t; - const x = mt * mt * sx + 2 * mt * t * cx + t * t * tx; - const y = mt * mt * sy + 2 * mt * t * cy + t * t * ty; - - const dx = x - prevX; - const dy = y - prevY; - const segLen = Math.sqrt(dx * dx + dy * dy); - distanceSinceToggle += segLen; - - if (drawSegment) { - if (!hasActiveDash) { - dashStartX = prevX; - dashStartY = prevY; - hasActiveDash = true; - } - } - - const threshold = drawSegment ? dash : gap; - if (distanceSinceToggle >= threshold) { - // end of current phase - if (drawSegment && hasActiveDash) { - g.moveTo(dashStartX, dashStartY); - g.lineTo(prevX, prevY); - g.stroke(); - hasActiveDash = false; - } - distanceSinceToggle = 0; - drawSegment = !drawSegment; - // If we transition into draw mode, start a new dash at current segment start - if (drawSegment) { - dashStartX = prevX; - dashStartY = prevY; - hasActiveDash = true; - } - } - - prevX = x; - prevY = y; - } - - // Flush any active dash at the end - if (drawSegment && hasActiveDash) { - g.moveTo(dashStartX, dashStartY); - g.lineTo(prevX, prevY); - g.stroke(); - } - }, - [], - ); - const drawEdges = useCallback( - (g: PixiGraphics) => { - g.clear(); - - // Match GraphCanvas LOD behaviour - const useSimplified = zoom < 0.3; - - // quick node lookup - const nodeMap = new Map(nodes.map((n) => [n.id, n])); - - edges.forEach((edge) => { - // Skip very weak doc-memory edges when zoomed out – behaviour copied from GraphCanvas - if ( - useSimplified && - edge.edgeType === "doc-memory" && - (edge.visualProps?.opacity ?? 1) < 0.3 - ) { - return; - } - const source = nodeMap.get(edge.source); - const target = nodeMap.get(edge.target); - if (!source || !target) return; - - const sx = source.x; - const sy = source.y; - const tx = target.x; - const ty = target.y; - - // No viewport culling here because container transform handles visibility - - let lineWidth = Math.max(1, edge.visualProps?.thickness ?? 1); - // Use opacity exactly as provided to match GraphCanvas behaviour - let opacity = edge.visualProps.opacity; - let col = edge.color || colors.connection.weak; - - if (edge.edgeType === "doc-memory") { - lineWidth = 1; - opacity = 0.9; - col = colors.connection.memory; - - if (useSimplified && opacity < 0.3) return; - } else if (edge.edgeType === "doc-doc") { - opacity = Math.max(0, edge.similarity * 0.5); - lineWidth = Math.max(1, edge.similarity * 2); - col = colors.connection.medium; - if (edge.similarity > 0.85) col = colors.connection.strong; - } else if (edge.edgeType === "version") { - col = edge.color || colors.relations.updates; - opacity = 0.8; - lineWidth = 2; - } - - const { hex: strokeHex, alpha: colorAlpha } = toHexAlpha(col); - const finalEdgeAlpha = Math.max(0, Math.min(1, opacity * colorAlpha)); - - // Always use round line caps (same as Canvas 2D) - const screenLineWidth = lineWidth / zoom; - g.lineStyle(screenLineWidth, strokeHex, finalEdgeAlpha); - - if (edge.edgeType === "version") { - // double line effect to match canvas (outer thicker, faint + inner thin) - g.lineStyle(3 / zoom, strokeHex, finalEdgeAlpha * 0.3); - g.moveTo(sx, sy); - g.lineTo(tx, ty); - g.stroke(); - - g.lineStyle(1 / zoom, strokeHex, finalEdgeAlpha); - g.moveTo(sx, sy); - g.lineTo(tx, ty); - g.stroke(); - - // arrow head - const angle = Math.atan2(ty - sy, tx - sx); - const arrowLen = Math.max(6 / zoom, 8); - const nodeRadius = target.size / 2; - const ax = tx - Math.cos(angle) * (nodeRadius + 2); - const ay = ty - Math.sin(angle) * (nodeRadius + 2); - - g.moveTo(ax, ay); - g.lineTo( - ax - arrowLen * Math.cos(angle - Math.PI / 6), - ay - arrowLen * Math.sin(angle - Math.PI / 6), - ); - g.moveTo(ax, ay); - g.lineTo( - ax - arrowLen * Math.cos(angle + Math.PI / 6), - ay - arrowLen * Math.sin(angle + Math.PI / 6), - ); - g.stroke(); - } else { - // straight line when zoomed out; dashed curved when zoomed in for doc-doc - if (useSimplified) { - g.moveTo(sx, sy); - g.lineTo(tx, ty); - g.stroke(); - } else { - const midX = (sx + tx) / 2; - const midY = (sy + ty) / 2; - const dx = tx - sx; - const dy = ty - sy; - const dist = Math.sqrt(dx * dx + dy * dy); - const ctrlOffset = - edge.edgeType === "doc-memory" ? 15 : Math.min(30, dist * 0.2); - - const cx = midX + ctrlOffset * (dy / dist); - const cy = midY - ctrlOffset * (dx / dist); - - if (edge.edgeType === "doc-doc") { - if (useSimplified) { - // Straight line when zoomed out (no dash) - g.moveTo(sx, sy); - g.quadraticCurveTo(cx, cy, tx, ty); - g.stroke(); - } else { - // Dash lengths scale with zoom to keep screen size constant - const dash = 10 / zoom; - const gap = 5 / zoom; - drawDashedQuadratic(g, sx, sy, cx, cy, tx, ty, dash, gap); - } - } else { - g.moveTo(sx, sy); - g.quadraticCurveTo(cx, cy, tx, ty); - g.stroke(); - } - } - } - }); - }, - [edges, nodes, zoom, width, drawDashedQuadratic], - ); - - /* ---------- pointer handlers (unchanged) ---------- */ - // Pointer move (pan or drag) - const handlePointerMove = useCallback( - (e: React.PointerEvent) => { - const mouseEvent = { - clientX: e.clientX, - clientY: e.clientY, - preventDefault: () => {}, - stopPropagation: () => {}, - } as React.MouseEvent; - - if (draggingNodeId) { - // Node dragging handled elsewhere (future steps) - onNodeDragMove(mouseEvent); - } else if (isPanningRef.current) { - onPanMove(mouseEvent); - } - - // Track movement for distinguishing click vs drag/pan - if (pointerDownPosRef.current) { - const dx = e.clientX - pointerDownPosRef.current.x; - const dy = e.clientY - pointerDownPosRef.current.y; - if (Math.sqrt(dx * dx + dy * dy) > 3) pointerMovedRef.current = true; - } - - // Hover detection - const nodeId = getNodeAtPosition(e.clientX, e.clientY); - if (nodeId !== currentHoveredRef.current) { - currentHoveredRef.current = nodeId; - onNodeHover(nodeId); - } - }, - [ - draggingNodeId, - onNodeDragMove, - onPanMove, - onNodeHover, - getNodeAtPosition, - ], - ); - - const handlePointerDown = useCallback( - (e: React.PointerEvent) => { - const mouseEvent = { - clientX: e.clientX, - clientY: e.clientY, - preventDefault: () => {}, - stopPropagation: () => {}, - } as React.MouseEvent; - - const nodeId = getNodeAtPosition(e.clientX, e.clientY); - if (nodeId) { - onNodeDragStart(nodeId, mouseEvent); - // drag handled externally - } else { - onPanStart(mouseEvent); - isPanningRef.current = true; - } - pointerDownPosRef.current = { x: e.clientX, y: e.clientY }; - pointerMovedRef.current = false; - }, - [onPanStart, onNodeDragStart, getNodeAtPosition], - ); - - const handlePointerUp = useCallback( - (e: React.PointerEvent) => { - const wasPanning = isPanningRef.current; - if (draggingNodeId) onNodeDragEnd(); - else if (wasPanning) onPanEnd(); - - // Consider it a click if not panning and movement was minimal - if (!wasPanning && !pointerMovedRef.current) { - const nodeId = getNodeAtPosition(e.clientX, e.clientY); - if (nodeId) onNodeClick(nodeId); - } - - isPanningRef.current = false; - pointerDownPosRef.current = null; - pointerMovedRef.current = false; - }, - [draggingNodeId, onNodeDragEnd, onPanEnd, getNodeAtPosition, onNodeClick], - ); - - // Click handler – opens detail panel - const handleClick = useCallback( - (e: React.MouseEvent) => { - if (isPanningRef.current) return; - const nodeId = getNodeAtPosition(e.clientX, e.clientY); - if (nodeId) onNodeClick(nodeId); - }, - [getNodeAtPosition, onNodeClick], - ); - - // Click handled in pointer up to avoid duplicate events - - const handleWheel = useCallback( - (e: React.WheelEvent) => { - e.preventDefault(); - e.stopPropagation(); - - // Accumulate deltas - pendingWheelDeltaRef.current.dx += e.deltaX; - pendingWheelDeltaRef.current.dy += e.deltaY; - - // Schedule a single update per frame - if (wheelRafRef.current === null) { - wheelRafRef.current = requestAnimationFrame(() => { - const { dx, dy } = pendingWheelDeltaRef.current; - pendingWheelDeltaRef.current = { dx: 0, dy: 0 }; - - // @ts-expect-error - onWheel({ - deltaY: dy, - deltaX: dx, - clientX: e.clientX, - clientY: e.clientY, - currentTarget: containerRef.current, - nativeEvent: e.nativeEvent, - preventDefault: () => {}, - stopPropagation: () => {}, - } as React.WheelEvent); - - wheelRafRef.current = null; - - // nothing else – caching removed - }); - } - }, - [onWheel], - ); - - // Cleanup any pending RAF on unmount - useEffect(() => { - return () => { - if (wheelRafRef.current !== null) { - cancelAnimationFrame(wheelRafRef.current); - } - }; - }, []); - - return ( -
- onDoubleClick?.(ev as unknown as React.MouseEvent) - } - onKeyDown={(ev) => { - if (ev.key === "Enter") - handleClick(ev as unknown as React.MouseEvent); - }} - onPointerDown={handlePointerDown} - onPointerLeave={() => { - if (draggingNodeId) onNodeDragEnd(); - if (isPanningRef.current) onPanEnd(); - isPanningRef.current = false; - pointerDownPosRef.current = null; - pointerMovedRef.current = false; - }} - onPointerMove={handlePointerMove} - onPointerUp={handlePointerUp} - onTouchStart={onTouchStart} - onTouchMove={onTouchMove} - onTouchEnd={onTouchEnd} - onWheel={handleWheel} - ref={containerRef} - role="application" - style={{ - cursor: draggingNodeId ? "grabbing" : "move", - touchAction: "none", - userSelect: "none", - WebkitUserSelect: "none", - }} - > - - {/* Grid background (not affected by world transform) */} - {}} /> - - {/* World container that pans/zooms as a single transform */} - - {/* Edges */} - {}} /> - - {/* Documents */} - {}} /> - - {/* Memories */} - {}} /> - - -
- ); - }, -); - -GraphWebGLCanvas.displayName = "GraphWebGLCanvas"; diff --git a/packages/ui/memory-graph/hooks/use-graph-data.ts b/packages/ui/memory-graph/hooks/use-graph-data.ts deleted file mode 100644 index 3e9fa5ccc..000000000 --- a/packages/ui/memory-graph/hooks/use-graph-data.ts +++ /dev/null @@ -1,304 +0,0 @@ -"use client"; - -import { - calculateSemanticSimilarity, - getConnectionVisualProps, - getMagicalConnectionColor, -} from "@repo/lib/similarity"; -import { useMemo } from "react"; -import { colors, LAYOUT_CONSTANTS } from "../constants"; -import type { - DocumentsResponse, - DocumentWithMemories, - GraphEdge, - GraphNode, - MemoryEntry, - MemoryRelation, -} from "../types"; - -export function useGraphData( - data: DocumentsResponse | null, - selectedSpace: string, - nodePositions: Map, - draggingNodeId: string | null, -) { - return useMemo(() => { - if (!data?.documents) return { nodes: [], edges: [] }; - - const allNodes: GraphNode[] = []; - const allEdges: GraphEdge[] = []; - - // Filter documents that have memories in selected space - const filteredDocuments = data.documents - .map((doc) => ({ - ...doc, - memoryEntries: - selectedSpace === "all" - ? doc.memoryEntries - : doc.memoryEntries.filter( - (memory) => - (memory.spaceContainerTag ?? memory.spaceId ?? "default") === - selectedSpace, - ), - })) - .filter((doc) => doc.memoryEntries.length > 0); - - // Group documents by space for better clustering - const documentsBySpace = new Map(); - filteredDocuments.forEach((doc) => { - const docSpace = - doc.memoryEntries[0]?.spaceContainerTag ?? - doc.memoryEntries[0]?.spaceId ?? - "default"; - if (!documentsBySpace.has(docSpace)) { - documentsBySpace.set(docSpace, []); - } - const spaceDocsArr = documentsBySpace.get(docSpace); - if (spaceDocsArr) { - spaceDocsArr.push(doc); - } - }); - - // Enhanced Layout with Space Separation - const { centerX, centerY, clusterRadius, spaceSpacing, documentSpacing } = - LAYOUT_CONSTANTS; - - /* 1. Build DOCUMENT nodes with space-aware clustering */ - const documentNodes: GraphNode[] = []; - let spaceIndex = 0; - - documentsBySpace.forEach((spaceDocs) => { - const spaceAngle = (spaceIndex / documentsBySpace.size) * Math.PI * 2; - const spaceOffsetX = Math.cos(spaceAngle) * spaceSpacing; - const spaceOffsetY = Math.sin(spaceAngle) * spaceSpacing; - const spaceCenterX = centerX + spaceOffsetX; - const spaceCenterY = centerY + spaceOffsetY; - - spaceDocs.forEach((doc, docIndex) => { - // Create proper circular layout with concentric rings - const docsPerRing = 6; // Start with 6 docs in inner ring - let currentRing = 0; - let docsInCurrentRing = docsPerRing; - let totalDocsInPreviousRings = 0; - - // Find which ring this document belongs to - while (totalDocsInPreviousRings + docsInCurrentRing <= docIndex) { - totalDocsInPreviousRings += docsInCurrentRing; - currentRing++; - docsInCurrentRing = docsPerRing + currentRing * 4; // Each ring has more docs - } - - // Position within the ring - const positionInRing = docIndex - totalDocsInPreviousRings; - const angleInRing = (positionInRing / docsInCurrentRing) * Math.PI * 2; - - // Radius increases significantly with each ring - const baseRadius = documentSpacing * 0.8; - const radius = - currentRing === 0 - ? baseRadius - : baseRadius + currentRing * documentSpacing * 1.2; - - const defaultX = spaceCenterX + Math.cos(angleInRing) * radius; - const defaultY = spaceCenterY + Math.sin(angleInRing) * radius; - - const customPos = nodePositions.get(doc.id); - - documentNodes.push({ - id: doc.id, - type: "document", - x: customPos?.x ?? defaultX, - y: customPos?.y ?? defaultY, - data: doc, - size: 58, - color: colors.document.primary, - isHovered: false, - isDragging: draggingNodeId === doc.id, - } satisfies GraphNode); - }); - - spaceIndex++; - }); - - /* 2. Gentle document collision avoidance with dampening */ - const minDocDist = LAYOUT_CONSTANTS.minDocDist; - - // Reduced iterations and gentler repulsion for smoother movement - for (let iter = 0; iter < 2; iter++) { - documentNodes.forEach((nodeA) => { - documentNodes.forEach((nodeB) => { - if (nodeA.id >= nodeB.id) return; - - // Only repel documents in the same space - const spaceA = - (nodeA.data as DocumentWithMemories).memoryEntries[0] - ?.spaceContainerTag ?? - (nodeA.data as DocumentWithMemories).memoryEntries[0]?.spaceId ?? - "default"; - const spaceB = - (nodeB.data as DocumentWithMemories).memoryEntries[0] - ?.spaceContainerTag ?? - (nodeB.data as DocumentWithMemories).memoryEntries[0]?.spaceId ?? - "default"; - - if (spaceA !== spaceB) return; - - const dx = nodeB.x - nodeA.x; - const dy = nodeB.y - nodeA.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - - if (dist < minDocDist) { - // Much gentler push with dampening - const push = (minDocDist - dist) / 8; - const dampening = Math.max(0.1, Math.min(1, dist / minDocDist)); - const smoothPush = push * dampening * 0.5; - - const nx = dx / dist; - const ny = dy / dist; - nodeA.x -= nx * smoothPush; - nodeA.y -= ny * smoothPush; - nodeB.x += nx * smoothPush; - nodeB.y += ny * smoothPush; - } - }); - }); - } - - allNodes.push(...documentNodes); - - /* 3. Add memories around documents WITH doc-memory connections */ - documentNodes.forEach((docNode) => { - const memoryNodeMap = new Map(); - const doc = docNode.data as DocumentWithMemories; - - doc.memoryEntries.forEach((memory, memIndex) => { - const memoryId = `${memory.id}`; - const customMemPos = nodePositions.get(memoryId); - - const clusterAngle = - (memIndex / doc.memoryEntries.length) * Math.PI * 2; - const variation = Math.sin(memIndex * 2.5) * 0.3 + 0.7; - const distance = clusterRadius * variation; - - const seed = - memIndex * 12345 + Number.parseInt(docNode.id.slice(0, 6), 36); - const offsetX = Math.sin(seed) * 0.5 * 40; - const offsetY = Math.cos(seed) * 0.5 * 40; - - const defaultMemX = - docNode.x + Math.cos(clusterAngle) * distance + offsetX; - const defaultMemY = - docNode.y + Math.sin(clusterAngle) * distance + offsetY; - - if (!memoryNodeMap.has(memoryId)) { - const memoryNode: GraphNode = { - id: memoryId, - type: "memory", - x: customMemPos?.x ?? defaultMemX, - y: customMemPos?.y ?? defaultMemY, - data: memory, - size: Math.max( - 32, - Math.min(48, (memory.memory?.length || 50) * 0.5), - ), - color: colors.memory.primary, - isHovered: false, - isDragging: draggingNodeId === memoryId, - }; - memoryNodeMap.set(memoryId, memoryNode); - allNodes.push(memoryNode); - } - - // Create doc-memory edge with similarity - allEdges.push({ - id: `edge-${docNode.id}-${memory.id}`, - source: docNode.id, - target: memoryId, - similarity: 1, - visualProps: getConnectionVisualProps(1), - color: colors.connection.memory, - edgeType: "doc-memory", - }); - }); - }); - - // Build mapping of memoryId -> nodeId for version chains - const memNodeIdMap = new Map(); - allNodes.forEach((n) => { - if (n.type === "memory") { - memNodeIdMap.set((n.data as MemoryEntry).id, n.id); - } - }); - - // Add version-chain edges (old -> new) - data.documents.forEach((doc) => { - doc.memoryEntries.forEach((mem: MemoryEntry) => { - // Support both new object structure and legacy array/single parent fields - let parentRelations: Record = {}; - - if ( - mem.memoryRelations && - typeof mem.memoryRelations === "object" && - Object.keys(mem.memoryRelations).length > 0 - ) { - parentRelations = mem.memoryRelations; - } else if (mem.parentMemoryId) { - parentRelations = { - [mem.parentMemoryId]: "updates" as MemoryRelation, - }; - } - Object.entries(parentRelations).forEach(([pid, relationType]) => { - const fromId = memNodeIdMap.get(pid); - const toId = memNodeIdMap.get(mem.id); - if (fromId && toId) { - allEdges.push({ - id: `version-${fromId}-${toId}`, - source: fromId, - target: toId, - similarity: 1, - visualProps: { - opacity: 0.8, - thickness: 1, - glow: 0, - pulseDuration: 3000, - }, - // choose color based on relation type - color: colors.relations[relationType] ?? colors.relations.updates, - edgeType: "version", - relationType: relationType as MemoryRelation, - }); - } - }); - }); - }); - - // Document-to-document similarity edges - for (let i = 0; i < filteredDocuments.length; i++) { - const docI = filteredDocuments[i]; - if (!docI) continue; - - for (let j = i + 1; j < filteredDocuments.length; j++) { - const docJ = filteredDocuments[j]; - if (!docJ) continue; - - const sim = calculateSemanticSimilarity( - docI.summaryEmbedding ? Array.from(docI.summaryEmbedding) : null, - docJ.summaryEmbedding ? Array.from(docJ.summaryEmbedding) : null, - ); - if (sim > 0.725) { - allEdges.push({ - id: `doc-doc-${docI.id}-${docJ.id}`, - source: docI.id, - target: docJ.id, - similarity: sim, - visualProps: getConnectionVisualProps(sim), - color: getMagicalConnectionColor(sim, 200), - edgeType: "doc-doc", - }); - } - } - } - - return { nodes: allNodes, edges: allEdges }; - }, [data, selectedSpace, nodePositions, draggingNodeId]); -} diff --git a/packages/ui/memory-graph/hooks/use-graph-interactions.ts b/packages/ui/memory-graph/hooks/use-graph-interactions.ts deleted file mode 100644 index ec44e83e9..000000000 --- a/packages/ui/memory-graph/hooks/use-graph-interactions.ts +++ /dev/null @@ -1,564 +0,0 @@ -"use client"; - -import { useCallback, useRef, useState } from "react"; -import { GRAPH_SETTINGS } from "../constants"; -import type { GraphNode } from "../types"; - -export function useGraphInteractions( - variant: "console" | "consumer" = "console", -) { - const settings = GRAPH_SETTINGS[variant]; - - const [panX, setPanX] = useState(settings.initialPanX); - const [panY, setPanY] = useState(settings.initialPanY); - const [zoom, setZoom] = useState(settings.initialZoom); - const [isPanning, setIsPanning] = useState(false); - const [panStart, setPanStart] = useState({ x: 0, y: 0 }); - const [hoveredNode, setHoveredNode] = useState(null); - const [selectedNode, setSelectedNode] = useState(null); - const [draggingNodeId, setDraggingNodeId] = useState(null); - const [dragStart, setDragStart] = useState({ - x: 0, - y: 0, - nodeX: 0, - nodeY: 0, - }); - const [nodePositions, setNodePositions] = useState< - Map - >(new Map()); - - // Touch gesture state - const [touchState, setTouchState] = useState<{ - touches: { id: number; x: number; y: number }[]; - lastDistance: number; - lastCenter: { x: number; y: number }; - isGesturing: boolean; - }>({ - touches: [], - lastDistance: 0, - lastCenter: { x: 0, y: 0 }, - isGesturing: false, - }); - - // Animation state for smooth transitions - const animationRef = useRef(null); - const [isAnimating, setIsAnimating] = useState(false); - - // Smooth animation helper - const animateToViewState = useCallback( - ( - targetPanX: number, - targetPanY: number, - targetZoom: number, - duration = 300, - ) => { - if (animationRef.current) { - cancelAnimationFrame(animationRef.current); - } - - const startPanX = panX; - const startPanY = panY; - const startZoom = zoom; - const startTime = Date.now(); - - setIsAnimating(true); - - const animate = () => { - const elapsed = Date.now() - startTime; - const progress = Math.min(elapsed / duration, 1); - - // Ease out cubic function for smooth transitions - const easeOut = 1 - (1 - progress) ** 3; - - const currentPanX = startPanX + (targetPanX - startPanX) * easeOut; - const currentPanY = startPanY + (targetPanY - startPanY) * easeOut; - const currentZoom = startZoom + (targetZoom - startZoom) * easeOut; - - setPanX(currentPanX); - setPanY(currentPanY); - setZoom(currentZoom); - - if (progress < 1) { - animationRef.current = requestAnimationFrame(animate); - } else { - setIsAnimating(false); - animationRef.current = null; - } - }; - - animate(); - }, - [panX, panY, zoom], - ); - - // Node drag handlers - const handleNodeDragStart = useCallback( - (nodeId: string, e: React.MouseEvent, nodes?: GraphNode[]) => { - const node = nodes?.find((n) => n.id === nodeId); - if (!node) return; - - setDraggingNodeId(nodeId); - setDragStart({ - x: e.clientX, - y: e.clientY, - nodeX: node.x, - nodeY: node.y, - }); - }, - [], - ); - - const handleNodeDragMove = useCallback( - (e: React.MouseEvent) => { - if (!draggingNodeId) return; - - const deltaX = (e.clientX - dragStart.x) / zoom; - const deltaY = (e.clientY - dragStart.y) / zoom; - - const newX = dragStart.nodeX + deltaX; - const newY = dragStart.nodeY + deltaY; - - setNodePositions((prev) => - new Map(prev).set(draggingNodeId, { x: newX, y: newY }), - ); - }, - [draggingNodeId, dragStart, zoom], - ); - - const handleNodeDragEnd = useCallback(() => { - setDraggingNodeId(null); - }, []); - - // Pan handlers - const handlePanStart = useCallback( - (e: React.MouseEvent) => { - setIsPanning(true); - setPanStart({ x: e.clientX - panX, y: e.clientY - panY }); - }, - [panX, panY], - ); - - const handlePanMove = useCallback( - (e: React.MouseEvent) => { - if (!isPanning || draggingNodeId) return; - - const newPanX = e.clientX - panStart.x; - const newPanY = e.clientY - panStart.y; - setPanX(newPanX); - setPanY(newPanY); - }, - [isPanning, panStart, draggingNodeId], - ); - - const handlePanEnd = useCallback(() => { - setIsPanning(false); - }, []); - - // Zoom handlers - const handleWheel = useCallback( - (e: React.WheelEvent) => { - // Always prevent default to stop browser navigation - e.preventDefault(); - e.stopPropagation(); - - // Handle horizontal scrolling (trackpad swipe) by converting to pan - if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) { - // Horizontal scroll - pan the graph instead of zooming - const panDelta = e.deltaX * 0.5; - setPanX((prev) => prev - panDelta); - return; - } - - // Vertical scroll - zoom behavior - const delta = e.deltaY > 0 ? 0.97 : 1.03; - const newZoom = Math.max(0.05, Math.min(3, zoom * delta)); - - // Get mouse position relative to the viewport - let mouseX = e.clientX; - let mouseY = e.clientY; - - // Try to get the container bounds to make coordinates relative to the graph container - const target = e.currentTarget; - if (target && "getBoundingClientRect" in target) { - const rect = target.getBoundingClientRect(); - mouseX = e.clientX - rect.left; - mouseY = e.clientY - rect.top; - } - - // Calculate the world position of the mouse cursor - const worldX = (mouseX - panX) / zoom; - const worldY = (mouseY - panY) / zoom; - - // Calculate new pan to keep the mouse position stationary - const newPanX = mouseX - worldX * newZoom; - const newPanY = mouseY - worldY * newZoom; - - setZoom(newZoom); - setPanX(newPanX); - setPanY(newPanY); - }, - [zoom, panX, panY], - ); - - const zoomIn = useCallback( - (centerX?: number, centerY?: number, animate = true) => { - const zoomFactor = 1.2; - const newZoom = Math.min(3, zoom * zoomFactor); // Increased max zoom to 3x - - if (centerX !== undefined && centerY !== undefined) { - // Mouse-centered zoom for programmatic zoom in - const worldX = (centerX - panX) / zoom; - const worldY = (centerY - panY) / zoom; - const newPanX = centerX - worldX * newZoom; - const newPanY = centerY - worldY * newZoom; - - if (animate && !isAnimating) { - animateToViewState(newPanX, newPanY, newZoom, 200); - } else { - setZoom(newZoom); - setPanX(newPanX); - setPanY(newPanY); - } - } else { - if (animate && !isAnimating) { - animateToViewState(panX, panY, newZoom, 200); - } else { - setZoom(newZoom); - } - } - }, - [zoom, panX, panY, isAnimating, animateToViewState], - ); - - const zoomOut = useCallback( - (centerX?: number, centerY?: number, animate = true) => { - const zoomFactor = 0.8; - const newZoom = Math.max(0.05, zoom * zoomFactor); // Decreased min zoom to 0.05x - - if (centerX !== undefined && centerY !== undefined) { - // Mouse-centered zoom for programmatic zoom out - const worldX = (centerX - panX) / zoom; - const worldY = (centerY - panY) / zoom; - const newPanX = centerX - worldX * newZoom; - const newPanY = centerY - worldY * newZoom; - - if (animate && !isAnimating) { - animateToViewState(newPanX, newPanY, newZoom, 200); - } else { - setZoom(newZoom); - setPanX(newPanX); - setPanY(newPanY); - } - } else { - if (animate && !isAnimating) { - animateToViewState(panX, panY, newZoom, 200); - } else { - setZoom(newZoom); - } - } - }, - [zoom, panX, panY, isAnimating, animateToViewState], - ); - - const resetView = useCallback(() => { - setPanX(settings.initialPanX); - setPanY(settings.initialPanY); - setZoom(settings.initialZoom); - setNodePositions(new Map()); - }, [settings]); - - // Auto-fit graph to viewport - const autoFitToViewport = useCallback( - ( - nodes: GraphNode[], - viewportWidth: number, - viewportHeight: number, - options?: { occludedRightPx?: number; animate?: boolean }, - ) => { - if (nodes.length === 0) return; - - // Find the bounds of all nodes - let minX = Number.POSITIVE_INFINITY; - let maxX = Number.NEGATIVE_INFINITY; - let minY = Number.POSITIVE_INFINITY; - let maxY = Number.NEGATIVE_INFINITY; - - nodes.forEach((node) => { - minX = Math.min(minX, node.x - node.size / 2); - maxX = Math.max(maxX, node.x + node.size / 2); - minY = Math.min(minY, node.y - node.size / 2); - maxY = Math.max(maxY, node.y + node.size / 2); - }); - - // Calculate the center of the content - const contentCenterX = (minX + maxX) / 2; - const contentCenterY = (minY + maxY) / 2; - - // Calculate the size of the content - const contentWidth = maxX - minX; - const contentHeight = maxY - minY; - - // Add padding (20% on each side) - const paddingFactor = 1.4; - const paddedWidth = contentWidth * paddingFactor; - const paddedHeight = contentHeight * paddingFactor; - - // Account for occluded area on the right (e.g., chat panel) - const occludedRightPx = Math.max(0, options?.occludedRightPx ?? 0); - const availableWidth = Math.max(1, viewportWidth - occludedRightPx); - - // Calculate the zoom needed to fit the content within available width - const zoomX = availableWidth / paddedWidth; - const zoomY = viewportHeight / paddedHeight; - const newZoom = Math.min(Math.max(0.05, Math.min(zoomX, zoomY)), 3); - - // Calculate pan to center the content within available area - const availableCenterX = availableWidth / 2; - const newPanX = availableCenterX - contentCenterX * newZoom; - const newPanY = viewportHeight / 2 - contentCenterY * newZoom; - - // Apply the new view (optional animation) - if (options?.animate) { - const steps = 8; - const durationMs = 160; // snappy - const intervalMs = Math.max(1, Math.floor(durationMs / steps)); - const startZoom = zoom; - const startPanX = panX; - const startPanY = panY; - let i = 0; - const ease = (t: number) => 1 - (1 - t) ** 2; // ease-out quad - const timer = setInterval(() => { - i++; - const t = ease(i / steps); - setZoom(startZoom + (newZoom - startZoom) * t); - setPanX(startPanX + (newPanX - startPanX) * t); - setPanY(startPanY + (newPanY - startPanY) * t); - if (i >= steps) clearInterval(timer); - }, intervalMs); - } else { - setZoom(newZoom); - setPanX(newPanX); - setPanY(newPanY); - } - }, - [zoom, panX, panY], - ); - - // Touch gesture handlers for mobile pinch-to-zoom - const handleTouchStart = useCallback((e: React.TouchEvent) => { - const touches = Array.from(e.touches).map((touch) => ({ - id: touch.identifier, - x: touch.clientX, - y: touch.clientY, - })); - - if (touches.length >= 2) { - // Start gesture with two or more fingers - const touch1 = touches[0]!; - const touch2 = touches[1]!; - - const distance = Math.sqrt( - (touch2.x - touch1.x) ** 2 + (touch2.y - touch1.y) ** 2, - ); - - const center = { - x: (touch1.x + touch2.x) / 2, - y: (touch1.y + touch2.y) / 2, - }; - - setTouchState({ - touches, - lastDistance: distance, - lastCenter: center, - isGesturing: true, - }); - } else { - setTouchState((prev) => ({ ...prev, touches, isGesturing: false })); - } - }, []); - - const handleTouchMove = useCallback( - (e: React.TouchEvent) => { - e.preventDefault(); - - const touches = Array.from(e.touches).map((touch) => ({ - id: touch.identifier, - x: touch.clientX, - y: touch.clientY, - })); - - if (touches.length >= 2 && touchState.isGesturing) { - const touch1 = touches[0]!; - const touch2 = touches[1]!; - - const distance = Math.sqrt( - (touch2.x - touch1.x) ** 2 + (touch2.y - touch1.y) ** 2, - ); - - const center = { - x: (touch1.x + touch2.x) / 2, - y: (touch1.y + touch2.y) / 2, - }; - - // Calculate zoom change based on pinch distance change - const distanceChange = distance / touchState.lastDistance; - const newZoom = Math.max(0.05, Math.min(3, zoom * distanceChange)); - - // Get canvas bounds for center calculation - const canvas = e.currentTarget as HTMLElement; - const rect = canvas.getBoundingClientRect(); - const centerX = center.x - rect.left; - const centerY = center.y - rect.top; - - // Calculate the world position of the pinch center - const worldX = (centerX - panX) / zoom; - const worldY = (centerY - panY) / zoom; - - // Calculate new pan to keep the pinch center stationary - const newPanX = centerX - worldX * newZoom; - const newPanY = centerY - worldY * newZoom; - - // Calculate pan change based on center movement - const centerDx = center.x - touchState.lastCenter.x; - const centerDy = center.y - touchState.lastCenter.y; - - setZoom(newZoom); - setPanX(newPanX + centerDx); - setPanY(newPanY + centerDy); - - setTouchState({ - touches, - lastDistance: distance, - lastCenter: center, - isGesturing: true, - }); - } else if (touches.length === 1 && !touchState.isGesturing && isPanning) { - // Single finger pan (only if not in gesture mode) - const touch = touches[0]!; - const newPanX = touch.x - panStart.x; - const newPanY = touch.y - panStart.y; - setPanX(newPanX); - setPanY(newPanY); - } - }, - [touchState, zoom, panX, panY, isPanning, panStart], - ); - - const handleTouchEnd = useCallback((e: React.TouchEvent) => { - const touches = Array.from(e.touches).map((touch) => ({ - id: touch.identifier, - x: touch.clientX, - y: touch.clientY, - })); - - if (touches.length < 2) { - setTouchState((prev) => ({ ...prev, touches, isGesturing: false })); - } else { - setTouchState((prev) => ({ ...prev, touches })); - } - - if (touches.length === 0) { - setIsPanning(false); - } - }, []); - - // Center viewport on a specific world position (with animation) - const centerViewportOn = useCallback( - ( - worldX: number, - worldY: number, - viewportWidth: number, - viewportHeight: number, - animate = true, - ) => { - const newPanX = viewportWidth / 2 - worldX * zoom; - const newPanY = viewportHeight / 2 - worldY * zoom; - - if (animate && !isAnimating) { - animateToViewState(newPanX, newPanY, zoom, 400); - } else { - setPanX(newPanX); - setPanY(newPanY); - } - }, - [zoom, isAnimating, animateToViewState], - ); - - // Node interaction handlers - const handleNodeHover = useCallback((nodeId: string | null) => { - setHoveredNode(nodeId); - }, []); - - const handleNodeClick = useCallback( - (nodeId: string) => { - setSelectedNode(selectedNode === nodeId ? null : nodeId); - }, - [selectedNode], - ); - - const handleDoubleClick = useCallback( - (e: React.MouseEvent) => { - // Calculate new zoom (zoom in by 1.5x) - const zoomFactor = 1.5; - const newZoom = Math.min(3, zoom * zoomFactor); - - // Get mouse position relative to the container - let mouseX = e.clientX; - let mouseY = e.clientY; - - // Try to get the container bounds to make coordinates relative to the graph container - const target = e.currentTarget; - if (target && "getBoundingClientRect" in target) { - const rect = target.getBoundingClientRect(); - mouseX = e.clientX - rect.left; - mouseY = e.clientY - rect.top; - } - - // Calculate the world position of the clicked point - const worldX = (mouseX - panX) / zoom; - const worldY = (mouseY - panY) / zoom; - - // Calculate new pan to keep the clicked point in the same screen position - const newPanX = mouseX - worldX * newZoom; - const newPanY = mouseY - worldY * newZoom; - - setZoom(newZoom); - setPanX(newPanX); - setPanY(newPanY); - }, - [zoom, panX, panY], - ); - - return { - // State - panX, - panY, - zoom, - hoveredNode, - selectedNode, - draggingNodeId, - nodePositions, - // Handlers - handlePanStart, - handlePanMove, - handlePanEnd, - handleWheel, - handleNodeHover, - handleNodeClick, - handleNodeDragStart, - handleNodeDragMove, - handleNodeDragEnd, - handleDoubleClick, - // Touch handlers - handleTouchStart, - handleTouchMove, - handleTouchEnd, - // Controls - zoomIn, - zoomOut, - resetView, - autoFitToViewport, - centerViewportOn, - setSelectedNode, - }; -} diff --git a/packages/ui/memory-graph/index.ts b/packages/ui/memory-graph/index.ts deleted file mode 100644 index ddc3bec1d..000000000 --- a/packages/ui/memory-graph/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Components - -// Types and constants -export { - colors, - GRAPH_SETTINGS, - LAYOUT_CONSTANTS, - POSITIONING, -} from "./constants"; -export { GraphWebGLCanvas as GraphCanvas } from "./graph-webgl-canvas"; -// Hooks -export { useGraphData } from "./hooks/use-graph-data"; -export { useGraphInteractions } from "./hooks/use-graph-interactions"; -export { Legend } from "./legend"; -export { LoadingIndicator } from "./loading-indicator"; -export { MemoryGraph } from "./memory-graph"; -export { NodeDetailPanel } from "./node-detail-panel"; -export { SpacesDropdown } from "./spaces-dropdown"; -export * from "./types"; diff --git a/packages/ui/memory-graph/legend.tsx b/packages/ui/memory-graph/legend.tsx deleted file mode 100644 index db2495cc2..000000000 --- a/packages/ui/memory-graph/legend.tsx +++ /dev/null @@ -1,311 +0,0 @@ -"use client"; - -import { useIsMobile } from "@hooks/use-mobile"; -import { cn } from "@repo/lib/utils"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@repo/ui/components/collapsible"; -import { GlassMenuEffect } from "@repo/ui/other/glass-effect"; -import { Brain, ChevronDown, ChevronUp, FileText } from "lucide-react"; -import { memo, useEffect, useState } from "react"; -import { colors } from "./constants"; -import type { GraphEdge, GraphNode, LegendProps } from "./types"; - -// Cookie utility functions for legend state -const setCookie = (name: string, value: string, days = 365) => { - if (typeof document === "undefined") return; - const expires = new Date(); - expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000); - document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`; -}; - -const getCookie = (name: string): string | null => { - if (typeof document === "undefined") return null; - const nameEQ = `${name}=`; - const ca = document.cookie.split(";"); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - if (!c) continue; - while (c.charAt(0) === " ") c = c.substring(1, c.length); - if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); - } - return null; -}; - -interface ExtendedLegendProps extends LegendProps { - id?: string; - nodes?: GraphNode[]; - edges?: GraphEdge[]; - isLoading?: boolean; -} - -export const Legend = memo(function Legend({ - variant = "console", - id, - nodes = [], - edges = [], - isLoading = false, -}: ExtendedLegendProps) { - const isMobile = useIsMobile(); - const [isExpanded, setIsExpanded] = useState(true); - const [isInitialized, setIsInitialized] = useState(false); - - // Load saved preference on client side - useEffect(() => { - if (!isInitialized) { - const savedState = getCookie("legendCollapsed"); - if (savedState === "true") { - setIsExpanded(false); - } else if (savedState === "false") { - setIsExpanded(true); - } else { - // Default: collapsed on mobile, expanded on desktop - setIsExpanded(!isMobile); - } - setIsInitialized(true); - } - }, [isInitialized, isMobile]); - - // Save to cookie when state changes - const handleToggleExpanded = (expanded: boolean) => { - setIsExpanded(expanded); - setCookie("legendCollapsed", expanded ? "false" : "true"); - }; - - // Use explicit classes that Tailwind can detect - const getPositioningClasses = () => { - if (variant === "console") { - // Both desktop and mobile use same positioning for console - return "bottom-4 right-4"; - } - if (variant === "consumer") { - return isMobile ? "bottom-48 left-4" : "top-18 right-4"; - } - return ""; - }; - - const getMobileSize = () => { - if (!isMobile) return ""; - return isExpanded ? "max-w-xs" : "w-16 h-12"; - }; - - const hexagonClipPath = - "polygon(50% 0%, 93% 25%, 93% 75%, 50% 100%, 7% 75%, 7% 25%)"; - - // Calculate stats - const memoryCount = nodes.filter((n) => n.type === "memory").length; - const documentCount = nodes.filter((n) => n.type === "document").length; - - return ( -
- - {/* Glass effect background */} - - -
- {/* Mobile and Desktop collapsed state */} - {!isExpanded && ( - -
-
?
- -
-
- )} - - {/* Expanded state */} - {isExpanded && ( - <> - {/* Header with toggle */} -
-
Legend
- - - -
- - -
- {/* Stats Section */} - {!isLoading && ( -
-
- Statistics -
-
-
- - - {memoryCount} memories - -
-
- - - {documentCount} documents - -
-
-
- - {edges.length} connections - -
-
-
- )} - - {/* Node Types */} -
-
- Nodes -
-
-
-
- Document -
-
-
- Memory (latest) -
-
-
- Memory (older) -
-
-
- - {/* Status Indicators */} -
-
- Status -
-
-
-
-
- ✕ -
-
- Forgotten -
-
-
- Expiring soon -
-
-
-
-
- New memory -
-
-
- - {/* Connection Types */} -
-
- Connections -
-
-
-
- Doc → Memory -
-
-
- Doc similarity -
-
-
- - {/* Relation Types */} -
-
- Relations -
-
- {[ - ["updates", colors.relations.updates], - ["extends", colors.relations.extends], - ["derives", colors.relations.derives], - ].map(([label, color]) => ( -
-
- - {label} - -
- ))} -
-
- - {/* Similarity Strength */} -
-
- Similarity -
-
-
-
- Weak -
-
-
- Strong -
-
-
-
- - - )} -
- -
- ); -}); - -Legend.displayName = "Legend"; diff --git a/packages/ui/memory-graph/loading-indicator.tsx b/packages/ui/memory-graph/loading-indicator.tsx deleted file mode 100644 index f4a1930a4..000000000 --- a/packages/ui/memory-graph/loading-indicator.tsx +++ /dev/null @@ -1,44 +0,0 @@ -"use client"; - -import { cn } from "@repo/lib/utils"; -import { GlassMenuEffect } from "@repo/ui/other/glass-effect"; -import { Sparkles } from "lucide-react"; -import { memo } from "react"; -import type { LoadingIndicatorProps } from "./types"; - -export const LoadingIndicator = memo( - ({ isLoading, isLoadingMore, totalLoaded, variant = "console" }) => { - // Use explicit classes that Tailwind can detect - const getPositioningClasses = () => { - // Both variants use the same positioning for loadingIndicator - return "top-20 left-4"; - }; - - if (!isLoading && !isLoadingMore) return null; - - return ( -
- {/* Glass effect background */} - - -
-
- - - {isLoading - ? "Loading memory graph..." - : `Loading more documents... (${totalLoaded})`} - -
-
-
- ); - }, -); - -LoadingIndicator.displayName = "LoadingIndicator"; diff --git a/packages/ui/memory-graph/memory-graph.tsx b/packages/ui/memory-graph/memory-graph.tsx deleted file mode 100644 index 8c1ad3c27..000000000 --- a/packages/ui/memory-graph/memory-graph.tsx +++ /dev/null @@ -1,458 +0,0 @@ -"use client"; - -import { GlassMenuEffect } from "@repo/ui/other/glass-effect"; -import { AnimatePresence } from "motion/react"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { colors } from "./constants"; -import { GraphWebGLCanvas as GraphCanvas } from "./graph-webgl-canvas"; -import { useGraphData } from "./hooks/use-graph-data"; -import { useGraphInteractions } from "./hooks/use-graph-interactions"; -import { Legend } from "./legend"; -import { LoadingIndicator } from "./loading-indicator"; -import { NavigationControls } from "./navigation-controls"; -import { NodeDetailPanel } from "./node-detail-panel"; -import { SpacesDropdown } from "./spaces-dropdown"; - -import type { MemoryGraphProps } from "./types"; - -export const MemoryGraph = ({ - children, - documents, - isLoading, - isLoadingMore, - error, - totalLoaded, - hasMore, - loadMoreDocuments, - showSpacesSelector, - variant = "console", - legendId, - highlightDocumentIds = [], - highlightsVisible = true, - occludedRightPx = 0, - autoLoadOnViewport = true, -}: MemoryGraphProps) => { - // Derive showSpacesSelector from variant if not explicitly provided - // console variant shows spaces selector, consumer variant hides it - const finalShowSpacesSelector = showSpacesSelector ?? (variant === "console"); - - const [selectedSpace, setSelectedSpace] = useState("all"); - const [containerSize, setContainerSize] = useState({ width: 0, height: 0 }); - const containerRef = useRef(null); - - // Create data object with dummy pagination to satisfy type requirements - const data = useMemo(() => { - return documents && documents.length > 0 - ? { - documents, - pagination: { - currentPage: 1, - limit: documents.length, - totalItems: documents.length, - totalPages: 1, - }, - } - : null; - }, [documents]); - - // Graph interactions with variant-specific settings - const { - panX, - panY, - zoom, - /** hoveredNode currently unused within this component */ - hoveredNode: _hoveredNode, - selectedNode, - draggingNodeId, - nodePositions, - handlePanStart, - handlePanMove, - handlePanEnd, - handleWheel, - handleNodeHover, - handleNodeClick, - handleNodeDragStart, - handleNodeDragMove, - handleNodeDragEnd, - handleDoubleClick, - handleTouchStart, - handleTouchMove, - handleTouchEnd, - setSelectedNode, - autoFitToViewport, - centerViewportOn, - zoomIn, - zoomOut, - } = useGraphInteractions(variant); - - // Graph data - const { nodes, edges } = useGraphData( - data, - selectedSpace, - nodePositions, - draggingNodeId, - ); - - // Auto-fit once per unique highlight set to show the full graph for context - const lastFittedHighlightKeyRef = useRef(""); - useEffect(() => { - const highlightKey = highlightsVisible - ? highlightDocumentIds.join("|") - : ""; - if ( - highlightKey && - highlightKey !== lastFittedHighlightKeyRef.current && - containerSize.width > 0 && - containerSize.height > 0 && - nodes.length > 0 - ) { - autoFitToViewport(nodes, containerSize.width, containerSize.height, { - occludedRightPx, - animate: true, - }); - lastFittedHighlightKeyRef.current = highlightKey; - } - }, [ - highlightsVisible, - highlightDocumentIds, - containerSize.width, - containerSize.height, - nodes.length, - occludedRightPx, - autoFitToViewport, - ]); - - // Auto-fit graph when component mounts or nodes change significantly - const hasAutoFittedRef = useRef(false); - useEffect(() => { - // Only auto-fit once when we have nodes and container size - if ( - !hasAutoFittedRef.current && - nodes.length > 0 && - containerSize.width > 0 && - containerSize.height > 0 - ) { - // Auto-fit to show all content for both variants - // Add a small delay to ensure the canvas is fully initialized - const timer = setTimeout(() => { - autoFitToViewport(nodes, containerSize.width, containerSize.height); - hasAutoFittedRef.current = true; - }, 100); - - return () => clearTimeout(timer); - } - }, [ - nodes, - containerSize.width, - containerSize.height, - autoFitToViewport, - ]); - - // Reset auto-fit flag when nodes array becomes empty (switching views) - useEffect(() => { - if (nodes.length === 0) { - hasAutoFittedRef.current = false; - } - }, [nodes.length]); - - // Extract unique spaces from memories and calculate counts - const { availableSpaces, spaceMemoryCounts } = useMemo(() => { - if (!data?.documents) return { availableSpaces: [], spaceMemoryCounts: {} }; - - const spaceSet = new Set(); - const counts: Record = {}; - - data.documents.forEach((doc) => { - doc.memoryEntries.forEach((memory) => { - const spaceId = memory.spaceContainerTag || memory.spaceId || "default"; - spaceSet.add(spaceId); - counts[spaceId] = (counts[spaceId] || 0) + 1; - }); - }); - - return { - availableSpaces: Array.from(spaceSet).sort(), - spaceMemoryCounts: counts, - }; - }, [data]); - - // Handle container resize - useEffect(() => { - const updateSize = () => { - if (containerRef.current) { - const newWidth = containerRef.current.clientWidth; - const newHeight = containerRef.current.clientHeight; - - // Only update if size actually changed and is valid - setContainerSize((prev) => { - if (prev.width !== newWidth || prev.height !== newHeight) { - return { width: newWidth, height: newHeight }; - } - return prev; - }); - } - }; - - // Use a slight delay to ensure DOM is fully rendered - const timer = setTimeout(updateSize, 0); - updateSize(); // Also call immediately - - window.addEventListener("resize", updateSize); - - // Use ResizeObserver for more accurate container size detection - const resizeObserver = new ResizeObserver(updateSize); - if (containerRef.current) { - resizeObserver.observe(containerRef.current); - } - - return () => { - clearTimeout(timer); - window.removeEventListener("resize", updateSize); - resizeObserver.disconnect(); - }; - }, []); - - // Enhanced node drag start that includes nodes data - const handleNodeDragStartWithNodes = useCallback( - (nodeId: string, e: React.MouseEvent) => { - handleNodeDragStart(nodeId, e, nodes); - }, - [handleNodeDragStart, nodes], - ); - - // Navigation callbacks - const handleCenter = useCallback(() => { - if (nodes.length > 0) { - // Calculate center of all nodes - let sumX = 0 - let sumY = 0 - let count = 0 - - nodes.forEach((node) => { - sumX += node.x - sumY += node.y - count++ - }) - - if (count > 0) { - const centerX = sumX / count - const centerY = sumY / count - centerViewportOn(centerX, centerY, containerSize.width, containerSize.height) - } - } - }, [nodes, centerViewportOn, containerSize.width, containerSize.height]) - - const handleAutoFit = useCallback(() => { - if (nodes.length > 0 && containerSize.width > 0 && containerSize.height > 0) { - autoFitToViewport(nodes, containerSize.width, containerSize.height, { - occludedRightPx, - animate: true, - }) - } - }, [nodes, containerSize.width, containerSize.height, occludedRightPx, autoFitToViewport]) - - // Get selected node data - const selectedNodeData = useMemo(() => { - if (!selectedNode) return null; - return nodes.find((n) => n.id === selectedNode) || null; - }, [selectedNode, nodes]); - - // Viewport-based loading: load more when most documents are visible (optional) - const checkAndLoadMore = useCallback(() => { - if ( - isLoadingMore || - !hasMore || - !data?.documents || - data.documents.length === 0 - ) - return; - - // Calculate viewport bounds - const viewportBounds = { - left: -panX / zoom - 200, - right: (-panX + containerSize.width) / zoom + 200, - top: -panY / zoom - 200, - bottom: (-panY + containerSize.height) / zoom + 200, - }; - - // Count visible documents - const visibleDocuments = data.documents.filter((doc) => { - const docNodes = nodes.filter( - (node) => node.type === "document" && node.data.id === doc.id, - ); - return docNodes.some( - (node) => - node.x >= viewportBounds.left && - node.x <= viewportBounds.right && - node.y >= viewportBounds.top && - node.y <= viewportBounds.bottom, - ); - }); - - // If 80% or more of documents are visible, load more - const visibilityRatio = visibleDocuments.length / data.documents.length; - if (visibilityRatio >= 0.8) { - loadMoreDocuments(); - } - }, [ - isLoadingMore, - hasMore, - data, - panX, - panY, - zoom, - containerSize.width, - containerSize.height, - nodes, - loadMoreDocuments, - ]); - - // Throttled version to avoid excessive checks - const lastLoadCheckRef = useRef(0); - const throttledCheckAndLoadMore = useCallback(() => { - const now = Date.now(); - if (now - lastLoadCheckRef.current > 1000) { - // Check at most once per second - lastLoadCheckRef.current = now; - checkAndLoadMore(); - } - }, [checkAndLoadMore]); - - // Monitor viewport changes to trigger loading - useEffect(() => { - if (!autoLoadOnViewport) return; - throttledCheckAndLoadMore(); - }, [throttledCheckAndLoadMore, autoLoadOnViewport]); - - // Initial load trigger when graph is first rendered - useEffect(() => { - if (!autoLoadOnViewport) return; - if (data?.documents && data.documents.length > 0 && hasMore) { - // Start loading more documents after initial render - setTimeout(() => { - throttledCheckAndLoadMore(); - }, 500); // Small delay to allow initial layout - } - }, [data, hasMore, throttledCheckAndLoadMore, autoLoadOnViewport]); - - if (error) { - return ( -
-
- {/* Glass effect background */} - - -
- Error loading documents: {error.message} -
-
-
- ); - } - - return ( -
- {/* Spaces selector - only shown for console */} - {finalShowSpacesSelector && availableSpaces.length > 0 && ( -
- -
- )} - - {/* Loading indicator */} - - - {/* Legend */} - - - {/* Node detail panel */} - - {selectedNodeData && ( - setSelectedNode(null)} - variant={variant} - /> - )} - - - {/* Show welcome screen when no memories exist */} - {!isLoading && - (!data || nodes.filter((n) => n.type === "document").length === 0) && ( - <>{children} - )} - - {/* Graph container */} -
- {(containerSize.width > 0 && containerSize.height > 0) && ( - - )} - - {/* Navigation controls */} - {containerSize.width > 0 && ( - zoomIn(containerSize.width / 2, containerSize.height / 2)} - onZoomOut={() => zoomOut(containerSize.width / 2, containerSize.height / 2)} - onAutoFit={handleAutoFit} - nodes={nodes} - className="absolute bottom-4 left-4" - /> - )} -
-
- ); -}; diff --git a/packages/ui/memory-graph/navigation-controls.tsx b/packages/ui/memory-graph/navigation-controls.tsx deleted file mode 100644 index b2abd67fa..000000000 --- a/packages/ui/memory-graph/navigation-controls.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client" - -import { memo } from "react" -import type { GraphNode } from "./types" - -interface NavigationControlsProps { - onCenter: () => void - onZoomIn: () => void - onZoomOut: () => void - onAutoFit: () => void - nodes: GraphNode[] - className?: string -} - -export const NavigationControls = memo(({ - onCenter, - onZoomIn, - onZoomOut, - onAutoFit, - nodes, - className = "", -}) => { - if (nodes.length === 0) { - return null - } - - return ( -
- - -
- - -
-
- ) -}) - -NavigationControls.displayName = "NavigationControls" \ No newline at end of file diff --git a/packages/ui/memory-graph/node-detail-panel.tsx b/packages/ui/memory-graph/node-detail-panel.tsx deleted file mode 100644 index 0fdc48011..000000000 --- a/packages/ui/memory-graph/node-detail-panel.tsx +++ /dev/null @@ -1,268 +0,0 @@ -"use client"; - -import { cn } from "@repo/lib/utils"; -import { Badge } from "@repo/ui/components/badge"; -import { Button } from "@repo/ui/components/button"; -import { GlassMenuEffect } from "@repo/ui/other/glass-effect"; -import { Brain, Calendar, ExternalLink, FileText, Hash, X } from "lucide-react"; -import { motion } from "motion/react"; -import { memo } from "react"; -import { - GoogleDocs, - GoogleDrive, - GoogleSheets, - GoogleSlides, - MicrosoftExcel, - MicrosoftOneNote, - MicrosoftPowerpoint, - MicrosoftWord, - NotionDoc, - OneDrive, - PDF, -} from "../assets/icons"; -import { HeadingH3Bold } from "../text/heading/heading-h3-bold"; -import type { - DocumentWithMemories, - MemoryEntry, - NodeDetailPanelProps, -} from "./types"; - -const formatDocumentType = (type: string) => { - // Special case for PDF - if (type.toLowerCase() === "pdf") return "PDF"; - - // Replace underscores with spaces and capitalize each word - return type - .split("_") - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) - .join(" "); -}; - -const getDocumentIcon = (type: string) => { - const iconProps = { className: "w-5 h-5 text-slate-300" }; - - switch (type) { - case "google_doc": - return ; - case "google_sheet": - return ; - case "google_slide": - return ; - case "google_drive": - return ; - case "notion": - case "notion_doc": - return ; - case "word": - case "microsoft_word": - return ; - case "excel": - case "microsoft_excel": - return ; - case "powerpoint": - case "microsoft_powerpoint": - return ; - case "onenote": - case "microsoft_onenote": - return ; - case "onedrive": - return ; - case "pdf": - return ; - default: - return ; - } -}; - -export const NodeDetailPanel = memo( - ({ node, onClose, variant = "console" }) => { - // Use explicit classes that Tailwind can detect - const getPositioningClasses = () => { - // Both variants use the same positioning for nodeDetail - return "top-4 right-4"; - }; - - if (!node) return null; - - const isDocument = node.type === "document"; - const data = node.data; - - return ( - - {/* Glass effect background */} - - - -
-
- {isDocument ? ( - getDocumentIcon((data as DocumentWithMemories).type) - ) : ( - - )} - - {isDocument ? "Document" : "Memory"} - -
- - - -
- -
- {isDocument ? ( - <> -
- - Title - -

- {(data as DocumentWithMemories).title || - "Untitled Document"} -

-
- - {(data as DocumentWithMemories).summary && ( -
- - Summary - -

- {(data as DocumentWithMemories).summary} -

-
- )} - -
- - Type - -

- {formatDocumentType((data as DocumentWithMemories).type)} -

-
- -
- - Memory Count - -

- {(data as DocumentWithMemories).memoryEntries.length}{" "} - memories -

-
- - {((data as DocumentWithMemories).url || - (data as DocumentWithMemories).customId) && ( - - )} - - ) : ( - <> -
- - Memory - -

- {(data as MemoryEntry).memory} -

- {(data as MemoryEntry).isForgotten && ( - - Forgotten - - )} - {(data as MemoryEntry).forgetAfter && ( -

- Expires:{" "} - {(data as MemoryEntry).forgetAfter - ? new Date( - (data as MemoryEntry).forgetAfter!, - ).toLocaleDateString() - : ""}{" "} - {"forgetReason" in data && - data.forgetReason && - `- ${data.forgetReason}`} -

- )} -
- -
- - Space - -

- {(data as MemoryEntry).spaceId || "Default"} -

-
- - )} - -
-
- - - {new Date(data.createdAt).toLocaleDateString()} - - - - {node.id} - -
-
-
-
-
- ); - }, -); - -NodeDetailPanel.displayName = "NodeDetailPanel"; diff --git a/packages/ui/memory-graph/spaces-dropdown.tsx b/packages/ui/memory-graph/spaces-dropdown.tsx deleted file mode 100644 index 72d5f2610..000000000 --- a/packages/ui/memory-graph/spaces-dropdown.tsx +++ /dev/null @@ -1,120 +0,0 @@ -"use client"; - -import { cn } from "@repo/lib/utils"; -import { Badge } from "@repo/ui/components/badge"; -import { ChevronDown, Eye } from "lucide-react"; -import { memo, useEffect, useRef, useState } from "react"; -import type { SpacesDropdownProps } from "./types"; - -export const SpacesDropdown = memo( - ({ selectedSpace, availableSpaces, spaceMemoryCounts, onSpaceChange }) => { - const [isOpen, setIsOpen] = useState(false); - const dropdownRef = useRef(null); - - // Close dropdown when clicking outside - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(event.target as Node) - ) { - setIsOpen(false); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - return () => - document.removeEventListener("mousedown", handleClickOutside); - }, []); - - const totalMemories = Object.values(spaceMemoryCounts).reduce( - (sum, count) => sum + count, - 0, - ); - - return ( -
- - - {isOpen && ( -
-
- - {availableSpaces.map((space) => ( - - ))} -
-
- )} -
- ); - }, -); - -SpacesDropdown.displayName = "SpacesDropdown"; diff --git a/packages/ui/memory-graph/types.ts b/packages/ui/memory-graph/types.ts deleted file mode 100644 index a939c6194..000000000 --- a/packages/ui/memory-graph/types.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"; -import type { z } from "zod"; - -export type DocumentsResponse = z.infer< - typeof DocumentsWithMemoriesResponseSchema ->; -export type DocumentWithMemories = DocumentsResponse["documents"][0]; -export type MemoryEntry = DocumentWithMemories["memoryEntries"][0]; - -export interface GraphNode { - id: string; - type: "document" | "memory"; - x: number; - y: number; - data: DocumentWithMemories | MemoryEntry; - size: number; - color: string; - isHovered: boolean; - isDragging: boolean; -} - -export type MemoryRelation = "updates" | "extends" | "derives"; - -export interface GraphEdge { - id: string; - source: string; - target: string; - similarity: number; - visualProps: { - opacity: number; - thickness: number; - glow: number; - pulseDuration: number; - }; - color: string; - edgeType: "doc-memory" | "doc-doc" | "version"; - relationType?: MemoryRelation; -} - -export interface SpacesDropdownProps { - selectedSpace: string; - availableSpaces: string[]; - spaceMemoryCounts: Record; - onSpaceChange: (space: string) => void; -} - -export interface NodeDetailPanelProps { - node: GraphNode | null; - onClose: () => void; - variant?: "console" | "consumer"; -} - -export interface GraphCanvasProps { - nodes: GraphNode[]; - edges: GraphEdge[]; - panX: number; - panY: number; - zoom: number; - width: number; - height: number; - onNodeHover: (nodeId: string | null) => void; - onNodeClick: (nodeId: string) => void; - onNodeDragStart: (nodeId: string, e: React.MouseEvent) => void; - onNodeDragMove: (e: React.MouseEvent) => void; - onNodeDragEnd: () => void; - onPanStart: (e: React.MouseEvent) => void; - onPanMove: (e: React.MouseEvent) => void; - onPanEnd: () => void; - onWheel: (e: React.WheelEvent) => void; - onDoubleClick: (e: React.MouseEvent) => void; - onTouchStart?: (e: React.TouchEvent) => void; - onTouchMove?: (e: React.TouchEvent) => void; - onTouchEnd?: (e: React.TouchEvent) => void; - draggingNodeId: string | null; - // Optional list of document IDs (customId or internal id) to highlight - highlightDocumentIds?: string[]; -} - -export interface MemoryGraphProps { - children?: React.ReactNode; - documents: DocumentWithMemories[]; - isLoading: boolean; - isLoadingMore: boolean; - error: Error | null; - totalLoaded: number; - hasMore: boolean; - loadMoreDocuments: () => Promise; - // App-specific props - showSpacesSelector?: boolean; // true for console, false for consumer - variant?: "console" | "consumer"; // for different positioning and styling - legendId?: string; // Optional ID for the legend component - // Optional document highlight list (document custom IDs) - highlightDocumentIds?: string[]; - // Whether highlights are currently visible (e.g., chat open) - highlightsVisible?: boolean; - // Pixels occluded on the right side of the viewport (e.g., chat panel) - occludedRightPx?: number; - // Whether to auto-load more documents based on viewport visibility - autoLoadOnViewport?: boolean; -} - -export interface LegendProps { - variant?: "console" | "consumer"; - nodes?: GraphNode[]; - edges?: GraphEdge[]; - isLoading?: boolean; - hoveredNode?: string | null; -} - -export interface LoadingIndicatorProps { - isLoading: boolean; - isLoadingMore: boolean; - totalLoaded: number; - variant?: "console" | "consumer"; -} - -export interface ControlsProps { - onZoomIn: () => void; - onZoomOut: () => void; - onResetView: () => void; - variant?: "console" | "consumer"; -} From 1b9b3012e37284d67d9061c6a13dd53cfeb7463f Mon Sep 17 00:00:00 2001 From: nexxeln <95541290+nexxeln@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:56:40 +0000 Subject: [PATCH 2/5] add docs for graph package (#603) --- apps/docs/docs.json | 12 + apps/docs/memory-graph/api-reference.mdx | 334 +++++++++++++++++++ apps/docs/memory-graph/examples.mdx | 407 +++++++++++++++++++++++ apps/docs/memory-graph/installation.mdx | 28 ++ apps/docs/memory-graph/npm.mdx | 5 + apps/docs/memory-graph/overview.mdx | 38 +++ apps/docs/memory-graph/quickstart.mdx | 207 ++++++++++++ packages/memory-graph/README.md | 372 +++------------------ 8 files changed, 1075 insertions(+), 328 deletions(-) create mode 100644 apps/docs/memory-graph/api-reference.mdx create mode 100644 apps/docs/memory-graph/examples.mdx create mode 100644 apps/docs/memory-graph/installation.mdx create mode 100644 apps/docs/memory-graph/npm.mdx create mode 100644 apps/docs/memory-graph/overview.mdx create mode 100644 apps/docs/memory-graph/quickstart.mdx diff --git a/apps/docs/docs.json b/apps/docs/docs.json index dab7caeb4..347d6df56 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -213,6 +213,18 @@ "ai-sdk/infinite-chat", "ai-sdk/npm" ] + }, + { + "group": "Memory Graph", + "icon": "network", + "pages": [ + "memory-graph/overview", + "memory-graph/installation", + "memory-graph/quickstart", + "memory-graph/api-reference", + "memory-graph/examples", + "memory-graph/npm" + ] } ] } diff --git a/apps/docs/memory-graph/api-reference.mdx b/apps/docs/memory-graph/api-reference.mdx new file mode 100644 index 000000000..92641a743 --- /dev/null +++ b/apps/docs/memory-graph/api-reference.mdx @@ -0,0 +1,334 @@ +--- +title: 'API Reference' +description: 'Complete reference for Memory Graph props and types' +--- + +## Component Props + +### MemoryGraph + +The main graph component. + +#### Core Props + + + Array of documents to display in the graph. Each document must include its memory entries. + + + + Shows a loading indicator when true. + + + + Error object to display. Shows an error message overlay when set. + + + + Visual variant: + - `console`: Full-featured dashboard view (0.8x zoom, space selector visible) + - `consumer`: Embedded widget view (0.5x zoom, space selector hidden) + + + + Content to render when no documents exist. Useful for empty states. + + +#### Pagination Props + + + Shows a subtle indicator when loading additional documents. + + + + Whether more documents are available to load. + + + + Total number of documents currently loaded. Shown in loading indicator. + + + + Callback to load more documents. Called automatically when viewport shows most documents. + + + + Automatically load more documents when 80% are visible in viewport. + + +#### Display Props + + + Show or hide the space filter dropdown. Defaults to `true` for console variant, `false` for consumer. + + + + Array of document IDs to highlight with a pulsing outline. Accepts both `customId` and internal `id`. + + + + Controls whether highlights are shown. Useful for toggling highlights without changing the array. + + + + Pixels occluded on the right side (e.g., by a sidebar). Graph auto-fits accounting for this space. + + + + Custom ID for the legend component. Useful for testing or styling. + + +#### Controlled State Props + + + Currently selected space. When provided, makes space selection controlled. Use `"all"` for all spaces. + + + + Callback when space selection changes. Required when using `selectedSpace`. + + + + Maximum memories to show per document when a specific space is selected. Only applies when `selectedSpace !== "all"`. + + + + Enable experimental features. Currently unused but reserved for future features. + + +## Data Types + +### DocumentWithMemories + +```typescript +interface DocumentWithMemories { + id: string; + customId?: string | null; + contentHash: string | null; + orgId: string; + userId: string; + connectionId?: string | null; + title?: string | null; + content?: string | null; + summary?: string | null; + url?: string | null; + source?: string | null; + type?: string | null; + status: 'pending' | 'processing' | 'done' | 'failed'; + metadata?: Record | null; + processingMetadata?: Record | null; + raw?: string | null; + tokenCount?: number | null; + wordCount?: number | null; + chunkCount?: number | null; + averageChunkSize?: number | null; + summaryEmbedding?: number[] | null; + summaryEmbeddingModel?: string | null; + createdAt: string | Date; + updatedAt: string | Date; + memoryEntries: MemoryEntry[]; +} +``` + +### MemoryEntry + +```typescript +interface MemoryEntry { + id: string; + customId?: string | null; + documentId: string; + content: string | null; + summary?: string | null; + title?: string | null; + url?: string | null; + type?: string | null; + metadata?: Record | null; + embedding?: number[] | null; + embeddingModel?: string | null; + tokenCount?: number | null; + createdAt: string | Date; + updatedAt: string | Date; + + // Fields from join relationship + sourceAddedAt?: Date | null; + sourceRelevanceScore?: number | null; + sourceMetadata?: Record | null; + spaceContainerTag?: string | null; + + // Version chain fields + updatesMemoryId?: string | null; + nextVersionId?: string | null; + relation?: 'updates' | 'extends' | 'derives' | null; + + // Memory status fields + isForgotten?: boolean; + forgetAfter?: Date | string | null; + isLatest?: boolean; + + // Space/container fields + spaceId?: string | null; + + // Legacy fields (for backwards compatibility) + memory?: string | null; + memoryRelations?: Array<{ + relationType: 'updates' | 'extends' | 'derives'; + targetMemoryId: string; + }> | null; + parentMemoryId?: string | null; +} +``` + +### GraphNode + +Internal type for rendered nodes: + +```typescript +interface GraphNode { + id: string; + type: 'document' | 'memory'; + x: number; + y: number; + data: DocumentWithMemories | MemoryEntry; + size: number; + color: string; + isHovered: boolean; + isDragging: boolean; +} +``` + +### GraphEdge + +Internal type for connections: + +```typescript +interface GraphEdge { + id: string; + source: string; + target: string; + similarity: number; + edgeType: 'doc-memory' | 'doc-doc' | 'version'; + relationType?: 'updates' | 'extends' | 'derives'; + color: string; + visualProps: { + opacity: number; + thickness: number; + glow: number; + pulseDuration: number; + }; +} +``` + +## Exported Components + +Besides `MemoryGraph`, the package exports individual components for advanced use cases: + +### GraphCanvas + +Low-level canvas renderer. Not recommended for direct use. + +```typescript +import { GraphCanvas } from '@supermemory/memory-graph'; +``` + +### Legend + +Graph legend showing node types and counts. + +```typescript +import { Legend } from '@supermemory/memory-graph'; +``` + +### LoadingIndicator + +Loading state indicator with progress counter. + +```typescript +import { LoadingIndicator } from '@supermemory/memory-graph'; +``` + +### NodeDetailPanel + +Side panel showing node details when clicked. + +```typescript +import { NodeDetailPanel } from '@supermemory/memory-graph'; +``` + +### SpacesDropdown + +Space filter dropdown. + +```typescript +import { SpacesDropdown } from '@supermemory/memory-graph'; +``` + +## Exported Hooks + +### useGraphData + +Processes documents into graph nodes and edges. + +```typescript +import { useGraphData } from '@supermemory/memory-graph'; + +const { nodes, edges } = useGraphData( + data, + selectedSpace, + nodePositions, + draggingNodeId, + memoryLimit +); +``` + +### useGraphInteractions + +Handles pan, zoom, and node interactions. + +```typescript +import { useGraphInteractions } from '@supermemory/memory-graph'; + +const { + panX, + panY, + zoom, + selectedNode, + handlePanStart, + handleWheel, + // ... more interaction handlers +} = useGraphInteractions('console'); +``` + +## Constants + +### colors + +Color palette used throughout the graph: + +```typescript +import { colors } from '@supermemory/memory-graph'; + +colors.document.primary; // Document fill color +colors.memory.primary; // Memory fill color +colors.connection.strong; // Strong edge color +``` + +### GRAPH_SETTINGS + +Initial zoom and pan settings for variants: + +```typescript +import { GRAPH_SETTINGS } from '@supermemory/memory-graph'; + +GRAPH_SETTINGS.console.initialZoom; // 0.8 +GRAPH_SETTINGS.consumer.initialZoom; // 0.5 +``` + +### LAYOUT_CONSTANTS + +Spatial layout configuration: + +```typescript +import { LAYOUT_CONSTANTS } from '@supermemory/memory-graph'; + +LAYOUT_CONSTANTS.clusterRadius; // Memory orbit radius +LAYOUT_CONSTANTS.documentSpacing; // Distance between documents +``` diff --git a/apps/docs/memory-graph/examples.mdx b/apps/docs/memory-graph/examples.mdx new file mode 100644 index 000000000..14d615d53 --- /dev/null +++ b/apps/docs/memory-graph/examples.mdx @@ -0,0 +1,407 @@ +--- +title: 'Examples' +description: 'Common use cases and implementation patterns' +--- + +## With Pagination + +Load documents in chunks for better performance with large datasets. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; +import { useCallback, useEffect, useState } from 'react'; + +export default function PaginatedGraph() { + const [documents, setDocuments] = useState([]); + const [page, setPage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [isLoading, setIsLoading] = useState(true); + const [isLoadingMore, setIsLoadingMore] = useState(false); + + // Initial load + useEffect(() => { + fetchPage(1, false); + }, []); + + const fetchPage = async (pageNum: number, append: boolean) => { + if (pageNum === 1) { + setIsLoading(true); + } else { + setIsLoadingMore(true); + } + + const res = await fetch(`/api/graph?page=${pageNum}&limit=100`); + const data = await res.json(); + + if (append) { + setDocuments(prev => [...prev, ...data.documents]); + } else { + setDocuments(data.documents); + } + + setHasMore(data.pagination.currentPage < data.pagination.totalPages); + setIsLoading(false); + setIsLoadingMore(false); + }; + + const loadMore = useCallback(async () => { + if (!isLoadingMore && hasMore) { + const nextPage = page + 1; + setPage(nextPage); + await fetchPage(nextPage, true); + } + }, [page, hasMore, isLoadingMore]); + + return ( +
+ +
+ ); +} +``` + +## Highlighting Search Results + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState } from 'react'; + +export default function SearchableGraph() { + const [documents, setDocuments] = useState([]); + const [searchResults, setSearchResults] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + + const handleSearch = async (query: string) => { + setSearchQuery(query); + + if (!query) { + setSearchResults([]); + return; + } + + const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`); + const data = await res.json(); + + // Extract document IDs from search results + const docIds = data.results.map(r => r.documentId); + setSearchResults(docIds); + }; + + return ( +
+
+ handleSearch(e.target.value)} + style={{ + padding: '8px 12px', + borderRadius: 8, + border: '1px solid #333', + background: '#1a1a1a', + color: 'white', + }} + /> +
+ + 0} + /> +
+ ); +} +``` + +## Controlled Space Selection + +Control space filtering from outside the component. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState } from 'react'; + +export default function ControlledSpaceGraph() { + const [documents, setDocuments] = useState([]); + const [selectedSpace, setSelectedSpace] = useState('all'); + + // Extract available spaces from documents + const spaces = Array.from( + new Set( + documents.flatMap(doc => + doc.memoryEntries.map(m => m.spaceId || 'default') + ) + ) + ); + + return ( +
+
+

Filters

+ + + + +
+ + +
+ ); +} +``` + +## Embedded Widget + +Use the consumer variant for embedded views with custom styling. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; + +export default function EmbeddedGraph({ documents }) { + return ( +
+ +
+

No memories to display

+
+
+
+ ); +} +``` + +## With Loading States + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useEffect, useState } from 'react'; + +export default function LoadingGraph() { + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetch('/api/graph') + .then(res => { + if (!res.ok) throw new Error('Failed to load graph'); + return res.json(); + }) + .then(data => { + setDocuments(data.documents); + setIsLoading(false); + }) + .catch(err => { + setError(err); + setIsLoading(false); + }); + }, []); + + return ( +
+ +
+
+

Welcome to your Memory Graph

+

Add some content to get started

+ +
+
+
+
+ ); +} +``` + +## React Server Component + +```tsx +// Next.js App Router with Server Component +import { MemoryGraphClient } from './memory-graph-client'; + +async function getGraphData() { + const res = await fetch('https://api.supermemory.ai/v3/documents/documents', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + page: 1, + limit: 500, + sort: 'createdAt', + order: 'desc', + }), + cache: 'no-store', // or use revalidation + }); + + return res.json(); +} + +export default async function GraphPage() { + const data = await getGraphData(); + + return ; +} +``` + +```tsx +// memory-graph-client.tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; + +interface Props { + initialDocuments: DocumentWithMemories[]; +} + +export function MemoryGraphClient({ initialDocuments }: Props) { + return ( +
+ +
+ ); +} +``` + +## Mobile-Responsive Layout + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState, useEffect } from 'react'; + +export default function ResponsiveGraph({ documents }) { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 768); + }; + + checkMobile(); + window.addEventListener('resize', checkMobile); + return () => window.removeEventListener('resize', checkMobile); + }, []); + + return ( +
+ +
+ ); +} +``` diff --git a/apps/docs/memory-graph/installation.mdx b/apps/docs/memory-graph/installation.mdx new file mode 100644 index 000000000..0051825f9 --- /dev/null +++ b/apps/docs/memory-graph/installation.mdx @@ -0,0 +1,28 @@ +--- +title: 'Installation' +description: 'Install and set up the Memory Graph component' +--- + +## Installation + +Install the package using your preferred package manager: + +```bash npm +npm install @supermemory/memory-graph +``` + +## Requirements + +- **React**: 18.0.0 or higher +- **react-dom**: 18.0.0 or higher + +## Next Steps + + + + Get the graph running with real data + + + Explore all available props and types + + diff --git a/apps/docs/memory-graph/npm.mdx b/apps/docs/memory-graph/npm.mdx new file mode 100644 index 000000000..731851784 --- /dev/null +++ b/apps/docs/memory-graph/npm.mdx @@ -0,0 +1,5 @@ +--- +title: "NPM link" +url: "https://www.npmjs.com/package/@supermemory/memory-graph" +icon: npm +--- diff --git a/apps/docs/memory-graph/overview.mdx b/apps/docs/memory-graph/overview.mdx new file mode 100644 index 000000000..c3260d21d --- /dev/null +++ b/apps/docs/memory-graph/overview.mdx @@ -0,0 +1,38 @@ +--- +title: 'Overview' +description: 'Interactive visualization for documents, memories and connections' +--- + +## What is Memory Graph? + +Memory Graph is a React component that visualizes your Supermemory documents and memories as an interactive network. Documents appear as rectangular nodes, memories as hexagonal nodes, and connections between them show relationships and similarity. + +The graph renders using Canvas 2D, providing smooth interactions with hundreds of nodes through pan, zoom, and drag operations. + +## When to Use It + +Use Memory Graph when you need to: + +- **Visualize knowledge graphs** - Show how documents and memories connect +- **Navigate memory spaces** - Filter and browse by workspace or tag +- **Create memory browsers** - Give users a visual overview of their stored content + +## Performance + +The graph handles hundreds of nodes efficiently through: +- Canvas-based rendering (not DOM elements) +- Viewport culling (only draws visible nodes) +- Level-of-detail optimization (simplifies rendering when zoomed out) +- Change-based rendering (only redraws when state changes) +- Throttled viewport calculations + +For very large datasets (1000+ documents), use pagination to load data in chunks. + +## Browser Support + +Works in all modern browsers that support: +- Canvas 2D API +- ES2020 JavaScript +- CSS custom properties + +Tested on Chrome, Firefox, Safari, and Edge (latest versions). diff --git a/apps/docs/memory-graph/quickstart.mdx b/apps/docs/memory-graph/quickstart.mdx new file mode 100644 index 000000000..d05a09250 --- /dev/null +++ b/apps/docs/memory-graph/quickstart.mdx @@ -0,0 +1,207 @@ +--- +title: 'Quick Start' +description: 'Get Memory Graph running in 2 minutes' +--- + +## Basic Setup + +Here's a minimal example to get the graph running: + +```tsx +'use client'; // For Next.js App Router + +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; +import { useEffect, useState } from 'react'; + +export default function GraphPage() { + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetch('/api/graph') + .then(res => res.json()) + .then(data => { + setDocuments(data.documents); + setIsLoading(false); + }) + .catch(err => { + setError(err); + setIsLoading(false); + }); + }, []); + + return ( +
+ +
+ ); +} +``` + +## Backend API Route + +Create an API route to fetch documents from Supermemory: + + + +```typescript Next.js App Router +// app/api/graph/route.ts +import { NextResponse } from 'next/server'; + +export async function GET() { + const response = await fetch('https://api.supermemory.ai/v3/documents/documents', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, + }, + body: JSON.stringify({ + page: 1, + limit: 500, + sort: 'createdAt', + order: 'desc', + }), + }); + + const data = await response.json(); + return NextResponse.json(data); +} +``` + +```typescript Next.js Pages Router +// pages/api/graph.ts +import type { NextApiRequest, NextApiResponse } from 'next'; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const response = await fetch('https://api.supermemory.ai/v3/documents/documents', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, + }, + body: JSON.stringify({ + page: 1, + limit: 500, + sort: 'createdAt', + order: 'desc', + }), + }); + + const data = await response.json(); + res.json(data); +} +``` + +```javascript Express +// routes/graph.js +app.get('/api/graph', async (req, res) => { + const response = await fetch('https://api.supermemory.ai/v3/documents/documents', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, + }, + body: JSON.stringify({ + page: 1, + limit: 500, + sort: 'createdAt', + order: 'desc', + }), + }); + + const data = await response.json(); + res.json(data); +}); +``` + + + + + Never expose your Supermemory API key to the client. Always fetch data through your backend. + + +## Environment Variables + +Add your API key to `.env.local`: + +```bash +SUPERMEMORY_API_KEY=your_api_key_here +``` + +Get your API key from the [Supermemory dashboard](https://console.supermemory.ai). + +## Common Customizations + +### Embedded Mode + +For a widget-style view, use the consumer variant: + +```tsx + +``` + +### CSS Import + +The component includes bundled styles. You don't need to import CSS separately. Styles are automatically injected when the component mounts. + +If you want explicit control, you can import the stylesheet: + +```typescript +import '@supermemory/memory-graph/styles.css'; +``` + + + The automatic CSS injection works for most setups. Only use the explicit import if you need custom control over style loading order. + + + +### Custom Empty State + +Show custom content when no documents exist: + +```tsx + +
+

No memories yet

+

Add content to see your knowledge graph

+
+
+``` + +### Hide Space Selector + +```tsx + +``` + +## Next Steps + + + + See more usage examples + + + Full API documentation + + diff --git a/packages/memory-graph/README.md b/packages/memory-graph/README.md index eae06940d..83710f5ae 100644 --- a/packages/memory-graph/README.md +++ b/packages/memory-graph/README.md @@ -1,378 +1,94 @@ # @supermemory/memory-graph -> Interactive graph visualization component for Supermemory - visualize and explore your memory connections +Interactive graph visualization for documents and their memory connections. [![npm version](https://img.shields.io/npm/v/@supermemory/memory-graph.svg)](https://www.npmjs.com/package/@supermemory/memory-graph) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -## Features - -- **WebGL-powered rendering** - Smooth performance with hundreds of nodes -- **Interactive exploration** - Pan, zoom, drag nodes, and explore connections -- **Semantic connections** - Visualizes relationships based on content similarity -- **Space filtering with search** - Dynamically search and filter by spaces/tags -- **Memory limit control** - Limit memories per document (50-3000) for performance -- **Controlled/uncontrolled modes** - Flexible state management for integration -- **Responsive design** - Works seamlessly on mobile and desktop -- **Zero configuration** - Works out of the box with automatic CSS injection -- **Lightweight** - Tree-shakeable and optimized bundle -- **TypeScript** - Full TypeScript support with exported types - ## Installation ```bash npm install @supermemory/memory-graph # or -yarn add @supermemory/memory-graph +bun add @supermemory/memory-graph # or pnpm add @supermemory/memory-graph -# or -bun add @supermemory/memory-graph ``` ## Quick Start -The component accepts document data directly - you fetch the data from your backend, which proxies requests to the Supermemory API with proper authentication. - ```tsx -import { MemoryGraph } from '@supermemory/memory-graph' -import type { DocumentWithMemories } from '@supermemory/memory-graph' +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; function App() { - const [documents, setDocuments] = useState([]) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { - // Fetch from YOUR backend (which proxies to Supermemory API) - fetch('/api/supermemory-graph') + fetch('/api/graph') .then(res => res.json()) .then(data => { - setDocuments(data.documents) - setIsLoading(false) - }) - .catch(err => { - setError(err) - setIsLoading(false) - }) - }, []) + setDocuments(data.documents); + setIsLoading(false); + }); + }, []); return ( - - ) -} -``` - -## Backend Proxy Example - -Create an API route in your backend that authenticates and proxies requests to Supermemory: - -### Next.js API Route - -```typescript -// app/api/supermemory-graph/route.ts -import { NextResponse } from 'next/server' - -export async function GET(request: Request) { - // Add your own auth check here - const user = await getAuthenticatedUser(request) - if (!user) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - } - - const response = await fetch('https://api.supermemory.ai/v3/documents/documents', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, - }, - body: JSON.stringify({ - page: 1, - limit: 500, - sort: 'createdAt', - order: 'desc', - }), - }) - - const data = await response.json() - return NextResponse.json(data) -} -``` - -## API Reference - -### Props - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `documents` | `DocumentWithMemories[]` | **required** | Array of documents to display | -| `isLoading` | `boolean` | `false` | Whether data is currently loading | -| `error` | `Error \| null` | `null` | Error that occurred during fetching | -| `variant` | `"console" \| "consumer"` | `"console"` | Visual variant | -| `showSpacesSelector` | `boolean` | Based on variant | Show/hide the spaces filter | -| `children` | `ReactNode` | - | Content to show when no documents | -| `highlightDocumentIds` | `string[]` | `[]` | Document IDs to highlight | -| `highlightsVisible` | `boolean` | `true` | Whether highlights are visible | - -### Space & Memory Control Props (Optional) - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `selectedSpace` | `string` | `"all"` | Currently selected space (controlled) | -| `onSpaceChange` | `(spaceId: string) => void` | - | Callback when space changes | -| `onSearchSpaces` | `(query: string) => Promise` | - | Async space search function | -| `memoryLimit` | `number` | `500` | Max memories per document when space selected | -| `onMemoryLimitChange` | `(limit: number) => void` | - | Callback when limit changes | -| `isExperimental` | `boolean` | `false` | Enable experimental features | - -### Pagination Props (Optional) - -For large datasets, you can implement pagination: - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `isLoadingMore` | `boolean` | `false` | Whether loading more data | -| `hasMore` | `boolean` | `false` | Whether more data is available | -| `totalLoaded` | `number` | `documents.length` | Total documents loaded | -| `loadMoreDocuments` | `() => Promise` | - | Callback to load more | - -### Types - -```typescript -import type { - DocumentWithMemories, - MemoryEntry, - DocumentsResponse, - MemoryGraphProps, - MemoryLimit, - MemoryCountSelectorProps, - GraphNode, - GraphEdge, - MemoryRelation -} from '@supermemory/memory-graph' - -// Memory limit can be one of these values -type MemoryLimit = 50 | 100 | 250 | 500 | 1000 | 2000 | 3000 -``` - -## Advanced Usage - -### With Pagination - -```tsx -import { MemoryGraph } from '@supermemory/memory-graph' - -function GraphWithPagination() { - const [documents, setDocuments] = useState([]) - const [page, setPage] = useState(1) - const [hasMore, setHasMore] = useState(true) - const [isLoadingMore, setIsLoadingMore] = useState(false) - - const loadMore = async () => { - setIsLoadingMore(true) - const res = await fetch(`/api/supermemory-graph?page=${page + 1}`) - const data = await res.json() - setDocuments(prev => [...prev, ...data.documents]) - setHasMore(data.pagination.currentPage < data.pagination.totalPages) - setPage(p => p + 1) - setIsLoadingMore(false) - } - - return ( - - ) -} -``` - -### Custom Empty State - -```tsx - -
-

No memories yet

-

Start adding content to see your knowledge graph

-
-
-``` - -### Controlled Space Selection & Memory Limiting - -Control the selected space and memory limit externally for integration with your app's state management: - -```tsx -import { MemoryGraph } from '@supermemory/memory-graph' - -function ControlledGraph() { - const [selectedSpace, setSelectedSpace] = useState("all") - const [memoryLimit, setMemoryLimit] = useState(500) - const [searchResults, setSearchResults] = useState([]) - - // Handle space search via your API - const handleSpaceSearch = async (query: string) => { - const response = await fetch(`/api/spaces/search?q=${query}`) - const spaces = await response.json() - setSearchResults(spaces) - return spaces - } - - return ( -
- {/* Display current state */} -
-

Selected Space: {selectedSpace}

-

Memory Limit: {memoryLimit}

- -
- - {/* Controlled graph */} +
- ) -} -``` - -### Uncontrolled Mode (Automatic) - -If you don't provide `selectedSpace` or `memoryLimit` props, the component manages its own state: - -```tsx - -``` - -### Space Search Integration - -Implement server-side space search for dynamic filtering: - -```tsx -// Frontend -const handleSpaceSearch = async (query: string): Promise => { - const response = await fetch('/api/spaces/search', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query }) - }) - return response.json() -} - - - -// Backend (Next.js example) -// app/api/spaces/search/route.ts -export async function POST(request: Request) { - const { query } = await request.json() - - const response = await fetch('https://api.supermemory.ai/v3/search/spaces', { - method: 'GET', - headers: { - 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, - }, - params: { q: query } - }) - - return response.json() + ); } ``` -### Variants - -The `variant` prop controls the visual layout and initial viewport settings: - -| Variant | Initial Zoom | Spaces Selector | Legend Position | Use Case | -|---------|-------------|-----------------|-----------------|----------| -| `console` | 0.8 | Shown | Bottom-right | Full-page dashboard views | -| `consumer` | 0.5 | Hidden | Top-right | Embedded/widget views | +## Features -```tsx -// Full dashboard view - +- **Interactive canvas visualization** - Pan, zoom, and drag nodes using Canvas 2D rendering +- **Document and memory nodes** - Documents as rectangles, memories as hexagons +- **Relationship visualization** - Edges show document similarity and memory version chains +- **Space filtering** - Filter by workspace or view all memories +- **Two variants** - Full-featured console mode or embedded consumer mode +- **Pagination support** - Load more documents on demand +- **TypeScript support** - Full type definitions included -// Embedded widget - -``` +## Essential Props -## Interactive Controls +| Prop | Type | Description | +|------|------|-------------| +| `documents` | `DocumentWithMemories[]` | Array of documents with their memory entries | +| `isLoading` | `boolean` | Show loading state | +| `variant` | `"console" \| "consumer"` | Display mode (default: "console") | +| `error` | `Error \| null` | Error to display | +| `loadMoreDocuments` | `() => Promise` | Function to load more data | +| `highlightDocumentIds` | `string[]` | IDs of documents to highlight | -- **Pan**: Click and drag the background -- **Zoom**: Mouse wheel or pinch on mobile -- **Select Node**: Click on any document or memory -- **Drag Nodes**: Click and drag individual nodes -- **Fit to View**: Auto-fit button to center all content -- **Space Filter**: Click the space selector to filter by space -- **Space Search**: Type in the search box and press Enter to find spaces -- **Memory Limit**: Select a limit (50-3K) when filtering by space +## Documentation -## Browser Support +Full documentation available at [docs.supermemory.ai](https://docs.supermemory.ai): -- Chrome/Edge (latest) -- Firefox (latest) -- Safari (latest) -- Mobile browsers with WebGL support +- [Overview](https://docs.supermemory.ai/memory-graph/overview) - What it is and when to use it +- [Installation](https://docs.supermemory.ai/memory-graph/installation) - Setup and requirements +- [Quick Start](https://docs.supermemory.ai/memory-graph/quickstart) - Get running in 2 minutes +- [API Reference](https://docs.supermemory.ai/memory-graph/api-reference) - Complete API documentation +- [Examples](https://docs.supermemory.ai/memory-graph/examples) - Common use cases +- [Troubleshooting](https://docs.supermemory.ai/memory-graph/troubleshooting) - Common issues ## Requirements - React 18+ -- Modern browser with WebGL support - -## Development - -```bash -# Install dependencies -bun install - -# Build the package -bun run build - -# Watch mode for development -bun run dev - -# Type checking -bun run check-types -``` +- Modern browser ## License MIT -## Support +## Links -- Issues: [GitHub Issues](https://github.com/supermemoryai/supermemory/issues) +- [GitHub](https://github.com/supermemoryai/supermemory/tree/main/packages/memory-graph) +- [Issues](https://github.com/supermemoryai/supermemory/issues) +- [Supermemory](https://supermemory.ai) From c4e67d8707ff515afaea685d6fc13d49844ca610 Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:58:30 +0000 Subject: [PATCH 3/5] chore: update new contributions for raycast extension (#561) chore: update new contributions for raycast extension add quick add from selection with extension --- apps/raycast-extension/CHANGELOG.md | 19 +- apps/raycast-extension/package-lock.json | 116 +---- apps/raycast-extension/package.json | 20 +- apps/raycast-extension/src/add-memory.tsx | 194 ++++---- apps/raycast-extension/src/api.ts | 57 ++- .../raycast-extension/src/search-memories.tsx | 432 ++++++++---------- .../raycast-extension/src/search-projects.tsx | 106 +++++ .../raycast-extension/src/withSupermemory.tsx | 48 ++ 8 files changed, 530 insertions(+), 462 deletions(-) create mode 100644 apps/raycast-extension/src/search-projects.tsx create mode 100644 apps/raycast-extension/src/withSupermemory.tsx diff --git a/apps/raycast-extension/CHANGELOG.md b/apps/raycast-extension/CHANGELOG.md index 06b6fe0e0..f8bdf596e 100644 --- a/apps/raycast-extension/CHANGELOG.md +++ b/apps/raycast-extension/CHANGELOG.md @@ -1,6 +1,19 @@ -# supermemory-raycast Changelog +# Supermemory Changelog -## [Initial Version] - {2025-09-27} +## [Quick Add from Selection] - 2025-11-05 + +- Select text anywhere and quickly add it as a memory - the content field is automatically filled +- Select text and search memories instantly - the search field is automatically filled +- Save time by selecting text before opening commands + +## [Search Projects + Enhancements] - 2025-10-13 + +- Added command to search and add projects +- Removed `useEffect` +- Simplified `getApiKey` since `Preferences` will be enforced for presence and trim automatically +- Moved API Key check into its own HoC + +## [Initial Version] - 2025-10-02 - Added Supermemory integration with Add Memory and Search Memories commands -- Added project organization support for memories \ No newline at end of file +- Added project organization support for memories diff --git a/apps/raycast-extension/package-lock.json b/apps/raycast-extension/package-lock.json index 703ef8396..323af290a 100644 --- a/apps/raycast-extension/package-lock.json +++ b/apps/raycast-extension/package-lock.json @@ -7,8 +7,8 @@ "name": "supermemory", "license": "MIT", "dependencies": { - "@raycast/api": "^1.103.2", - "@raycast/utils": "^1.17.0" + "@raycast/api": "^1.103.3", + "@raycast/utils": "^2.2.1" }, "devDependencies": { "@raycast/eslint-config": "^2.0.4", @@ -1134,18 +1134,18 @@ } }, "node_modules/@raycast/api": { - "version": "1.103.2", - "resolved": "https://registry.npmjs.org/@raycast/api/-/api-1.103.2.tgz", - "integrity": "sha512-5QTKMRv86t0cUFH9a07ne8a+ry8bZ2xtOd7trx3yiMmJREr5edYXsqcGDsOyeJLjrjH7WhoRlESIW/CHgNwg8w==", + "version": "1.103.3", + "resolved": "https://registry.npmjs.org/@raycast/api/-/api-1.103.3.tgz", + "integrity": "sha512-+lS8yOrqSP7++ZyomZnMkN0pzEZto/XOqag8MXt9SmTuJBZvfMV74f9wzXmJkRmynYxQHnpLqvs9otWrDd3Bvw==", "license": "MIT", "dependencies": { - "@oclif/core": "^4.4.1", - "@oclif/plugin-autocomplete": "^3.2.31", - "@oclif/plugin-help": "^6.2.29", - "@oclif/plugin-not-found": "^3.2.57", + "@oclif/core": "^4.5.4", + "@oclif/plugin-autocomplete": "^3.2.35", + "@oclif/plugin-help": "^6.2.33", + "@oclif/plugin-not-found": "^3.2.68", "@types/node": "22.13.10", "@types/react": "19.0.10", - "esbuild": "^0.25.5", + "esbuild": "^0.25.10", "react": "19.0.0" }, "bin": { @@ -1204,20 +1204,21 @@ } }, "node_modules/@raycast/utils": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@raycast/utils/-/utils-1.19.1.tgz", - "integrity": "sha512-/udUGcTZCgZZwzesmjBkqG5naQZTD/ZLHbqRwkWcF+W97vf9tr9raxKyQjKsdZ17OVllw2T3sHBQsVUdEmCm2g==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@raycast/utils/-/utils-2.2.1.tgz", + "integrity": "sha512-MBOD3eccHTu1HVQstoqoJJsA5PubWv18EUq8Dxwg1PEJE+xVjEuslXpsNgR/2RtpTGeKgGiXePxUiVp5mILN5w==", "license": "MIT", "dependencies": { - "cross-fetch": "^3.1.6", - "dequal": "^2.0.3", - "object-hash": "^3.0.0", - "signal-exit": "^4.0.2", - "stream-chain": "^2.2.5", - "stream-json": "^1.8.0" + "dequal": "^2.0.3" }, "peerDependencies": { - "@raycast/api": ">=1.69.0" + "@raycast/api": ">=1.99.4", + "react": ">=19.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, "node_modules/@types/estree": { @@ -1733,15 +1734,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2608,35 +2600,6 @@ "dev": true, "license": "MIT" }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2910,21 +2873,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", - "license": "BSD-3-Clause" - }, - "node_modules/stream-json": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", - "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", - "license": "BSD-3-Clause", - "dependencies": { - "stream-chain": "^2.2.5" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3037,12 +2985,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -3127,22 +3069,6 @@ "punycode": "^2.1.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/apps/raycast-extension/package.json b/apps/raycast-extension/package.json index 9481601b2..ed8215770 100644 --- a/apps/raycast-extension/package.json +++ b/apps/raycast-extension/package.json @@ -5,6 +5,10 @@ "description": "Add and search memories with your personal AI-powered knowledge base", "icon": "extension-icon.png", "author": "supermemory", + "contributors": [ + "xmok", + "maheshthedev" + ], "platforms": [ "macOS", "Windows" @@ -18,15 +22,23 @@ { "name": "add-memory", "title": "Add Memory", - "subtitle": "add memory to your supermemory app", + "subtitle": "Supermemory", "description": "Add text, URLs, or documents to your supermemory knowledge base", "mode": "view" }, { "name": "search-memories", "title": "Search Memories", + "subtitle": "Supermemory", "description": "Search through your saved memories and find relevant information", "mode": "view" + }, + { + "name": "search-projects", + "title": "Search Projects", + "subtitle": "Supermemory", + "description": "Search through your saved projects and find relevant information", + "mode": "view" } ], "preferences": [ @@ -40,8 +52,8 @@ } ], "dependencies": { - "@raycast/api": "^1.103.2", - "@raycast/utils": "^1.17.0" + "@raycast/api": "^1.103.3", + "@raycast/utils": "^2.2.1" }, "devDependencies": { "@raycast/eslint-config": "^2.0.4", @@ -59,4 +71,4 @@ "prepublishOnly": "echo \"\\n\\nIt seems like you are trying to publish the Raycast extension to npm.\\n\\nIf you did intend to publish it to npm, remove the \\`prepublishOnly\\` script and rerun \\`npm publish\\` again.\\nIf you wanted to publish it to the Raycast Store instead, use \\`npm run publish\\` instead.\\n\\n\" && exit 1", "publish": "npx @raycast/api@latest publish" } -} \ No newline at end of file +} diff --git a/apps/raycast-extension/src/add-memory.tsx b/apps/raycast-extension/src/add-memory.tsx index 87fb853f5..812c1c4a2 100644 --- a/apps/raycast-extension/src/add-memory.tsx +++ b/apps/raycast-extension/src/add-memory.tsx @@ -1,110 +1,114 @@ import { - Form, - ActionPanel, - Action, - showToast, - Toast, - useNavigation, -} from "@raycast/api"; -import { useEffect, useState } from "react"; -import { - addMemory, - fetchProjects, - checkApiConnection, - type Project, -} from "./api"; + Form, + ActionPanel, + Action, + showToast, + Toast, + useNavigation, + Icon, + getSelectedText, +} from "@raycast/api" +import { useState, useEffect } from "react" +import { addMemory, fetchProjects } from "./api" +import { usePromise } from "@raycast/utils" +import { withSupermemory } from "./withSupermemory" interface FormValues { - content: string; - project: string; + content: string + project: string } -export default function Command() { - const [projects, setProjects] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [isSubmitting, setIsSubmitting] = useState(false); - const { pop } = useNavigation(); +export default withSupermemory(Command) +function Command() { + const [isSubmitting, setIsSubmitting] = useState(false) + const [initialContent, setInitialContent] = useState("") + const { pop } = useNavigation() - useEffect(() => { - async function loadProjects() { - try { - setIsLoading(true); - const isConnected = await checkApiConnection(); - if (!isConnected) { - return; - } + const { isLoading, data: projects = [] } = usePromise(fetchProjects) - const fetchedProjects = await fetchProjects(); - setProjects(fetchedProjects); - } catch (error) { - console.error("Failed to load projects:", error); - } finally { - setIsLoading(false); - } - } + useEffect(() => { + async function loadSelectedText() { + try { + const selectedText = await getSelectedText() + if (selectedText) { + setInitialContent(selectedText) + } + } catch { + // No text selected or error getting selected text - silently fail + // User can still manually enter content + } + } - loadProjects(); - }, []); + loadSelectedText() + }, []) - async function handleSubmit(values: FormValues) { - if (!values.content.trim()) { - await showToast({ - style: Toast.Style.Failure, - title: "Content Required", - message: "Please enter some content for the memory", - }); - return; - } + async function handleSubmit(values: FormValues) { + if (!values.content.trim()) { + await showToast({ + style: Toast.Style.Failure, + title: "Content Required", + message: "Please enter some content for the memory", + }) + return + } - try { - setIsSubmitting(true); + try { + setIsSubmitting(true) - const containerTags = values.project ? [values.project] : undefined; + const containerTags = values.project ? [values.project] : undefined - await addMemory({ - content: values.content.trim(), - containerTags, - }); + await addMemory({ + content: values.content.trim(), + containerTags, + }) - pop(); - } catch (error) { - console.error("Failed to add memory:", error); - } finally { - setIsSubmitting(false); - } - } + pop() + } catch (error) { + console.error("Failed to add memory:", error) + } finally { + setIsSubmitting(false) + } + } - return ( -
- - - } - > - - - - - {projects.map((project) => ( - - ))} - - - ); + return ( +
+ + + ) + } + > + setInitialContent(value)} + /> + + + + {projects.map((project) => ( + + ))} + + + ) } diff --git a/apps/raycast-extension/src/api.ts b/apps/raycast-extension/src/api.ts index 0cb2ec208..55672a77b 100644 --- a/apps/raycast-extension/src/api.ts +++ b/apps/raycast-extension/src/api.ts @@ -35,6 +35,10 @@ export interface AddMemoryRequest { metadata?: Record; } +interface AddProjectRequest { + name: string; +} + export interface SearchRequest { q: string; containerTags?: string[]; @@ -66,28 +70,16 @@ class AuthenticationError extends Error { } } -async function getApiKey(): Promise { - try { - const preferences = getPreferenceValues<{ apiKey: string }>(); - const apiKey = preferences.apiKey?.trim(); - - if (!apiKey) { - throw new AuthenticationError( - "API key is required. Please add your Supermemory API key in preferences.", - ); - } - - return apiKey; - } catch { - throw new AuthenticationError("Failed to get API key from preferences."); - } +function getApiKey(): string { + const { apiKey } = getPreferenceValues(); + return apiKey; } async function makeAuthenticatedRequest( endpoint: string, options: RequestInit = {}, ): Promise { - const apiKey = await getApiKey(); + const apiKey = getApiKey(); const url = `${API_BASE_URL}${endpoint}`; @@ -159,6 +151,21 @@ export async function fetchProjects(): Promise { } } +export async function addProject(request: AddProjectRequest): Promise { + const response = await makeAuthenticatedRequest("/v3/projects", { + method: "POST", + body: JSON.stringify(request), + }); + + await showToast({ + style: Toast.Style.Success, + title: "Project Added", + message: "Successfully added project to Supermemory", + }); + + return response; +} + export async function addMemory(request: AddMemoryRequest): Promise { try { const response = await makeAuthenticatedRequest("/v3/documents", { @@ -209,19 +216,7 @@ export async function searchMemories( } // Helper function to check if API key is configured and valid -export async function checkApiConnection(): Promise { - try { - await fetchProjects(); - return true; - } catch (error) { - if (error instanceof AuthenticationError) { - await showToast({ - style: Toast.Style.Failure, - title: "API Key Required", - message: - "Please configure your Supermemory API key in preferences. Get it from https://supermemory.link/raycast", - }); - } - return false; - } +export async function fetchSettings(): Promise { + const response = await makeAuthenticatedRequest("/v3/settings"); + return response; } diff --git a/apps/raycast-extension/src/search-memories.tsx b/apps/raycast-extension/src/search-memories.tsx index 850fbe3c5..dbc47ceb7 100644 --- a/apps/raycast-extension/src/search-memories.tsx +++ b/apps/raycast-extension/src/search-memories.tsx @@ -1,222 +1,187 @@ import { - ActionPanel, - Detail, - List, - Action, - Icon, - showToast, - Toast, - Clipboard, - openExtensionPreferences, -} from "@raycast/api"; -import { useState, useEffect, useCallback } from "react"; -import { searchMemories, checkApiConnection, type SearchResult } from "./api"; + ActionPanel, + Detail, + List, + Action, + Icon, + showToast, + Toast, + getSelectedText, +} from "@raycast/api" +import { useState, useEffect } from "react" +import { searchMemories, type SearchResult } from "./api" +import { usePromise } from "@raycast/utils" +import { withSupermemory } from "./withSupermemory" const extractContent = (memory: SearchResult) => { - if (memory.chunks && memory.chunks.length > 0) { - return memory.chunks - .map((chunk: unknown) => { - if (typeof chunk === "string") return chunk; - if ( - chunk && - typeof chunk === "object" && - "content" in chunk && - typeof chunk.content === "string" - ) - return chunk.content; - if ( - chunk && - typeof chunk === "object" && - "text" in chunk && - typeof chunk.text === "string" - ) - return chunk.text; - return ""; - }) - .filter(Boolean) - .join(" "); - } - return "No content available"; -}; + if (memory.chunks && memory.chunks.length > 0) { + return memory.chunks + .map((chunk: unknown) => { + if (typeof chunk === "string") return chunk + if ( + chunk && + typeof chunk === "object" && + "content" in chunk && + typeof chunk.content === "string" + ) + return chunk.content + if ( + chunk && + typeof chunk === "object" && + "text" in chunk && + typeof chunk.text === "string" + ) + return chunk.text + return "" + }) + .filter(Boolean) + .join(" ") + } + return "No content available" +} const extractUrl = (memory: SearchResult) => { - if (memory.metadata?.url && typeof memory.metadata.url === "string") { - return memory.metadata.url; - } - return null; -}; - -export default function Command() { - const [searchResults, setSearchResults] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [searchText, setSearchText] = useState(""); - const [hasSearched, setHasSearched] = useState(false); - const [isConnected, setIsConnected] = useState(null); - - useEffect(() => { - async function checkConnection() { - const connected = await checkApiConnection(); - setIsConnected(connected); - } - checkConnection(); - }, []); - - const performSearch = useCallback( - async (query: string) => { - if (!query.trim() || !isConnected) return; - - try { - setIsLoading(true); - setHasSearched(true); - - const results = await searchMemories({ - q: query.trim(), - limit: 50, - }); - - setSearchResults(results); - - if (results.length === 0) { - await showToast({ - style: Toast.Style.Success, - title: "Search Complete", - message: "No memories found for your query", - }); - } - } catch (error) { - console.error("Search failed:", error); - setSearchResults([]); - } finally { - setIsLoading(false); - } - }, - [isConnected], - ); - - useEffect(() => { - if (!searchText.trim()) { - setSearchResults([]); - setHasSearched(false); - return; - } - - const debounceTimer = setTimeout(() => { - performSearch(searchText); - }, 500); - - return () => clearTimeout(debounceTimer); - }, [searchText, performSearch]); - - const formatDate = (dateString: string) => { - try { - return new Date(dateString).toLocaleDateString("en-US", { - year: "numeric", - month: "short", - day: "numeric", - hour: "2-digit", - minute: "2-digit", - }); - } catch { - return "Unknown date"; - } - }; - - const truncateContent = (content: string, maxLength = 100) => { - if (content.length <= maxLength) return content; - return `${content.substring(0, maxLength)}...`; - }; - - if (isConnected === false) { - return ( - - - openExtensionPreferences()} - icon={Icon.Gear} - /> - - } - /> - - ); - } - - return ( - - {!hasSearched && !searchText.trim() ? ( - - ) : hasSearched && searchResults.length === 0 ? ( - - ) : ( - searchResults.map((memory) => { - const content = extractContent(memory); - const url = extractUrl(memory); - return ( - - } - icon={Icon.Eye} - /> - Clipboard.copy(content)} - icon={Icon.Clipboard} - shortcut={{ modifiers: ["cmd"], key: "c" }} - /> - {url && ( - - )} - - } - /> - ); - }) - )} - - ); + if (memory.metadata?.url && typeof memory.metadata.url === "string") { + return memory.metadata.url + } + return null +} + +const truncateContent = (content: string, maxLength = 100) => { + if (content.length <= maxLength) return content + return `${content.substring(0, maxLength)}...` +} + +export default withSupermemory(Command) +function Command() { + const [searchText, setSearchText] = useState("") + + useEffect(() => { + async function loadSelectedText() { + try { + const selectedText = await getSelectedText() + if (selectedText) { + setSearchText(selectedText) + } + } catch { + // No text selected or error getting selected text - silently fail + } + } + + loadSelectedText() + }, []) + + const { isLoading, data: searchResults = [] } = usePromise( + async (query: string) => { + const q = query.trim() + if (!q) return [] + + const results = await searchMemories({ + q, + limit: 50, + }) + if (!results.length) { + await showToast({ + style: Toast.Style.Success, + title: "Search Complete", + message: "No memories found for your query", + }) + } + return results + }, + [searchText], + ) + + const formatDate = (dateString: string) => { + try { + return new Date(dateString).toLocaleDateString("en-US", { + year: "numeric", + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + }) + } catch { + return "Unknown date" + } + } + + const hasSearched = !isLoading && !searchResults.length + return ( + + {hasSearched && !searchText.trim() ? ( + + ) : hasSearched ? ( + + ) : isLoading && searchText.trim() ? ( + + ) : ( + searchResults.map((memory) => { + const content = extractContent(memory) + const url = extractUrl(memory) + return ( + + } + icon={Icon.Eye} + /> + + {url && ( + + )} + + } + /> + ) + }) + )} + + ) } function MemoryDetail({ memory }: { memory: SearchResult }) { - const content = extractContent(memory); - const url = extractUrl(memory); + const content = extractContent(memory) + const url = extractUrl(memory) - const markdown = ` + const markdown = ` # ${memory.title || "Untitled Memory"} ${content} @@ -226,28 +191,27 @@ ${content} **Created:** ${new Date(memory.createdAt).toLocaleString()} ${url ? `**URL:** ${url}` : ""} ${memory.score ? `**Relevance:** ${Math.round(memory.score * 100)}%` : ""} -`; - - return ( - - Clipboard.copy(content)} - icon={Icon.Clipboard} - shortcut={{ modifiers: ["cmd"], key: "c" }} - /> - {url && ( - - )} - - } - /> - ); +` + + return ( + + + {url && ( + + )} + + } + /> + ) } diff --git a/apps/raycast-extension/src/search-projects.tsx b/apps/raycast-extension/src/search-projects.tsx new file mode 100644 index 000000000..bacd85371 --- /dev/null +++ b/apps/raycast-extension/src/search-projects.tsx @@ -0,0 +1,106 @@ +import { + ActionPanel, + List, + Action, + Icon, + Form, + useNavigation, +} from "@raycast/api"; +import { useState } from "react"; +import { fetchProjects, addProject } from "./api"; +import { + FormValidation, + showFailureToast, + useCachedPromise, + useForm, +} from "@raycast/utils"; +import { withSupermemory } from "./withSupermemory"; + +export default withSupermemory(Command); + +function Command() { + const { isLoading, data: projects, mutate } = useCachedPromise(fetchProjects); + + return ( + + {!isLoading && !projects?.length ? ( + + } + onPop={mutate} + /> + + } + /> + ) : ( + projects?.map((project) => ( + + } + onPop={mutate} + /> + + } + /> + )) + )} + + ); +} + +function CreateProject() { + const { pop } = useNavigation(); + const [isLoading, setIsLoading] = useState(false); + const { handleSubmit, itemProps } = useForm<{ name: string }>({ + async onSubmit(values) { + setIsLoading(true); + try { + await addProject(values); + pop(); + } catch (error) { + await showFailureToast(error, { title: "Failed to add project" }); + } finally { + setIsLoading(false); + } + }, + validation: { + name: FormValidation.Required, + }, + }); + return ( +
+ + + } + > + + + ); +} diff --git a/apps/raycast-extension/src/withSupermemory.tsx b/apps/raycast-extension/src/withSupermemory.tsx new file mode 100644 index 000000000..13c1d7b80 --- /dev/null +++ b/apps/raycast-extension/src/withSupermemory.tsx @@ -0,0 +1,48 @@ +import { usePromise } from "@raycast/utils"; +import { fetchSettings } from "./api"; +import { + Action, + ActionPanel, + Detail, + Icon, + List, + openExtensionPreferences, +} from "@raycast/api"; +import { ComponentType } from "react"; + +export function withSupermemory

(Component: ComponentType

) { + return function SupermemoryWrappedComponent(props: P) { + const { isLoading, data } = usePromise(fetchSettings, [], { + failureToastOptions: { + title: "Invalid API Key", + message: + "Invalid API key. Please check your API key in preferences. Get a new one from https://supermemory.link/raycast", + }, + }); + + if (!data) { + return isLoading ? ( + + ) : ( + + + + + } + /> + + ); + } + + return ; + }; +} From 16979f8bee059505f6167804336875764af4beca Mon Sep 17 00:00:00 2001 From: nexxeln <95541290+nexxeln@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:00:38 +0000 Subject: [PATCH 4/5] github connector docs (#594) --- apps/docs/connectors/github.mdx | 550 ++++++++++++++++++++++++++++++ apps/docs/connectors/overview.mdx | 12 +- apps/docs/docs.json | 1 + 3 files changed, 561 insertions(+), 2 deletions(-) create mode 100644 apps/docs/connectors/github.mdx diff --git a/apps/docs/connectors/github.mdx b/apps/docs/connectors/github.mdx new file mode 100644 index 000000000..71bbccf7d --- /dev/null +++ b/apps/docs/connectors/github.mdx @@ -0,0 +1,550 @@ +--- +title: "GitHub Connector" +description: "Connect GitHub repositories to sync documentation files into your Supermemory knowledge base" +icon: "github" +--- + +Connect GitHub repositories to sync documentation files into your Supermemory knowledge base with OAuth authentication, webhook support, and automatic incremental syncing. + +## Quick Setup + +### 1. Create GitHub Connection + + + + ```typescript + import Supermemory from 'supermemory'; + + const client = new Supermemory({ + apiKey: process.env.SUPERMEMORY_API_KEY! + }); + + const connection = await client.connections.create('github', { + redirectUrl: 'https://yourapp.com/auth/github/callback', + containerTags: ['user-123', 'github-sync'], + documentLimit: 5000, + metadata: { + source: 'github', + team: 'engineering' + } + }); + + // Redirect user to GitHub OAuth + window.location.href = connection.authLink; + console.log('Auth expires in:', connection.expiresIn); + ``` + + + ```python + from supermemory import Supermemory + import os + + client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY")) + + connection = client.connections.create( + 'github', + redirect_url='https://yourapp.com/auth/github/callback', + container_tags=['user-123', 'github-sync'], + document_limit=10000, + metadata={ + 'source': 'github', + 'team': 'engineering' + } + ) + + # Redirect user to GitHub OAuth + print(f'Redirect to: {connection.auth_link}') + print(f'Expires in: {connection.expires_in}') + ``` + + + ```bash + curl -X POST "https://api.supermemory.ai/v3/connections/github" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "redirectUrl": "https://yourapp.com/auth/github/callback", + "containerTags": ["user-123", "github-sync"], + "documentLimit": 5000, + "metadata": { + "source": "github", + "team": "engineering" + } + }' + ``` + + + + +**OAuth Scopes:** The GitHub connector requires these scopes: +- `repo` - Access to private and public repositories +- `user:email` - Access to user's email address +- `admin:repo_hook` - Manage webhooks for incremental sync + + +### 2. Handle OAuth Callback + +After the user grants permissions, GitHub redirects to your callback URL. The connection is automatically established, and the user can now select which repositories to sync. + +### 3. List and Configure Repositories + +Unlike other connectors, GitHub requires repository selection before syncing begins. This gives your users control over which repositories to index. + + + + ```typescript + // List available repositories for the user + const repositories = await client.connections.github.listRepositories( + connectionId, + { + page: 1, + perPage: 100 + } + ); + + // Display repositories in your UI + repositories.forEach(repo => { + console.log(`${repo.full_name} - ${repo.description}`); + console.log(`Private: ${repo.private}`); + console.log(`Default branch: ${repo.default_branch}`); + console.log(`Last updated: ${repo.updated_at}`); + }); + + // After user selects repositories, configure them + await client.connections.github.configure(connectionId, { + repositories: [ + { + id: repo.id, + name: repo.full_name, + defaultBranch: repo.default_branch + } + ] + }); + + console.log('Repository sync initiated'); + ``` + + + ```python + # List available repositories for the user + repositories = client.connections.github.list_repositories( + connection_id, + page=1, + per_page=100 + ) + + # Display repositories in your UI + for repo in repositories: + print(f'{repo.full_name} - {repo.description}') + print(f'Private: {repo.private}') + print(f'Default branch: {repo.default_branch}') + print(f'Last updated: {repo.updated_at}') + + # After user selects repositories, configure them + client.connections.github.configure( + connection_id, + repositories=[ + { + 'id': repo.id, + 'name': repo.full_name, + 'defaultBranch': repo.default_branch + } + ] + ) + + print('Repository sync initiated') + ``` + + + ```bash + # List available repositories + curl -X GET "https://api.supermemory.ai/v3/connections/{connectionId}/github/repositories?page=1&per_page=100" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" + + # Configure selected repositories + curl -X POST "https://api.supermemory.ai/v3/connections/{connectionId}/github/configure" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "repositories": [ + { + "id": 123456789, + "name": "your-org/documentation", + "defaultBranch": "main" + }, + { + "id": 987654321, + "name": "your-org/api-docs", + "defaultBranch": "main" + } + ] + }' + ``` + + + + +**API-First Design:** + +Supermemory provides the API endpoints to list and configure repositories. As a Supermemory customer, you need to build the UI in your application where your end-users can: +1. View their available GitHub repositories +2. Select which repositories to sync +3. Confirm the selection + +This gives you complete control over the user experience and allows you to integrate repository selection seamlessly into your application's workflow. + + +## Supported Document Types + +The GitHub connector syncs documentation and text files with the following extensions: + +- **Markdown files**: `.md`, `.mdx`, `.markdown` +- **Text files**: `.txt` +- **reStructuredText**: `.rst` +- **AsciiDoc**: `.adoc` +- **Org-mode**: `.org` + +Files are indexed as `github_markdown` document type in Supermemory. + + +Only text-based documentation files are synced. Binary files, images, and code files (`.js`, `.py`, `.go`, etc.) are excluded by default to focus on searchable documentation content. + + +## Incremental Sync with Webhooks + +The GitHub connector automatically sets up webhooks for real-time incremental syncing. When files are pushed or deleted in configured repositories, Supermemory is notified immediately. + + +**Batch Processing:** Webhook events are processed in batches with a 10-minute delay to optimize performance and prevent excessive syncing during rapid commits. This means changes pushed to your repository will be reflected in Supermemory within approximately 10 minutes. + + +### How It Works + +1. **Webhook Setup**: When you configure repositories, a webhook is automatically installed in each repository +2. **Push Events**: When commits are pushed to the default branch, changed documentation files are synced +3. **Delete Events**: When documentation files are deleted, they're removed from your Supermemory knowledge base +4. **Incremental Updates**: Only changed files are processed, keeping sync fast and efficient + +### Webhook Security + +Webhooks are secured using HMAC-SHA256 signature validation with constant-time comparison. Supermemory automatically validates that webhook events come from GitHub before processing them. Each repository gets a unique webhook secret for maximum security. + + + + ```typescript + // Check webhook status + const connection = await client.connections.get(connectionId); + + console.log('Webhooks configured:', connection.metadata.webhooks?.length); + console.log('Last sync:', new Date(connection.metadata.lastSyncedAt)); + console.log('Repositories:', connection.metadata.repositories); + ``` + + + ```python + # Check webhook status + connection = client.connections.get(connection_id) + + print(f'Webhooks configured: {len(connection.metadata.get("webhooks", []))}') + print(f'Last sync: {connection.metadata.get("lastSyncedAt")}') + print(f'Repositories: {connection.metadata.get("repositories")}') + ``` + + + ```bash + # Get connection details including webhook status + curl -X POST "https://api.supermemory.ai/v3/connections/list" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{}' + ``` + + + +## Connection Management + +### List All Connections + + + + ```typescript + // List all GitHub connections for specific container tags + const connections = await client.connections.list({ + containerTags: ['user-123'], + provider: 'github' + }); + + connections.forEach(conn => { + console.log(`Provider: ${conn.provider}`); + console.log(`ID: ${conn.id}`); + console.log(`Email: ${conn.email}`); + console.log(`Created: ${conn.createdAt}`); + console.log(`Document limit: ${conn.documentLimit}`); + console.log(`Repositories: ${conn.metadata.repositories?.length || 0}`); + console.log('---'); + }); + ``` + + + ```python + # List all GitHub connections for specific container tags + connections = client.connections.list( + container_tags=['user-123'], + provider='github' + ) + + for conn in connections: + print(f'Provider: {conn.provider}') + print(f'ID: {conn.id}') + print(f'Email: {conn.email}') + print(f'Created: {conn.created_at}') + print(f'Document limit: {conn.document_limit}') + print(f'Repositories: {len(conn.metadata.get("repositories", []))}') + print('---') + ``` + + + ```bash + # List all GitHub connections for specific container tags + curl -X POST "https://api.supermemory.ai/v3/connections/list" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "containerTags": ["user-123"], + "provider": "github" + }' + ``` + + + +### Update Repository Configuration + +You can update which repositories are synced at any time: + + + + ```typescript + // Add or remove repositories + await client.connections.github.configure(connectionId, { + repositories: [ + { + id: 123456789, + name: 'your-org/documentation', + defaultBranch: 'main' + }, + { + id: 987654321, + name: 'your-org/new-repo', + defaultBranch: 'develop' // Can specify different branch + } + ] + }); + + console.log('Repository configuration updated'); + ``` + + + ```python + # Add or remove repositories + client.connections.github.configure( + connection_id, + repositories=[ + { + 'id': 123456789, + 'name': 'your-org/documentation', + 'defaultBranch': 'main' + }, + { + 'id': 987654321, + 'name': 'your-org/new-repo', + 'defaultBranch': 'develop' # Can specify different branch + } + ] + ) + + print('Repository configuration updated') + ``` + + + ```bash + # Update repository configuration + curl -X POST "https://api.supermemory.ai/v3/connections/{connectionId}/github/configure" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "repositories": [ + { + "id": 123456789, + "name": "your-org/documentation", + "defaultBranch": "main" + }, + { + "id": 987654321, + "name": "your-org/new-repo", + "defaultBranch": "develop" + } + ] + }' + ``` + + + + +When you update the repository configuration: +- New repositories are added and synced immediately +- Removed repositories have their webhooks deleted +- Existing documents from removed repositories remain in Supermemory unless you delete them manually + + +### Delete Connection + + + + ```typescript + // Delete by connection ID + const result = await client.connections.delete(connectionId); + console.log('Deleted connection:', result.id); + ``` + + + ```python + # Delete by connection ID + result = client.connections.delete(connection_id) + print(f'Deleted connection: {result.id}') + ``` + + + ```bash + # Delete by connection ID + curl -X DELETE "https://api.supermemory.ai/v3/connections/{connectionId}" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" + ``` + + + + +Deleting a GitHub connection will: +- Stop all future syncs from configured repositories +- Remove all webhooks from the repositories +- Revoke the OAuth authorization +- **Permanently delete all synced documents** from your Supermemory knowledge base + + +### Manual Sync + +Trigger a manual synchronization for all configured repositories: + + + + ```typescript + // Trigger sync for GitHub connections + await client.connections.import('github'); + + // Trigger sync for specific container tags + await client.connections.import('github', { + containerTags: ['user-123'] + }); + + console.log('Manual sync initiated'); + ``` + + + ```python + # Trigger sync for GitHub connections + client.connections.import_('github') + + # Trigger sync for specific container tags + client.connections.import_( + 'github', + container_tags=['user-123'] + ) + + print('Manual sync initiated') + ``` + + + ```bash + # Trigger sync for all GitHub connections + curl -X POST "https://api.supermemory.ai/v3/connections/github/import" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" + + # Trigger sync for specific container tags + curl -X POST "https://api.supermemory.ai/v3/connections/github/import" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "containerTags": ["user-123"] + }' + + # Response: {"message": "Manual sync initiated", "provider": "github"} + ``` + + + +## Advanced Configuration + +### Custom OAuth Application + +For white-label deployments or custom branding, configure your own GitHub OAuth app using the settings API: + + + + ```typescript + // Update organization settings with your GitHub OAuth app + await client.settings.update({ + githubCustomKeyEnabled: true, + githubClientId: 'Iv1.1234567890abcdef', + githubClientSecret: 'your-github-client-secret' + }); + + // Get current settings + const settings = await client.settings.get(); + console.log('GitHub custom key enabled:', settings.githubCustomKeyEnabled); + console.log('Client ID configured:', !!settings.githubClientId); + ``` + + + ```python + # Update organization settings with your GitHub OAuth app + client.settings.update( + github_custom_key_enabled=True, + github_client_id='Iv1.1234567890abcdef', + github_client_secret='your-github-client-secret' + ) + + # Get current settings + settings = client.settings.get() + print(f'GitHub custom key enabled: {settings.github_custom_key_enabled}') + print(f'Client ID configured: {bool(settings.github_client_id)}') + ``` + + + ```bash + # Update organization settings + curl -X PATCH "https://api.supermemory.ai/v3/settings" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "githubCustomKeyEnabled": true, + "githubClientId": "Iv1.1234567890abcdef", + "githubClientSecret": "your-github-client-secret" + }' + + # Get current settings + curl -X GET "https://api.supermemory.ai/v3/settings" \ + -H "Authorization: Bearer $SUPERMEMORY_API_KEY" + ``` + + + + +**Setting up a GitHub OAuth App:** + +1. Go to GitHub Settings → Developer settings → OAuth Apps +2. Click "New OAuth App" +3. Set Authorization callback URL to: `https://api.supermemory.ai/v3/connections/auth/callback/github` +4. Copy the Client ID and generate a Client Secret +5. Configure them in Supermemory using the settings API above + +After configuration, all new GitHub connections will use your custom OAuth app instead of Supermemory's default app. + diff --git a/apps/docs/connectors/overview.mdx b/apps/docs/connectors/overview.mdx index af9eaef96..c1428c109 100644 --- a/apps/docs/connectors/overview.mdx +++ b/apps/docs/connectors/overview.mdx @@ -1,10 +1,10 @@ --- title: "Connectors Overview" -description: "Integrate Google Drive, Notion, OneDrive, and Web Crawler to automatically sync documents into your knowledge base" +description: "Integrate Google Drive, Notion, OneDrive, GitHub and Web Crawler to automatically sync documents into your knowledge base" sidebarTitle: "Overview" --- -Connect external platforms to automatically sync documents into Supermemory. Supported connectors include Google Drive, Notion, OneDrive, and Web Crawler with real-time synchronization and intelligent content processing. +Connect external platforms to automatically sync documents into Supermemory. Supported connectors include Google Drive, Notion, OneDrive, GitHub and Web Crawler with real-time synchronization and intelligent content processing. ## Supported Connectors @@ -26,6 +26,13 @@ Connect external platforms to automatically sync documents into Supermemory. Sup Scheduled sync every 4 hours. Supports personal and business accounts with file versioning. + + + + **GitHub Repositories** + + Real-time incremental sync via webhooks. Supports documentation files in repositories. + **Web Pages, Documentation** @@ -212,6 +219,7 @@ graph TD | **Google Drive** | ✅ Webhooks (7-day expiry) | ✅ Every 4 hours | ✅ On-demand | | **Notion** | ✅ Webhooks | ✅ Every 4 hours | ✅ On-demand | | **OneDrive** | ✅ Webhooks (30-day expiry) | ✅ Every 4 hours | ✅ On-demand | +| **GitHub** | ✅ Webhooks | ✅ Every 4 hours | ✅ On-demand | | **Web Crawler** | ❌ Not supported | ✅ Scheduled recrawling (7+ days) | ✅ On-demand | diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 347d6df56..e2d1f202a 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -138,6 +138,7 @@ "connectors/notion", "connectors/google-drive", "connectors/onedrive", + "connectors/github", "connectors/web-crawler", "connectors/troubleshooting" ] From f9d304ec3e8b58f35ee74758fcd23e449bfdf721 Mon Sep 17 00:00:00 2001 From: Arnab Mondal Date: Fri, 5 Dec 2025 00:34:44 +0530 Subject: [PATCH 5/5] feat(tools): allow passing apiKey via options for browser support (#599) Co-authored-by: Mahesh Sanikommmu --- packages/tools/README.md | 4 +++- packages/tools/src/vercel/index.ts | 12 +++++++----- packages/tools/src/vercel/middleware.ts | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/tools/README.md b/packages/tools/README.md index b9df69302..10bd095b4 100644 --- a/packages/tools/README.md +++ b/packages/tools/README.md @@ -57,7 +57,7 @@ const addTool = addMemoryTool(process.env.SUPERMEMORY_API_KEY!, { #### AI SDK Middleware with Supermemory - `withSupermemory` will take advantage supermemory profile v4 endpoint personalized based on container tag -- Make sure you have `SUPERMEMORY_API_KEY` in env +- You can provide the Supermemory API key via the `apiKey` option to `withSupermemory` (recommended for browser usage), or fall back to `SUPERMEMORY_API_KEY` in the environment for server usage. ```typescript import { generateText } from "ai" @@ -395,6 +395,8 @@ interface WithSupermemoryOptions { verbose?: boolean mode?: "profile" | "query" | "full" addMemory?: "always" | "never" + /** Optional Supermemory API key. Use this in browser environments. */ + apiKey?: string } ``` diff --git a/packages/tools/src/vercel/index.ts b/packages/tools/src/vercel/index.ts index c50bbd409..1d87c73c2 100644 --- a/packages/tools/src/vercel/index.ts +++ b/packages/tools/src/vercel/index.ts @@ -7,6 +7,7 @@ interface WrapVercelLanguageModelOptions { verbose?: boolean; mode?: "profile" | "query" | "full"; addMemory?: "always" | "never"; + apiKey?: string; } /** @@ -24,6 +25,7 @@ interface WrapVercelLanguageModelOptions { * @param options.verbose - Optional flag to enable detailed logging of memory search and injection process (default: false) * @param options.mode - Optional mode for memory search: "profile", "query", or "full" (default: "profile") * @param options.addMemory - Optional mode for memory search: "always", "never" (default: "never") + * @param options.apiKey - Optional Supermemory API key to use instead of the environment variable * * @returns A wrapped language model that automatically includes relevant memories in prompts * @@ -44,7 +46,7 @@ interface WrapVercelLanguageModelOptions { * }) * ``` * - * @throws {Error} When SUPERMEMORY_API_KEY environment variable is not set + * @throws {Error} When neither `options.apiKey` nor `process.env.SUPERMEMORY_API_KEY` are set * @throws {Error} When supermemory API request fails */ const wrapVercelLanguageModel = ( @@ -52,10 +54,10 @@ const wrapVercelLanguageModel = ( containerTag: string, options?: WrapVercelLanguageModelOptions, ): LanguageModelV2 => { - const SUPERMEMORY_API_KEY = process.env.SUPERMEMORY_API_KEY + const providedApiKey = options?.apiKey ?? process.env.SUPERMEMORY_API_KEY - if (!SUPERMEMORY_API_KEY) { - throw new Error("SUPERMEMORY_API_KEY is not set") + if (!providedApiKey) { + throw new Error("SUPERMEMORY_API_KEY is not set — provide it via `options.apiKey` or set `process.env.SUPERMEMORY_API_KEY`") } const conversationId = options?.conversationId @@ -65,7 +67,7 @@ const wrapVercelLanguageModel = ( const wrappedModel = wrapLanguageModel({ model, - middleware: createSupermemoryMiddleware(containerTag, conversationId, verbose, mode, addMemory), + middleware: createSupermemoryMiddleware(containerTag, providedApiKey, conversationId, verbose, mode, addMemory), }) return wrappedModel diff --git a/packages/tools/src/vercel/middleware.ts b/packages/tools/src/vercel/middleware.ts index dd61e3971..bc107a0a8 100644 --- a/packages/tools/src/vercel/middleware.ts +++ b/packages/tools/src/vercel/middleware.ts @@ -68,6 +68,7 @@ const addMemoryTool = async ( export const createSupermemoryMiddleware = ( containerTag: string, + apiKey: string, conversationId?: string, verbose = false, mode: "profile" | "query" | "full" = "profile", @@ -76,7 +77,7 @@ export const createSupermemoryMiddleware = ( const logger = createLogger(verbose) const client = new Supermemory({ - apiKey: process.env.SUPERMEMORY_API_KEY, + apiKey, }) return {