diff --git a/bun.lock b/bun.lock index 0b7114a..e358509 100644 --- a/bun.lock +++ b/bun.lock @@ -125,31 +125,18 @@ "name": "@synsci/docs", "version": "1.2.2", "dependencies": { - "@astrojs/cloudflare": "12.6.3", - "@astrojs/markdown-remark": "6.3.1", - "@astrojs/solid-js": "5.1.0", - "@astrojs/starlight": "0.34.3", - "@fontsource/ibm-plex-mono": "5.2.5", - "@shikijs/transformers": "3.4.2", - "@types/luxon": "catalog:", - "ai": "catalog:", - "astro": "5.7.13", - "diff": "catalog:", - "js-base64": "3.7.7", - "lang-map": "0.4.0", - "luxon": "catalog:", - "marked": "catalog:", - "marked-shiki": "catalog:", - "rehype-autolink-headings": "7.1.0", - "remeda": "catalog:", - "shiki": "catalog:", - "solid-js": "catalog:", - "toolbeam-docs-theme": "0.4.8", + "lucide-react": "^0.453.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-markdown": "^9.0.1", + "remark-gfm": "^4.0.0", }, "devDependencies": { - "@synsci/openscience": "workspace:*", - "@types/node": "catalog:", - "typescript": "catalog:", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.6.3", + "vite": "^6.0.5", }, }, "frontend/ui": { @@ -253,7 +240,7 @@ }, "tooling/launcher": { "name": "synsci", - "version": "1.2.4", + "version": "1.2.5", "bin": { "synsci": "bin/synsci.mjs", }, @@ -415,28 +402,6 @@ "@anycable/core": ["@anycable/core@0.9.2", "", { "dependencies": { "nanoevents": "^7.0.1" } }, "sha512-x5ZXDcW/N4cxWl93CnbHs/u7qq4793jS2kNPWm+duPrXlrva+ml2ZGT7X9tuOBKzyIHf60zWCdIK7TUgMPAwXA=="], - "@astrojs/cloudflare": ["@astrojs/cloudflare@12.6.3", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.1", "@astrojs/underscore-redirects": "1.0.0", "@cloudflare/workers-types": "^4.20250507.0", "tinyglobby": "^0.2.13", "vite": "^6.3.5", "wrangler": "^4.14.1" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-xhJptF5tU2k5eo70nIMyL1Udma0CqmUEnGSlGyFflLqSY82CRQI6nWZ/xZt0ZvmXuErUjIx0YYQNfZsz5CNjLQ=="], - - "@astrojs/compiler": ["@astrojs/compiler@2.13.1", "", {}, "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg=="], - - "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="], - - "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="], - - "@astrojs/mdx": ["@astrojs/mdx@4.3.14", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.11", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA=="], - - "@astrojs/prism": ["@astrojs/prism@3.2.0", "", { "dependencies": { "prismjs": "^1.29.0" } }, "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw=="], - - "@astrojs/sitemap": ["@astrojs/sitemap@3.7.3", "", { "dependencies": { "sitemap": "^9.0.0", "stream-replace-string": "^2.0.0", "zod": "^4.3.6" } }, "sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA=="], - - "@astrojs/solid-js": ["@astrojs/solid-js@5.1.0", "", { "dependencies": { "vite": "^6.3.5", "vite-plugin-solid": "^2.11.6" }, "peerDependencies": { "solid-devtools": "^0.30.1", "solid-js": "^1.8.5" }, "optionalPeers": ["solid-devtools"] }, "sha512-VmPHOU9k7m6HHCT2Y1mNzifilUnttlowBM36frGcfj5wERJE9Ci0QtWJbzdf6AlcoIirb7xVw+ByupU011Di9w=="], - - "@astrojs/starlight": ["@astrojs/starlight@0.34.3", "", { "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/mdx": "^4.2.3", "@astrojs/sitemap": "^3.3.0", "@pagefind/default-ui": "^1.3.0", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", "astro-expressive-code": "^0.41.1", "bcp-47": "^2.1.0", "hast-util-from-html": "^2.0.1", "hast-util-select": "^6.0.2", "hast-util-to-string": "^3.0.0", "hastscript": "^9.0.0", "i18next": "^23.11.5", "js-yaml": "^4.1.0", "klona": "^2.0.6", "mdast-util-directive": "^3.0.0", "mdast-util-to-markdown": "^2.1.0", "mdast-util-to-string": "^4.0.0", "pagefind": "^1.3.0", "rehype": "^13.0.1", "rehype-format": "^5.0.0", "remark-directive": "^3.0.0", "ultrahtml": "^1.6.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "vfile": "^6.0.2" }, "peerDependencies": { "astro": "^5.5.0" } }, "sha512-MAuD3NF+E+QXJJuVKofoR6xcPTP4BJmYWeOBd03udVdubNGVnPnSWVZAi+ZtnTofES4+mJdp8BNGf+ubUxkiiA=="], - - "@astrojs/telemetry": ["@astrojs/telemetry@3.2.1", "", { "dependencies": { "ci-info": "^4.2.0", "debug": "^4.4.0", "dlv": "^1.1.3", "dset": "^3.1.4", "is-docker": "^3.0.0", "is-wsl": "^3.1.0", "which-pm-runs": "^1.1.0" } }, "sha512-SSVM820Jqc6wjsn7qYfV9qfeQvePtVc1nSofhyap7l0/iakUKywj3hfy3UJAOV4sGV4Q/u450RD4AaCaFvNPlg=="], - - "@astrojs/underscore-redirects": ["@astrojs/underscore-redirects@1.0.0", "", {}, "sha512-qZxHwVnmb5FXuvRsaIGaqWgnftjCuMY+GSbaVZdBmE4j8AfgPqKPxYp8SUERyJcjpKCEmO4wD6ybuGH8A2kVRQ=="], - "@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="], "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], @@ -473,6 +438,10 @@ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A=="], + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw=="], + + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="], @@ -481,36 +450,12 @@ "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], - "@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="], - "@clack/core": ["@clack/core@1.0.0-alpha.1", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-rFbCU83JnN7l3W1nfgCqqme4ZZvTTgsiKQ6FM0l+r0P+o2eJpExcocBUWUIwnDzL76Aca9VhUdWmB2MbUv+Qyg=="], "@clack/prompts": ["@clack/prompts@1.0.0-alpha.1", "", { "dependencies": { "@clack/core": "1.0.0-alpha.1", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-07MNT0OsxjKOcyVfX8KhXBhJiyUbDP1vuIAcHc+nx5v93MJO23pX3X/k3bWz6T3rpM9dgWPq90i4Jq7gZAyMbw=="], - "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="], - - "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="], - - "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260601.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-iXZBVuRbvuVqQ/63wul01hHCv/3R8G5S8zbkjfoHvyPZFynmlKTV59Hk+H8whyGwFAZuB71UJGLr+G5mJKfjWA=="], - - "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260601.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-veGpZQGBw07Twt+Y4z3oyo+/obKHt0iWUwvDV5GOiDAYjC/zW+YGstgVzg4SHq+k1sLH3ElqL2TXx20I5WBv3Q=="], - - "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260601.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n/9hDz7fPGpYF0J684+Xr5zgjcS2jdmY2Of5m6e+eQ/M9+RfR+UaU8Ee/tkA1dDC0LYQB13hfPafZG66Ff1CsA=="], - - "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260601.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-VHRZZbexATS+n+1j3x/CZaYbIJEye0J3iIHgG0Wp+l+NrZCKQ8qi8Lq1uTV0dLJQ67FuZtJtWdQ95mm9F7Fc+A=="], - - "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260601.1", "", { "os": "win32", "cpu": "x64" }, "sha512-ye0C7MFLkeH16iTo8Tcjv2KiFmp23+sZGvUzSQa4xhP0QMe6EoJ+H/4SqqvnZ5nfN54slqKvx2VnXceENWe2CQ=="], - - "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260602.1", "", {}, "sha512-0VssYYXHUn4VR1BaV+GXfhFpI53P2f6AIi17qyA9lQFyTs/u5ZF6IDPda2enDTIPFz/02872RM8CYVlXvRKtUA=="], - "@corvu/utils": ["@corvu/utils@0.4.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.11" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA=="], - "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], - - "@ctrl/tinycolor": ["@ctrl/tinycolor@4.2.0", "", {}, "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="], - - "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], @@ -563,14 +508,6 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@expressive-code/core": ["@expressive-code/core@0.41.7", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg=="], - - "@expressive-code/plugin-frames": ["@expressive-code/plugin-frames@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA=="], - - "@expressive-code/plugin-shiki": ["@expressive-code/plugin-shiki@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "shiki": "^3.2.2" } }, "sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ=="], - - "@expressive-code/plugin-text-markers": ["@expressive-code/plugin-text-markers@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw=="], - "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], @@ -579,8 +516,6 @@ "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], - "@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.2.5", "", {}, "sha512-G09N3GfuT9qj3Ax2FDZvKqZttzM3v+cco2l8uXamhKyXLdmlaUDH5o88/C3vtTHj2oT7yRKsvxz9F+BXbWKMYA=="], - "@gitlab/gitlab-ai-provider": ["@gitlab/gitlab-ai-provider@3.3.1", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=2.0.0", "@ai-sdk/provider-utils": ">=3.0.0" } }, "sha512-J4/LfVcxOKbR2gfoBWRKp1BpWppprC2Cz/Ff5E0B/0lS341CDtZwzkgWvHfkM/XU6q83JRs059dS0cR8VOODOQ=="], "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], @@ -601,56 +536,6 @@ "@hono/zod-validator": ["@hono/zod-validator@0.4.2", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.19.1" } }, "sha512-1rrlBg+EpDPhzOV4hT9pxr5+xDVmKuz6YJl+la7VCwK6ass5ldyKm5fD+umJdV2zhHD6jROoCCv8NbTwyfhT0g=="], - "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], - - "@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=="], - - "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], - - "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], - - "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], - - "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], - - "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], - - "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], - - "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], - - "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], - - "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], - - "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], - - "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], - - "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], - - "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], - - "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], - - "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], - - "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], - - "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], - - "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], - - "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], - - "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], - - "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], - - "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], - - "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], - "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], "@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=="], @@ -713,8 +598,6 @@ "@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="], - "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], - "@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="], "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.2", "", { "dependencies": { "@hono/node-server": "^1.19.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww=="], @@ -787,22 +670,6 @@ "@oslojs/jwt": ["@oslojs/jwt@0.2.0", "", { "dependencies": { "@oslojs/encoding": "0.4.1" } }, "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg=="], - "@pagefind/darwin-arm64": ["@pagefind/darwin-arm64@1.5.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ=="], - - "@pagefind/darwin-x64": ["@pagefind/darwin-x64@1.5.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw=="], - - "@pagefind/default-ui": ["@pagefind/default-ui@1.5.2", "", {}, "sha512-pm1LMnQg8N2B3n2TnjKlhaFihpz6zTiA4HiGQ6/slKO/+8K9CAU5kcjdSSPgpuk1PMuuN4hxLipUIifnrkl3Sg=="], - - "@pagefind/freebsd-x64": ["@pagefind/freebsd-x64@1.5.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA=="], - - "@pagefind/linux-arm64": ["@pagefind/linux-arm64@1.5.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw=="], - - "@pagefind/linux-x64": ["@pagefind/linux-x64@1.5.2", "", { "os": "linux", "cpu": "x64" }, "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA=="], - - "@pagefind/windows-arm64": ["@pagefind/windows-arm64@1.5.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g=="], - - "@pagefind/windows-x64": ["@pagefind/windows-x64@1.5.2", "", { "os": "win32", "cpu": "x64" }, "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg=="], - "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="], @@ -835,15 +702,9 @@ "@playwright/test": ["@playwright/test@1.57.0", "", { "dependencies": { "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" } }, "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA=="], - "@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="], - - "@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="], - - "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="], - "@rdkit/rdkit": ["@rdkit/rdkit@2025.3.4-1.0.0", "", {}, "sha512-MJzNoeW2SWt2KCdIibfY213uLWyHZjFfS2ntJ/HuYNHdu6dEiim7jb6ZMU9wnt9Oovkc85BHMuupxkufIMvftQ=="], - "@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.61.0", "", { "os": "android", "cpu": "arm" }, "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ=="], @@ -897,9 +758,9 @@ "@scarf/scarf": ["@scarf/scarf@1.4.0", "", {}, "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ=="], - "@shikijs/core": ["@shikijs/core@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ=="], + "@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], - "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ=="], "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="], @@ -907,14 +768,12 @@ "@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="], - "@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="], + "@shikijs/transformers": ["@shikijs/transformers@3.9.2", "", { "dependencies": { "@shikijs/core": "3.9.2", "@shikijs/types": "3.9.2" } }, "sha512-MW5hT4TyUp6bNAgTExRYLk1NNasVQMTCw1kgbxHcEC0O5cbepPWaB+1k+JzW9r3SP2/R8kiens8/3E6hGKfgsA=="], - "@shikijs/types": ["@shikijs/types@3.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg=="], + "@shikijs/types": ["@shikijs/types@3.9.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-/M5L0Uc2ljyn2jKvj4Yiah7ow/W+DJSglVafvWAJ/b8AZDeeRAdMu3c2riDzB7N42VD+jSnWxeP9AKtd4TfYVw=="], "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], - "@smithy/core": ["@smithy/core@3.24.6", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug=="], "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-Ussyv240JxwQP8AmkYdm26wGP/1I8QmIv0ZosgDJDlSzD73FEdj1BOpXMc06VrxX5KxTKhadFNomT2SWutUnpg=="], @@ -973,8 +832,6 @@ "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], - "@speed-highlight/core": ["@speed-highlight/core@1.2.15", "", {}, "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw=="], - "@standard-community/standard-json": ["@standard-community/standard-json@0.3.5", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@types/json-schema": "^7.0.15", "@valibot/to-json-schema": "^1.3.0", "arktype": "^2.1.20", "effect": "^3.16.8", "quansync": "^0.2.11", "sury": "^10.0.0", "typebox": "^1.0.17", "valibot": "^1.1.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.24.5" }, "optionalPeers": ["@valibot/to-json-schema", "arktype", "effect", "sury", "typebox", "valibot", "zod", "zod-to-json-schema"] }, "sha512-4+ZPorwDRt47i+O7RjyuaxHRK/37QY/LmgxlGrRrSTLYoFatEOzvqIc85GTlM18SFZ5E91C+v0o/M37wZPpUHA=="], "@standard-community/standard-openapi": ["@standard-community/standard-openapi@0.2.9", "", { "peerDependencies": { "@standard-community/standard-json": "^0.3.5", "@standard-schema/spec": "^1.0.0", "arktype": "^2.1.20", "effect": "^3.17.14", "openapi-types": "^12.1.3", "sury": "^10.0.0", "typebox": "^1.0.0", "valibot": "^1.1.0", "zod": "^3.25.0 || ^4.0.0", "zod-openapi": "^4" }, "optionalPeers": ["arktype", "effect", "sury", "typebox", "valibot", "zod", "zod-openapi"] }, "sha512-htj+yldvN1XncyZi4rehbf9kLbu8os2Ke/rfqoZHCMHuw34kiF3LP/yQPdA0tQ940y8nDq3Iou8R3wG+AGGyvg=="], @@ -1067,14 +924,10 @@ "@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.1", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A=="], - "@types/fontkit": ["@types/fontkit@2.0.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-qNYerFky3muCmZPq+R+B3cUDRA5OONw/oh6aGGFxx2LOBz6yu8eamKusrhkHnC6rc2fm76+G9z9QoWSB2SaQaw=="], - "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], - "@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="], - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/katex": ["@types/katex@0.16.7", "", {}, "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="], @@ -1083,12 +936,8 @@ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], - "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], - "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="], - "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], "@types/qs": ["@types/qs@6.15.1", "", {}, "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw=="], @@ -1097,7 +946,7 @@ "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], - "@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="], + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], "@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="], @@ -1139,14 +988,12 @@ "@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="], + "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], + "@zip.js/zip.js": ["@zip.js/zip.js@2.7.62", "", {}, "sha512-OaLvZ8j4gCkLn048ypkZu29KX30r8/OfFF2w4Jo5WXFr+J04J+lzJ5TKZBVgFXhlvSkqNFQdfnY1Q8TMTCyBVA=="], "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], - "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "ai": ["ai@5.0.119", "", { "dependencies": { "@ai-sdk/gateway": "2.0.25", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HUOwhc17fl2SZTJGZyA/99aNu706qKfXaUBCy9vgZiXBwrxg2eTzn2BCz7kmYDsfx6Fg2ACBy2icm41bsDXCTw=="], @@ -1155,36 +1002,18 @@ "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], - "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "arctic": ["arctic@2.3.4", "", { "dependencies": { "@oslojs/crypto": "1.0.1", "@oslojs/encoding": "1.1.0", "@oslojs/jwt": "0.2.0" } }, "sha512-+p30BOWsctZp+CVYCt7oAean/hWGW42sH5LAcRQX56ttEkFJWbzXBhmSpibbzwSJkRrotmsA+oAoJoVsU0f5xA=="], - "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], - - "array-iterate": ["array-iterate@2.0.1", "", {}, "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg=="], - - "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="], - - "astro": ["astro@5.7.13", "", { "dependencies": { "@astrojs/compiler": "^2.11.0", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.1", "@astrojs/telemetry": "3.2.1", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-cRGq2llKOhV3XMcYwQpfBIUcssN6HEK5CRbcMxAfd9OcFhvWE7KUy50zLioAZVVl3AqgUTJoNTlmZfD2eG0G1w=="], - - "astro-expressive-code": ["astro-expressive-code@0.41.7", "", { "dependencies": { "rehype-expressive-code": "^0.41.7" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, "sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ=="], - "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-/O6JWUmjv03OI9lL2ry9bUjpD5S3PclM55RRJEyCdcFZ5W2SEA/59d+l2hNsk3gI6kiWRdRPdOtqZmsQzFN1pQ=="], "babel-preset-solid": ["babel-preset-solid@1.9.12", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.6" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.12" }, "optionalPeers": ["solid-js"] }, "sha512-LLqnuKVDlKpyBlMPcH6qEvs/wmS9a+NczppxJ3ryS/c0O5IiSFOIBQi9GzyiGDSbcJpx4Gr87jyFTos1MyEuWg=="], @@ -1193,38 +1022,24 @@ "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.33", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw=="], - "bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="], - - "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="], - "before-after-hook": ["before-after-hook@2.2.3", "", {}, "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], - - "blob-to-buffer": ["blob-to-buffer@1.2.9", "", {}, "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA=="], - "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], - "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="], - "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], @@ -1243,8 +1058,6 @@ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -1265,12 +1078,8 @@ "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], - "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], - "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], - "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], - "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], @@ -1281,28 +1090,16 @@ "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], - "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], - - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - - "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], - - "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], - "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], - "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], - "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], "compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="], @@ -1317,9 +1114,7 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], - - "cookie-es": ["cookie-es@1.2.3", "", {}, "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw=="], + "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], @@ -1329,18 +1124,10 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - "crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], - "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=="], - "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="], - - "css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="], - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], @@ -1369,20 +1156,10 @@ "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], - "deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="], - - "devalue": ["devalue@5.8.1", "", {}, "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw=="], - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], - "dfa": ["dfa@1.2.0", "", {}, "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q=="], - "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="], - "direction": ["direction@2.0.1", "", { "bin": { "direction": "cli.js" } }, "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA=="], - - "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], - "dns-packet": ["dns-packet@5.6.1", "", { "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" } }, "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw=="], "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], @@ -1397,8 +1174,6 @@ "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], - "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], @@ -1419,20 +1194,12 @@ "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], - "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], - "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], - "esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="], - - "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="], - "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=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -1443,24 +1210,10 @@ "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], - "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="], - - "estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="], - "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], - "estree-util-scope": ["estree-util-scope@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0" } }, "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ=="], - - "estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="], - - "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="], - - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], - "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], "eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="], @@ -1471,8 +1224,6 @@ "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], - "expressive-code": ["expressive-code@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "@expressive-code/plugin-frames": "^0.41.7", "@expressive-code/plugin-shiki": "^0.41.7", "@expressive-code/plugin-text-markers": "^0.41.7" } }, "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA=="], - "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], @@ -1491,12 +1242,6 @@ "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], - "flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="], - - "fontace": ["fontace@0.3.1", "", { "dependencies": { "@types/fontkit": "^2.0.8", "fontkit": "^2.0.4" } }, "sha512-9f5g4feWT1jWT8+SbL85aLIRLIXUaDygaM2xPXRmzPYxrOMNok79Lr3FGJoKVNKibE0WCunNiEVG2mwuE+2qEg=="], - - "fontkit": ["fontkit@2.0.4", "", { "dependencies": { "@swc/helpers": "^0.5.12", "brotli": "^1.3.2", "clone": "^2.1.2", "dfa": "^1.2.0", "fast-deep-equal": "^3.1.3", "restructure": "^3.0.0", "tiny-inflate": "^1.0.3", "unicode-properties": "^1.4.0", "unicode-trie": "^2.0.0" } }, "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g=="], - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], @@ -1533,8 +1278,6 @@ "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], - "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], - "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], "google-auth-library": ["google-auth-library@10.6.2", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw=="], @@ -1553,56 +1296,18 @@ "h264-mp4-encoder": ["h264-mp4-encoder@1.0.12", "", {}, "sha512-xih3J+Go0o1RqGjhOt6TwXLWWGqLONRPyS8yoMu/RoS/S8WyEv4HuHp1KBsDDl8srZQ3gw9f95JYkCSjCuZbHQ=="], - "h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="], - "happy-dom": ["happy-dom@20.9.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ=="], "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], - "hast-util-embedded": ["hast-util-embedded@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-is-element": "^3.0.0" } }, "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA=="], - - "hast-util-format": ["hast-util-format@1.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-minify-whitespace": "^1.0.0", "hast-util-phrasing": "^3.0.0", "hast-util-whitespace": "^3.0.0", "html-whitespace-sensitive-tag-names": "^3.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA=="], - - "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], - - "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="], - - "hast-util-has-property": ["hast-util-has-property@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA=="], - - "hast-util-heading-rank": ["hast-util-heading-rank@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA=="], - - "hast-util-is-body-ok-link": ["hast-util-is-body-ok-link@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ=="], - - "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], - - "hast-util-minify-whitespace": ["hast-util-minify-whitespace@1.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-is-element": "^3.0.0", "hast-util-whitespace": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw=="], - - "hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], - - "hast-util-phrasing": ["hast-util-phrasing@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-has-property": "^3.0.0", "hast-util-is-body-ok-link": "^3.0.0", "hast-util-is-element": "^3.0.0" } }, "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ=="], - - "hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="], - - "hast-util-select": ["hast-util-select@6.0.4", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "bcp-47-match": "^2.0.0", "comma-separated-tokens": "^2.0.0", "css-selector-parser": "^3.0.0", "devlop": "^1.0.0", "direction": "^2.0.0", "hast-util-has-property": "^3.0.0", "hast-util-to-string": "^3.0.0", "hast-util-whitespace": "^3.0.0", "nth-check": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw=="], - - "hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="], - "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], - "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="], - - "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="], - - "hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="], - "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], - "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], "hono": ["hono@4.10.7", "", {}, "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw=="], @@ -1611,16 +1316,10 @@ "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], - "html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="], - "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], - "html-whitespace-sensitive-tag-names": ["html-whitespace-sensitive-tag-names@3.0.1", "", {}, "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA=="], - - "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], - "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], @@ -1629,8 +1328,6 @@ "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], - "i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="], - "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], @@ -1639,8 +1336,6 @@ "immutable": ["immutable@5.1.9", "", {}, "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg=="], - "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], @@ -1653,14 +1348,10 @@ "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], - "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], - "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], - "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], - "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -1709,8 +1400,6 @@ "jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="], - "js-base64": ["js-base64@3.7.7", "", {}, "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="], @@ -1741,14 +1430,6 @@ "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], - "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], - - "klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="], - - "lang-map": ["lang-map@0.4.0", "", { "dependencies": { "language-map": "^1.1.0" } }, "sha512-oiSqZIEUnWdFeDNsp4HId4tAxdFbx5iMBOwA3666Fn2L8Khj8NiD9xRvMsGmKXopPVkaDFtSv3CJOmXFUB0Hcg=="], - - "language-map": ["language-map@1.5.0", "", {}, "sha512-n7gFZpe+DwEAX9cXVTw43i3wiudWDDtSn28RmdnS/HCPr284dQI/SztsamWanRr75oSlKSaGbV2nmWCTzGCoVg=="], - "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], @@ -1777,18 +1458,18 @@ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - "lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="], + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], + "lucide-react": ["lucide-react@0.453.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ=="], + "luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], - "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], - "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], "marked": ["marked@17.0.1", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg=="], @@ -1799,10 +1480,6 @@ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - "mdast-util-definitions": ["mdast-util-definitions@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="], - - "mdast-util-directive": ["mdast-util-directive@3.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q=="], - "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], @@ -1819,8 +1496,6 @@ "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], - "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="], - "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="], "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="], @@ -1835,8 +1510,6 @@ "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], - "mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="], - "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], "merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="], @@ -1849,8 +1522,6 @@ "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], - "micromark-extension-directive": ["micromark-extension-directive@3.0.2", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "parse-entities": "^4.0.0" } }, "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA=="], - "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], @@ -1865,22 +1536,10 @@ "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], - "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q=="], - - "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.2", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ=="], - - "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="], - - "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="], - - "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="], - "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], - "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="], - "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], @@ -1901,8 +1560,6 @@ "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], - "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg=="], - "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], @@ -1927,8 +1584,6 @@ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], - "miniflare": ["miniflare@4.20260601.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.24.8", "workerd": "1.20260601.1", "ws": "8.20.1", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-56TFiulSEQu43cYxdXgCiA3U3i+Ls0NoXwJXd6DmpNsx8yl/1Il2T3DQ4CMXjR6yfE7CSvC5MuXaqcSAMREjgw=="], - "minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], @@ -1939,8 +1594,6 @@ "morphdom": ["morphdom@2.7.8", "", {}, "sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg=="], - "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "multicast-dns": ["multicast-dns@7.2.5", "", { "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" }, "bin": { "multicast-dns": "cli.js" } }, "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg=="], @@ -1955,17 +1608,13 @@ "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], - "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], - "netcdfjs": ["netcdfjs@3.0.0", "", { "dependencies": { "iobuffer": "^5.3.2" } }, "sha512-LOvT8KkC308qtpUkcBPiCMBtii7ZQCN6LxcVheWgyUeZ6DQWcpSRFV9dcVXLj/2eHZ/bre9tV5HTH4Sf93vrFw=="], - "nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], - "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], - "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], @@ -1973,12 +1622,8 @@ "node-html-parser": ["node-html-parser@7.1.0", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ=="], - "node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="], - "node-releases": ["node-releases@2.0.47", "", {}, "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og=="], - "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], @@ -1989,8 +1634,6 @@ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - "ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], - "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], @@ -2013,24 +1656,12 @@ "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=="], - "p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="], - - "p-queue": ["p-queue@8.1.1", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="], - - "p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="], - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], - - "pagefind": ["pagefind@1.5.2", "", { "optionalDependencies": { "@pagefind/darwin-arm64": "1.5.2", "@pagefind/darwin-x64": "1.5.2", "@pagefind/freebsd-x64": "1.5.2", "@pagefind/linux-arm64": "1.5.2", "@pagefind/linux-x64": "1.5.2", "@pagefind/windows-arm64": "1.5.2", "@pagefind/windows-x64": "1.5.2" }, "bin": { "pagefind": "lib/runner/bin.cjs" } }, "sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q=="], - "pako": ["pako@2.2.0", "", {}, "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w=="], "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], - "parse-latin": ["parse-latin@7.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "@types/unist": "^3.0.0", "nlcst-to-string": "^4.0.0", "unist-util-modify-children": "^4.0.0", "unist-util-visit-children": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ=="], - "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], @@ -2041,7 +1672,7 @@ "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], + "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -2049,8 +1680,6 @@ "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], - "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], @@ -2067,18 +1696,10 @@ "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], - "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], - - "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=="], - "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], - "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], - - "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], - "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], @@ -2087,8 +1708,6 @@ "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], - "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], @@ -2099,17 +1718,11 @@ "react-dom": ["react-dom@19.2.7", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.7" } }, "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ=="], - "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], + "react-markdown": ["react-markdown@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw=="], - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - - "recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="], - - "recma-jsx": ["recma-jsx@1.0.1", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" }, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w=="], + "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], - "recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="], - - "recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], @@ -2117,34 +1730,12 @@ "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], - "rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="], - - "rehype-autolink-headings": ["rehype-autolink-headings@7.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-is-element": "^3.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw=="], - - "rehype-expressive-code": ["rehype-expressive-code@0.41.7", "", { "dependencies": { "expressive-code": "^0.41.7" } }, "sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ=="], - - "rehype-format": ["rehype-format@5.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-format": "^1.0.0" } }, "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ=="], - - "rehype-parse": ["rehype-parse@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag=="], - - "rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="], - - "rehype-recma": ["rehype-recma@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "hast-util-to-estree": "^3.0.0" } }, "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw=="], - - "rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="], - - "remark-directive": ["remark-directive@3.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-directive": "^3.0.0", "micromark-extension-directive": "^3.0.0", "unified": "^11.0.0" } }, "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A=="], - "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], - "remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="], - "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="], - "remark-smartypants": ["remark-smartypants@3.0.2", "", { "dependencies": { "retext": "^9.0.0", "retext-smartypants": "^6.0.0", "unified": "^11.0.4", "unist-util-visit": "^5.0.0" } }, "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA=="], - "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], "remeda": ["remeda@2.26.0", "", { "dependencies": { "type-fest": "^4.41.0" } }, "sha512-lmNNwtaC6Co4m0WTTNoZ/JlpjEqAjPZO0+czC9YVRQUpkbS4x8Hmh+Mn9HPfJfiXqUQ5IXXgSXSOB2pBKAytdA=="], @@ -2153,16 +1744,6 @@ "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - "restructure": ["restructure@3.0.2", "", {}, "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw=="], - - "retext": ["retext@9.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "retext-latin": "^4.0.0", "retext-stringify": "^4.0.0", "unified": "^11.0.0" } }, "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA=="], - - "retext-latin": ["retext-latin@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "parse-latin": "^7.0.0", "unified": "^11.0.0" } }, "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA=="], - - "retext-smartypants": ["retext-smartypants@6.2.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ=="], - - "retext-stringify": ["retext-stringify@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unified": "^11.0.0" } }, "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA=="], - "rollup": ["rollup@4.61.0", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.61.0", "@rollup/rollup-android-arm64": "4.61.0", "@rollup/rollup-darwin-arm64": "4.61.0", "@rollup/rollup-darwin-x64": "4.61.0", "@rollup/rollup-freebsd-arm64": "4.61.0", "@rollup/rollup-freebsd-x64": "4.61.0", "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", "@rollup/rollup-linux-arm-musleabihf": "4.61.0", "@rollup/rollup-linux-arm64-gnu": "4.61.0", "@rollup/rollup-linux-arm64-musl": "4.61.0", "@rollup/rollup-linux-loong64-gnu": "4.61.0", "@rollup/rollup-linux-loong64-musl": "4.61.0", "@rollup/rollup-linux-ppc64-gnu": "4.61.0", "@rollup/rollup-linux-ppc64-musl": "4.61.0", "@rollup/rollup-linux-riscv64-gnu": "4.61.0", "@rollup/rollup-linux-riscv64-musl": "4.61.0", "@rollup/rollup-linux-s390x-gnu": "4.61.0", "@rollup/rollup-linux-x64-gnu": "4.61.0", "@rollup/rollup-linux-x64-musl": "4.61.0", "@rollup/rollup-openbsd-x64": "4.61.0", "@rollup/rollup-openharmony-arm64": "4.61.0", "@rollup/rollup-win32-arm64-msvc": "4.61.0", "@rollup/rollup-win32-ia32-msvc": "4.61.0", "@rollup/rollup-win32-x64-gnu": "4.61.0", "@rollup/rollup-win32-x64-msvc": "4.61.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g=="], "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], @@ -2177,13 +1758,11 @@ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], @@ -2195,8 +1774,6 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - "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=="], - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], @@ -2213,14 +1790,8 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], - "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "sitemap": ["sitemap@9.0.1", "", { "dependencies": { "@types/node": "^24.9.2", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.4.1" }, "bin": { "sitemap": "dist/esm/cli.js" } }, "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ=="], - - "smol-toml": ["smol-toml@1.6.1", "", {}, "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg=="], - "socket.io-client": ["socket.io-client@4.8.3", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-client": "~6.6.1", "socket.io-parser": "~4.2.4" } }, "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g=="], "socket.io-parser": ["socket.io-parser@4.2.6", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1" } }, "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg=="], @@ -2235,8 +1806,6 @@ "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], - "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], @@ -2247,8 +1816,6 @@ "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], - "stream-replace-string": ["stream-replace-string@2.0.0", "", {}, "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w=="], - "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], @@ -2263,8 +1830,6 @@ "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], - "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], - "swagger-ui-dist": ["swagger-ui-dist@5.32.8", "", { "dependencies": { "@scarf/scarf": "=1.4.0" } }, "sha512-dgMdWXIgnI4zX4OPhKEdWnlDODbgm8W3AX0Ivn/BBqcUh6xZsBxhZMnvk6DJyRz1BTrj8dPxtarmEGgkz30oyA=="], "synsci": ["synsci@workspace:tooling/launcher"], @@ -2279,8 +1844,6 @@ "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], - "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], @@ -2289,8 +1852,6 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - "toolbeam-docs-theme": ["toolbeam-docs-theme@0.4.8", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-b+5ynEFp4Woe5a22hzNQm42lD23t13ZMihVxHbzjA50zdcM9aOSJTIjdJ0PDSd4/50HbBXcpHiQsz6rM4N88ww=="], - "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "tree-sitter-bash": ["tree-sitter-bash@0.25.0", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-gZtlj9+qFS81qKxpLfD6H0UssQ3QBc/F0nKkPsiFDyfQF2YBqYvglFJUzchrPpVhZe9kLZTrJ9n2J6lmka69Vg=="], @@ -2301,8 +1862,6 @@ "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], - "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], @@ -2329,71 +1888,41 @@ "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - "ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="], - "ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="], - "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="], - - "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], - "undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], - "unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="], - - "unicode-properties": ["unicode-properties@1.4.1", "", { "dependencies": { "base64-js": "^1.3.0", "unicode-trie": "^2.0.0" } }, "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg=="], - - "unicode-trie": ["unicode-trie@2.0.0", "", { "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ=="], - "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], - "unifont": ["unifont@0.5.2", "", { "dependencies": { "css-tree": "^3.0.0", "ofetch": "^1.4.1", "ohash": "^2.0.0" } }, "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg=="], - - "unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="], - "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], - "unist-util-modify-children": ["unist-util-modify-children@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "array-iterate": "^2.0.0" } }, "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw=="], - "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], - "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], - - "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="], - "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], - "unist-util-visit-children": ["unist-util-visit-children@3.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA=="], - "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], "universal-user-agent": ["universal-user-agent@7.0.3", "", {}, "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A=="], "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="], - "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "upng-js": ["upng-js@2.1.0", "", { "dependencies": { "pako": "^1.0.5" } }, "sha512-d3xzZzpMP64YkjP5pr8gNyvBt7dLk/uGI67EctzDuVp4lCZyVMo0aJO6l/VDlgbInJYDY6cnClLoBp29eKWI6g=="], - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], - "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], - "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], "virtua": ["virtua@0.42.3", "", { "peerDependencies": { "react": ">=16.14.0", "react-dom": ">=16.14.0", "solid-js": ">=1.0", "svelte": ">=5.0", "vue": ">=3.2" }, "optionalPeers": ["react", "react-dom", "solid-js", "svelte", "vue"] }, "sha512-5FoAKcEvh05qsUF97Yz42SWJ7bwnPExjUYHGuoxz1EUtfWtaOgXaRwnylJbDpA0QcH1rKvJ2qsGRi9MK1fpQbg=="], - "vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="], + "vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], "vite-plugin-icons-spritesheet": ["vite-plugin-icons-spritesheet@3.0.1", "", { "dependencies": { "chalk": "^5.4.1", "glob": "^11.0.1", "node-html-parser": "^7.0.1", "tinyexec": "^0.3.2" }, "peerDependencies": { "vite": ">=5.2.0" } }, "sha512-Cr0+Z6wRMwSwKisWW9PHeTjqmQFv0jwRQQMc3YgAhAgZEe03j21el0P/CA31KN/L5eiL1LhR14VTXl96LetonA=="], @@ -2405,8 +1934,6 @@ "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], - "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="], @@ -2419,16 +1946,8 @@ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="], - "why-is-node-running": ["why-is-node-running@3.2.2", "", { "bin": { "why-is-node-running": "cli.js" } }, "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A=="], - "widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="], - - "workerd": ["workerd@1.20260601.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260601.1", "@cloudflare/workerd-darwin-arm64": "1.20260601.1", "@cloudflare/workerd-linux-64": "1.20260601.1", "@cloudflare/workerd-linux-arm64": "1.20260601.1", "@cloudflare/workerd-windows-64": "1.20260601.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Bg4+HF3B8TW0urAv8chiz25HSQ/aJxMBjgheUzu/nB1NQa+CaKGrUPv+Z3bf0np/WxLHYW1kcseVEtzZVPbX4g=="], - - "wrangler": ["wrangler@4.97.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260601.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260601.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260601.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-jzW/aNvjerV+4TmwbvwGY6lpcuBk7EFUTonMDNfci45wSmMTj2/OJN+83cc/CeepKdb+6ZjGJw9NRjmcQoxqRg=="], - "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], @@ -2441,64 +1960,32 @@ "xmlhttprequest-ssl": ["xmlhttprequest-ssl@2.1.2", "", {}, "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ=="], - "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="], - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - - "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], - - "yocto-spinner": ["yocto-spinner@0.2.3", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ=="], - - "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + "yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="], - "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], - - "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], - "zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="], - "zod-to-ts": ["zod-to-ts@1.2.0", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="], - "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@astrojs/cloudflare/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], - - "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - - "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.11", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.6", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.21.0", "smol-toml": "^1.6.0", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ=="], - - "@astrojs/sitemap/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - - "@astrojs/solid-js/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], - "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - - "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], - - "@expressive-code/plugin-shiki/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], - "@gitlab/gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@hey-api/openapi-ts/commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], "@hey-api/openapi-ts/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], + "@hey-api/openapi-ts/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "@hono/zod-validator/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@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=="], @@ -2541,19 +2028,15 @@ "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], - "@pierre/diffs/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], - - "@pierre/diffs/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ=="], - "@pierre/diffs/@shikijs/transformers": ["@shikijs/transformers@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/types": "3.19.0" } }, "sha512-e6vwrsyw+wx4OkcrDbL+FVCxwx8jgKiCoXzakVur++mIWVcgpzIi8vxf4/b4dVTYrV/nUx5RjinMf4tq8YV8Fw=="], "@pierre/diffs/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], "@pierre/diffs/shiki": ["shiki@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/engine-javascript": "3.19.0", "@shikijs/engine-oniguruma": "3.19.0", "@shikijs/langs": "3.19.0", "@shikijs/themes": "3.19.0", "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-77VJr3OR/VUZzPiStyRhADmO2jApMM0V2b1qf0RpfWya8Zr1PeZev5AEpPGAAKWdiYUtcZGBE4F5QvJml1PvWA=="], - "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "@shikijs/core/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], + "@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], "@shikijs/engine-oniguruma/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], @@ -2561,12 +2044,14 @@ "@shikijs/themes/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "@synsci/ui/@shikijs/transformers": ["@shikijs/transformers@3.9.2", "", { "dependencies": { "@shikijs/core": "3.9.2", "@shikijs/types": "3.9.2" } }, "sha512-MW5hT4TyUp6bNAgTExRYLk1NNasVQMTCw1kgbxHcEC0O5cbepPWaB+1k+JzW9r3SP2/R8kiens8/3E6hGKfgsA=="], + "@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA=="], - "@synsci/workspace/@shikijs/transformers": ["@shikijs/transformers@3.9.2", "", { "dependencies": { "@shikijs/core": "3.9.2", "@shikijs/types": "3.9.2" } }, "sha512-MW5hT4TyUp6bNAgTExRYLk1NNasVQMTCw1kgbxHcEC0O5cbepPWaB+1k+JzW9r3SP2/R8kiens8/3E6hGKfgsA=="], + "@synsci/ui/vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="], "@synsci/workspace/katex": ["katex@0.17.0", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw=="], + "@synsci/workspace/vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="], + "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -2583,31 +2068,15 @@ "accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], - "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=="], - - "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - - "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - - "astro/diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="], - - "astro/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], - - "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "astro/zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], - "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "glob/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], @@ -2621,9 +2090,7 @@ "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "miniflare/sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], - - "miniflare/undici": ["undici@7.24.8", "", {}, "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ=="], + "molstar/react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], @@ -2635,17 +2102,13 @@ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "path-scurry/lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="], - "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], - - "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], + "shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], "shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], @@ -2655,40 +2118,10 @@ "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], - "unicode-trie/pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="], - - "unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], - "upng-js/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "vite/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], - - "wrangler/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], - - "yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], - "zod-to-json-schema/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "zod-to-ts/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.6", "", {}, "sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q=="], - - "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], - "@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=="], @@ -2739,10 +2172,6 @@ "@octokit/rest/@octokit/core/before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], - "@pierre/diffs/@shikijs/core/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - - "@pierre/diffs/@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], - "@pierre/diffs/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA=="], "@pierre/diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], @@ -2757,21 +2186,13 @@ "@pierre/diffs/shiki/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], - "@synsci/ui/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA=="], - - "@synsci/ui/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.9.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-/M5L0Uc2ljyn2jKvj4Yiah7ow/W+DJSglVafvWAJ/b8AZDeeRAdMu3c2riDzB7N42VD+jSnWxeP9AKtd4TfYVw=="], - - "@synsci/workspace/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA=="], - - "@synsci/workspace/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.9.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-/M5L0Uc2ljyn2jKvj4Yiah7ow/W+DJSglVafvWAJ/b8AZDeeRAdMu3c2riDzB7N42VD+jSnWxeP9AKtd4TfYVw=="], + "@synsci/ui/vite/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], "@synsci/workspace/katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], - - "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@synsci/workspace/vite/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], - "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], @@ -2779,182 +2200,126 @@ "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], - - "miniflare/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], - - "miniflare/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], - - "miniflare/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], - - "miniflare/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], - - "miniflare/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], - - "miniflare/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], - - "miniflare/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], - - "miniflare/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], - - "miniflare/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], - - "miniflare/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], - - "miniflare/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], - - "miniflare/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], - - "miniflare/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], - - "miniflare/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], - - "miniflare/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], - - "miniflare/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], - - "miniflare/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], - - "miniflare/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], - - "miniflare/sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "unstorage/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], - - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], - - "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], - - "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], - - "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], - - "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], - - "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], - - "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], - - "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + "@octokit/graphql/@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + "@octokit/plugin-request-log/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.3", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag=="], - "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + "@octokit/plugin-request-log/@octokit/core/@octokit/request/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], - "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + "@octokit/plugin-request-log/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + "@octokit/rest/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.3", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag=="], - "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + "@octokit/rest/@octokit/core/@octokit/request/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], - "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + "@synsci/ui/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], - "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + "@synsci/ui/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], - "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + "@synsci/ui/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], - "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + "@synsci/ui/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], - "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + "@synsci/ui/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], - "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + "@synsci/ui/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], - "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + "@synsci/ui/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], - "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + "@synsci/ui/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], - "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], - "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], - "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], - "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], - "wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], - "wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], - "wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], - "wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], - "wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], + "@synsci/ui/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], - "wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + "@synsci/ui/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], - "wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + "@synsci/ui/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], - "wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + "@synsci/ui/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], - "wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + "@synsci/ui/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], - "wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + "@synsci/ui/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], - "wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + "@synsci/ui/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], - "wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + "@synsci/ui/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], - "wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + "@synsci/ui/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], - "wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + "@synsci/ui/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], - "wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + "@synsci/workspace/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], - "wrangler/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + "@synsci/workspace/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], - "wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + "@synsci/workspace/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], - "wrangler/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + "@synsci/workspace/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], - "wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], - "wrangler/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + "@synsci/workspace/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], - "wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + "@synsci/workspace/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], - "wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + "@synsci/workspace/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], - "wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], - "wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], - "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@synsci/workspace/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], - "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], - "@octokit/graphql/@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@synsci/workspace/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], - "@octokit/plugin-request-log/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.3", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag=="], + "@synsci/workspace/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], - "@octokit/plugin-request-log/@octokit/core/@octokit/request/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], - "@octokit/plugin-request-log/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@synsci/workspace/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], - "@octokit/rest/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.3", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag=="], + "@synsci/workspace/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], - "@octokit/rest/@octokit/core/@octokit/request/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], - "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@synsci/workspace/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], - "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@synsci/workspace/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], } } diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 5472014..0000000 --- a/docs/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# OpenScience docs - -Mintlify documentation for OpenScience. Preview locally with `npx mint dev` from this directory. -Hosted at https://openscience.sh/docs. diff --git a/docs/agents.mdx b/docs/agents.mdx deleted file mode 100644 index 6b2814f..0000000 --- a/docs/agents.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Agents" -description: "Configure and use specialized agents." -icon: "bot" -keywords: ["agents", "subagents", "research", "plan", "biology", "physics", "ml", "custom agents"] ---- - -Agents are specialized assistants configured for specific tasks and workflows. Each agent has its own prompt, model, and tool access. You can switch between agents during a session or invoke them with an `@` mention. - -## Types - -There are two types of agents in OpenScience: primary agents and subagents. - -### Primary agents - -Primary agents are the main assistants you interact with directly. Cycle through them with the **Tab** key, or your configured `switch_agent` keybind. Tool access is configured via [permissions](/permissions); for example, Research has all tools enabled while Plan is restricted. - -OpenScience comes with two built-in primary agents, **Research** (the default) and **Plan**, plus the domain specialists **Biology**, **Physics**, and **ML** that can run as either primary agents or subagents. - -### Subagents - -Subagents are specialized assistants that primary agents invoke for specific tasks. You can also invoke them manually by `@` mentioning them in a message. - -OpenScience ships with built-in subagents that primary agents invoke automatically for specialized work: task (general-purpose), explore, literature-review, critique, reviewer, physics-critique, and write. - -## Built-in agents - -### Research - -_Mode_: `primary` - -Research is the default primary agent with all tools enabled. It is the standard harness for scientific research work such as literature review, data analysis, GPU compute, and synthesis, with full access to file operations and system commands. - -### Biology, Physics, and ML - -_Mode_: `all` - -Domain specialists for computational biology, computational physics, and machine learning. Each ships with a task-specific workflow prompt and can be used as your primary agent or invoked as a subagent. - -### Plan - -_Mode_: `primary` - -A restricted agent for planning and analysis. By default, the following are set to `ask`: - -- File edits: all writes, patches, and edits -- `bash`: all shell commands - -Use it when you want the LLM to analyze code, suggest changes, or create plans without modifying anything. - -### Task - -_Mode_: `subagent` - -A general-purpose agent for researching complex questions and executing multi-step tasks. Has full tool access (except todo), so it can make file changes when needed. Use it to run multiple units of work in parallel. - -### Explore - -_Mode_: `subagent` - -A fast, read-only agent for exploring codebases. It cannot modify files. Use it to find files by patterns, search code for keywords, or answer questions about the codebase. - -## Usage - -1. For primary agents, use the **Tab** key to cycle through them during a session, or your configured `switch_agent` keybind. - -2. Subagents can be invoked: - - Automatically by primary agents, based on the subagent's description. - - Manually, by `@` mentioning a subagent in your message: - - ```text - @explore help me search for this function - ``` - -3. When subagents create their own child sessions, you can move between the parent session and its child sessions in the workspace. Cycle forward with the `session_child_cycle` keybind and backward with `session_child_cycle_reverse`. - -## Configure - -You can customize the built-in agents or create your own, in JSON or markdown. - -### JSON - -Configure agents in your `openscience.json` config file: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "agent": { - "research": { - "mode": "primary", - "model": "anthropic/claude-sonnet-4-5", - "prompt": "{file:./prompts/research.txt}", - "tools": { - "write": true, - "edit": true, - "bash": true - } - }, - "code-reviewer": { - "description": "Reviews code for best practices and potential issues", - "mode": "subagent", - "model": "anthropic/claude-sonnet-4-5", - "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", - "tools": { - "write": false, - "edit": false - } - } - } -} -``` - -### Markdown - -You can also define agents as markdown files. Place them in: - -- Global: `~/.config/openscience/agents/` -- Per project: `.openscience/agents/` - -```markdown ~/.config/openscience/agents/review.md ---- -description: Reviews code for quality and best practices -mode: subagent -model: anthropic/claude-sonnet-4-5 -temperature: 0.1 -tools: - write: false - edit: false - bash: false ---- - -You are in code review mode. Focus on: - -- Code quality and best practices -- Potential bugs and edge cases -- Performance implications -- Security considerations - -Provide constructive feedback without making direct changes. -``` - -The file name becomes the agent name: `review.md` creates a `review` agent. - -## Options - -### Description - -A brief description of what the agent does and when to use it. This is required: - -```json openscience.json -{ - "agent": { - "review": { - "description": "Reviews code for best practices and potential issues" - } - } -} -``` - -### Temperature - -Control the randomness of the LLM's responses. Lower values make responses more focused and deterministic; higher values increase variability: - -```json openscience.json -{ - "agent": { - "plan": { - "temperature": 0.1 - }, - "creative": { - "temperature": 0.8 - } - } -} -``` - -Typical ranges: - -- **0.0-0.2**: focused and deterministic, good for code analysis and planning -- **0.3-0.5**: balanced, good for general development tasks -- **0.6-1.0**: more varied, useful for brainstorming and exploration - -If no temperature is specified, OpenScience uses model-specific defaults: typically 0 for most models, 0.55 for Qwen models. - -### Max steps - -Limit the number of agentic iterations an agent can perform before it is forced to respond with text only. Useful for controlling costs: - -```json openscience.json -{ - "agent": { - "quick-thinker": { - "description": "Fast reasoning with limited iterations", - "prompt": "You are a quick thinker. Solve problems with minimal steps.", - "maxSteps": 5 - } - } -} -``` - -When the limit is reached, the agent receives a system prompt instructing it to summarize its work and list remaining tasks. If unset, the agent iterates until the model chooses to stop or you interrupt the session. - -### Disable - -Set `disable` to `true` to disable an agent: - -```json openscience.json -{ - "agent": { - "review": { - "disable": true - } - } -} -``` - -### Prompt - -Specify a custom system prompt file for the agent: - -```json openscience.json -{ - "agent": { - "review": { - "prompt": "{file:./prompts/code-review.txt}" - } - } -} -``` - -The path is relative to where the config file is located, so this works for both global and project config. - -### Model - -Override the model for a specific agent. Useful for using a faster model for planning and a more capable model for implementation: - -```json openscience.json -{ - "agent": { - "plan": { - "model": "anthropic/claude-haiku-4-5" - } - } -} -``` - -If you do not specify a model, primary agents use the [globally configured model](/config#models), and subagents use the model of the primary agent that invoked them. - -### Tools - -Control which tools are available to an agent by setting them to `true` or `false`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "tools": { - "write": true, - "bash": true - }, - "agent": { - "plan": { - "tools": { - "write": false, - "bash": false - } - } - } -} -``` - -Agent-specific config overrides the global config. You can use wildcards to control multiple tools at once, for example to disable all tools from an MCP server: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "agent": { - "readonly": { - "tools": { - "mymcp_*": false, - "write": false, - "edit": false - } - } - } -} -``` - -See [Tools](/tools). - -### Permissions - -Configure what actions an agent can take. Each permission resolves to `"ask"`, `"allow"`, or `"deny"`. Agent permissions are merged with the global config, and agent rules take precedence: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "edit": "deny" - }, - "agent": { - "research": { - "permission": { - "edit": "ask" - } - } - } -} -``` - -You can set permissions for specific bash commands with glob patterns. Since the last matching rule takes precedence, put the `*` wildcard first and specific rules after: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "agent": { - "research": { - "permission": { - "bash": { - "*": "ask", - "git status *": "allow" - } - } - } - } -} -``` - -Permissions also work in markdown agents: - -```markdown ~/.config/openscience/agents/review.md ---- -description: Code review without edits -mode: subagent -permission: - edit: deny - bash: - "*": ask - "git diff": allow - "git log*": allow - "grep *": allow - webfetch: deny ---- - -Only analyze code and suggest changes. -``` - -See [Permissions](/permissions). - -### Mode - -Control how the agent can be used with the `mode` option: `primary`, `subagent`, or `all`. Defaults to `all`: - -```json openscience.json -{ - "agent": { - "review": { - "mode": "subagent" - } - } -} -``` - -### Hidden - -Hide a subagent from the `@` autocomplete menu with `hidden: true`. Useful for internal subagents that should only be invoked programmatically by other agents via the task tool: - -```json openscience.json -{ - "agent": { - "internal-helper": { - "mode": "subagent", - "hidden": true - } - } -} -``` - -This only affects visibility in the autocomplete menu. Hidden agents can still be invoked by the model via the task tool if permissions allow. Only applies to `mode: subagent` agents. - -### Task permissions - -Control which subagents an agent can invoke via the task tool with `permission.task`. Uses glob patterns: - -```json openscience.json -{ - "agent": { - "orchestrator": { - "mode": "primary", - "permission": { - "task": { - "*": "deny", - "orchestrator-*": "allow", - "code-reviewer": "ask" - } - } - } - } -} -``` - -When set to `deny`, the subagent is removed from the task tool description entirely, so the model does not attempt to invoke it. - -Rules are evaluated in order and the last matching rule wins. In the example above, `orchestrator-planner` matches both `*` (deny) and `orchestrator-*` (allow); since `orchestrator-*` comes after `*`, the result is `allow`. - -Users can always invoke any subagent directly via the `@` autocomplete menu, even if the agent's task permissions would deny it. - -### Additional options - -Any other options in your agent configuration are passed through directly to the provider as model options. This lets you use provider-specific parameters: - -```json openscience.json -{ - "agent": { - "deep-thinker": { - "description": "Agent that uses high reasoning effort for complex problems", - "model": "openai/gpt-5", - "reasoningEffort": "high", - "textVerbosity": "low" - } - } -} -``` - -These options are model and provider specific. Run `openscience models` to list available models. - -## Create agents - -Create a new agent interactively: - -```bash -openscience agent create -``` - -This command: - -1. Asks where to save the agent: global or project-specific. -2. Asks for a description of what the agent should do. -3. Generates an appropriate system prompt and identifier. -4. Lets you select which tools the agent can access. -5. Creates a markdown file with the agent configuration. - -## Examples - -### Documentation agent - -```markdown ~/.config/openscience/agents/docs-writer.md ---- -description: Writes and maintains project documentation -mode: subagent -tools: - bash: false ---- - -You are a technical writer. Create clear, comprehensive documentation. - -Focus on: - -- Clear explanations -- Proper structure -- Code examples -- User-friendly language -``` - -### Security auditor - -```markdown ~/.config/openscience/agents/security-auditor.md ---- -description: Performs security audits and identifies vulnerabilities -mode: subagent -tools: - write: false - edit: false ---- - -You are a security expert. Focus on identifying potential security issues. - -Look for: - -- Input validation vulnerabilities -- Authentication and authorization flaws -- Data exposure risks -- Dependency vulnerabilities -- Configuration security issues -``` diff --git a/docs/atlas.mdx b/docs/atlas.mdx deleted file mode 100644 index 8e3f25e..0000000 --- a/docs/atlas.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: "Atlas" -description: "Synthetic Sciences' managed platform for OpenScience: curated models, wallet billing, and cloud compute." -icon: "cloud" -keywords: ["atlas", "connect login", "wallet", "billing", "managed", "byok", "synsci"] ---- - -Atlas is Synthetic Sciences' managed platform for OpenScience. It gives you: - -- **Curated models**: a tested set of frontier models, served through the managed `synsci` provider and billed from a prepaid wallet. -- **Research graph**: your sessions, runs, and findings organized into a durable research map. -- **Cloud compute**: managed GPU compute for training jobs and experiment runs. - - -Atlas is completely optional. Bring-your-own-key (BYOK) is free, first-class, and needs no account. Configure your own provider API keys and OpenScience works fully without Atlas. - - -## Sign in - -Authenticate the CLI with: - -```bash -openscience connect login -``` - -This opens your browser to approve the device; the CLI then stores a long-lived `thk_` API key locally. On headless or CI machines, create a key in the dashboard and pass it directly: - -```bash -openscience connect login --key thk_... -``` - -You can also set the key in the `SYNSC_CLI_KEY` environment variable for non-interactive use. Manage your devices, API keys, and billing at [app.syntheticsciences.ai](https://app.syntheticsciences.ai/cli). - -Check the connection at any time: - -```bash -openscience connect status -``` - -List authenticated devices with `openscience connect devices`, and disconnect with `openscience connect logout`. - -## The two credential stores - -OpenScience keeps two kinds of credentials, and it is worth understanding the difference: - -1. **Local provider keys (BYOK).** Keys you add with `openscience auth login` or the `/connect` command are stored locally in `~/.local/share/openscience/auth.json`. They stay on your machine and are never uploaded anywhere. Requests made with them go straight to the provider. - -2. **The Atlas session.** `openscience connect login` stores a `thk_` session key locally and syncs *down*: it pulls the credentials for services you have connected in the dashboard onto your machine, so a new machine is ready to work after a single login. Re-run the sync at any time: - - ```bash - openscience connect sync - ``` - -When both stores have a credential for the same provider, **your local key wins**. Synced managed credentials never override a key you set yourself, whether it came from `auth.json` or a shell export. Requests on your own keys are direct to the provider and never metered by Atlas. - -## Models - -Managed models are served through the `synsci` provider. The [model ID](/models) in your config uses the format `synsci/`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "model": "synsci/gpt-5-nano" -} -``` - -Run `/models` in the workspace to see the curated list. - -## Billing - -Atlas is billed from a prepaid wallet. Only **managed** calls, meaning requests running on Atlas-issued `thk_` credentials, draw from the wallet. Calls made with your own API keys (BYOK) or a first-party OAuth subscription (Claude Pro/Max, ChatGPT, GitHub Copilot) cost the wallet nothing and are never blocked by it. - -If your balance cannot cover a managed call, the session halts with an insufficient-credits message. Top up in the dashboard's Plan tab, or switch back to your own keys. - -Check your wallet balance and key routing from the CLI: - -```bash -openscience billing -``` - -And open the Plan tab to top up: - -```bash -openscience billing topup -``` - -Wallet top-ups are $50 or $200, one-time or recurring monthly. BYOK works on every plan. - -## Spend modes - -Key routing is per provider and automatic: your own key is used if one is set, otherwise the Atlas managed credential is used (and debits the wallet). You can pin the spend mode explicitly in your config: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "billing": { - "llm": "byok", - "compute": "byok" - } -} -``` - -- `llm`: `"managed"` bills LLM calls to your wallet; `"byok"` runs them on your own keys or subscriptions and is never billed. Unset means auto-detect from the resolved credential. -- `compute`: the same toggle for cloud compute. `"managed"` runs on Atlas-provisioned compute billed to your wallet; `"byok"` uses your own connected GPU providers. Defaults to `"byok"`. - -The spend toggle governs wallet gating, not which key is used. Key resolution (local key first, managed fallback) happens per provider; the `billing` setting controls whether managed usage is allowed to draw from the wallet. - -## BYOK - -You do not need an Atlas account to use OpenScience. Configure any [provider](/providers) with your own API key and all usage is billed by that provider directly, never by Synthetic Sciences. diff --git a/docs/cli.mdx b/docs/cli.mdx deleted file mode 100644 index 700b072..0000000 --- a/docs/cli.mdx +++ /dev/null @@ -1,465 +0,0 @@ ---- -title: "CLI reference" -description: "OpenScience CLI options, commands, and environment variables." -sidebarTitle: "CLI" -icon: "terminal" -keywords: ["cli", "commands", "flags", "environment variables", "run", "serve"] ---- - -The OpenScience CLI opens the workspace in your browser when run without any arguments: - -```bash -openscience -``` - -It also accepts the commands documented on this page, so you can interact with OpenScience programmatically: - -```bash -openscience run "Explain how closures work in JavaScript" -``` - -## workspace - -Open the OpenScience workspace in your browser: - -```bash -openscience [project] -``` - -### Flags - -| Flag | Short | Description | -| ------------ | ----- | ------------------------------------------ | -| `--continue` | `-c` | Continue the last session | -| `--session` | `-s` | Session ID to continue | -| `--prompt` | | Prompt to use | -| `--model` | `-m` | Model to use in the form of provider/model | -| `--agent` | | Agent to use | -| `--port` | | Port to listen on | -| `--hostname` | | Hostname to listen on | - -## Commands - -### agent - -Manage agents: - -```bash -openscience agent [command] -``` - -**create**: create a new agent with a custom system prompt and tool configuration. The command guides you through the setup: - -```bash -openscience agent create -``` - -**list**: list all available agents: - -```bash -openscience agent list -``` - -### auth - -Manage provider credentials: - -```bash -openscience auth [command] -``` - -**login**: configure API keys for any provider from the [Models.dev](https://models.dev) list. Credentials are stored locally in `~/.local/share/openscience/auth.json` and are never uploaded: - -```bash -openscience auth login -``` - -When OpenScience starts up it loads the providers from the credentials file, along with any keys defined in your environment or a `.env` file in your project. - -**list** (or `ls`): list authenticated providers and active provider environment variables: - -```bash -openscience auth list -``` - -**logout**: clear a provider from the credentials file: - -```bash -openscience auth logout -``` - -### connect - -Connect to the [Atlas](/atlas) dashboard: - -```bash -openscience connect [command] -``` - -**login**: authenticate the CLI with the dashboard. Opens your browser to approve the device; on headless or CI machines pass a key directly: - -```bash -openscience connect login -openscience connect login --key thk_... -``` - -| Flag | Description | -| -------------- | -------------------------------------------------------------- | -| `--key` | Paste a `thk_` API key directly (for headless or CI machines) | -| `--no-browser` | Skip the browser flow and paste a key manually | - -**status**: show connection status, backend, user, and synced services: - -```bash -openscience connect status -``` - -**sync**: pull credentials for dashboard-connected services down to this machine: - -```bash -openscience connect sync -``` - -**devices**: list authenticated devices: - -```bash -openscience connect devices -``` - -**logout**: disconnect from the dashboard: - -```bash -openscience connect logout -``` - -### billing - -Show your Atlas CLI wallet balance and how key routing works: - -```bash -openscience billing -``` - -**topup**: open the dashboard Plan tab to top up wallet credits: - -```bash -openscience billing topup -``` - -See [Atlas billing](/atlas#billing). - -### github - -Manage the GitHub agent for repository automation: - -```bash -openscience github [command] -``` - -**install**: install the GitHub agent in your repository. Sets up the GitHub Actions workflow and guides you through configuration: - -```bash -openscience github install -``` - -**run**: run the GitHub agent, typically from GitHub Actions: - -```bash -openscience github run -``` - -| Flag | Description | -| --------- | -------------------------------------- | -| `--event` | GitHub mock event to run the agent for | -| `--token` | GitHub personal access token | - -### mcp - -Manage Model Context Protocol servers: - -```bash -openscience mcp [command] -``` - -**add**: add a local or remote MCP server to your configuration: - -```bash -openscience mcp add -``` - -**list** (or `ls`): list configured MCP servers and their connection status: - -```bash -openscience mcp list -``` - -**auth**: authenticate with an OAuth-enabled MCP server. Without a server name, you are prompted to select from available OAuth-capable servers: - -```bash -openscience mcp auth [name] -openscience mcp auth list -``` - -**logout**: remove OAuth credentials for an MCP server: - -```bash -openscience mcp logout [name] -``` - -**debug**: debug OAuth connection issues for an MCP server: - -```bash -openscience mcp debug -``` - -See [MCP servers](/mcp-servers). - -### models - -List all available models from configured providers, in the format `provider/model`: - -```bash -openscience models [provider] -``` - -This is useful for figuring out the exact model name to use in [your config](/config). Pass a provider ID to filter: - -```bash -openscience models anthropic -``` - -| Flag | Description | -| ----------- | ------------------------------------------------------------- | -| `--refresh` | Refresh the models cache from Models.dev | -| `--verbose` | More verbose model output (includes metadata like costs) | - -Use `--refresh` when new models have been added to a provider and you want to see them in OpenScience. - -### run - -Run OpenScience in non-interactive mode by passing a prompt directly: - -```bash -openscience run [message..] -``` - -This is useful for scripting and automation: - -```bash -openscience run Explain the use of context in Go -``` - -You can attach to a running `openscience serve` instance to avoid MCP server cold boot times on every run: - -```bash -# Start a headless server in one terminal -openscience serve - -# In another terminal, run commands that attach to it -openscience run --attach http://localhost:4096 "Explain async/await in JavaScript" -``` - -| Flag | Short | Description | -| ------------ | ----- | ------------------------------------------------------------------ | -| `--command` | | The command to run, use message for args | -| `--continue` | `-c` | Continue the last session | -| `--session` | `-s` | Session ID to continue | -| `--share` | | Share the session | -| `--model` | `-m` | Model to use in the form of provider/model | -| `--agent` | | Agent to use | -| `--file` | `-f` | File(s) to attach to message | -| `--format` | | Format: default (formatted) or json (raw JSON events) | -| `--title` | | Title for the session (uses truncated prompt if no value provided) | -| `--attach` | | Attach to a running openscience server (e.g., http://localhost:4096) | -| `--port` | | Port for the local server (defaults to random port) | - -### serve - -Start a headless OpenScience server for API access: - -```bash -openscience serve -``` - -This starts an HTTP server that provides API access without a browser interface. Set `OPENSCIENCE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `openscience`). - -| Flag | Description | -| ------------ | ------------------------------------------ | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | -| `--mdns` | Enable mDNS discovery | -| `--cors` | Additional browser origin(s) to allow CORS | - -### session - -Manage OpenScience sessions: - -```bash -openscience session [command] -``` - -**list**: list all sessions: - -```bash -openscience session list -``` - -| Flag | Short | Description | -| ------------- | ----- | ------------------------------------ | -| `--max-count` | `-n` | Limit to N most recent sessions | -| `--format` | | Output format: table or json (table) | - -### stats - -Show token usage and cost statistics for your sessions: - -```bash -openscience stats -``` - -| Flag | Description | -| ----------- | ---------------------------------------------------------------------------- | -| `--days` | Show stats for the last N days (all time) | -| `--tools` | Number of tools to show (all) | -| `--models` | Show model usage breakdown (hidden by default). Pass a number to show top N | -| `--project` | Filter by project (all projects, empty string: current project) | - -### export - -Export session data as JSON: - -```bash -openscience export [sessionID] -``` - -If you do not provide a session ID, you are prompted to select from available sessions. - -### import - -Import session data from a JSON file or an OpenScience share URL: - -```bash -openscience import -``` - -```bash -openscience import session.json -openscience import https://syntheticsciences.ai/s/abc123 -``` - -### web - -Start a headless OpenScience server and open the web interface: - -```bash -openscience web -``` - -Set `OPENSCIENCE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `openscience`). - -| Flag | Description | -| ------------ | ------------------------------------------ | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | -| `--mdns` | Enable mDNS discovery | -| `--cors` | Additional browser origin(s) to allow CORS | - -### acp - -Start an ACP (Agent Client Protocol) server that communicates via stdin/stdout using nd-JSON: - -```bash -openscience acp -``` - -| Flag | Description | -| ------------ | --------------------- | -| `--cwd` | Working directory | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | - -### uninstall - -Uninstall OpenScience and remove all related files: - -```bash -openscience uninstall -``` - -| Flag | Short | Description | -| --------------- | ----- | ------------------------------------------- | -| `--keep-config` | `-c` | Keep configuration files | -| `--keep-data` | `-d` | Keep session data and snapshots | -| `--dry-run` | | Show what would be removed without removing | -| `--force` | `-f` | Skip confirmation prompts | - -### upgrade - -Update OpenScience to the latest version or a specific version: - -```bash -openscience upgrade [target] -``` - -```bash -openscience upgrade # latest -openscience upgrade v0.1.48 # specific version -``` - -| Flag | Short | Description | -| ---------- | ----- | ----------------------------------------------------------------- | -| `--method` | `-m` | The installation method that was used: curl, npm, pnpm, bun, brew | - -## Global flags - -| Flag | Short | Description | -| -------------- | ----- | ------------------------------------ | -| `--help` | `-h` | Display help | -| `--version` | `-v` | Print version number | -| `--print-logs` | | Print logs to stderr | -| `--log-level` | | Log level (DEBUG, INFO, WARN, ERROR) | - -## Environment variables - -| Variable | Type | Description | -| ---------------------------------------- | ------- | ---------------------------------------------------- | -| `OPENSCIENCE_AUTO_SHARE` | boolean | Automatically share sessions | -| `OPENSCIENCE_GIT_BASH_PATH` | string | Path to Git Bash executable on Windows | -| `OPENSCIENCE_CONFIG` | string | Path to config file | -| `OPENSCIENCE_CONFIG_DIR` | string | Path to config directory | -| `OPENSCIENCE_CONFIG_CONTENT` | string | Inline JSON config content | -| `OPENSCIENCE_DISABLE_AUTOUPDATE` | boolean | Disable automatic update checks | -| `OPENSCIENCE_DISABLE_PRUNE` | boolean | Disable pruning of old data | -| `OPENSCIENCE_DISABLE_TERMINAL_TITLE` | boolean | Disable automatic terminal title updates | -| `OPENSCIENCE_PERMISSION` | string | Inline JSON permissions config | -| `OPENSCIENCE_DISABLE_DEFAULT_PLUGINS` | boolean | Disable default plugins | -| `OPENSCIENCE_DISABLE_LSP_DOWNLOAD` | boolean | Disable automatic LSP server downloads | -| `OPENSCIENCE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models | -| `OPENSCIENCE_DISABLE_AUTOCOMPACT` | boolean | Disable automatic context compaction | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE` | boolean | Disable reading from `.claude` (prompt + skills) | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Disable reading `~/.claude/CLAUDE.md` | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Disable loading `.claude/skills` | -| `OPENSCIENCE_CLIENT` | string | Client identifier (defaults to `cli`) | -| `OPENSCIENCE_ENABLE_EXA` | boolean | Enable Exa web search tools | -| `OPENSCIENCE_SERVER_PASSWORD` | string | Enable basic auth for `serve`/`web` | -| `OPENSCIENCE_SERVER_USERNAME` | string | Override basic auth username (default `openscience`) | - -### Experimental - -These environment variables enable experimental features that may change or be removed: - -| Variable | Type | Description | -| -------------------------------------------------- | ------- | ---------------------------------------- | -| `OPENSCIENCE_EXPERIMENTAL` | boolean | Enable all experimental features | -| `OPENSCIENCE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Enable icon discovery | -| `OPENSCIENCE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Disable copy on select | -| `OPENSCIENCE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Default timeout for bash commands in ms | -| `OPENSCIENCE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Max output tokens for LLM responses | -| `OPENSCIENCE_EXPERIMENTAL_FILEWATCHER` | boolean | Enable file watcher for entire dir | -| `OPENSCIENCE_EXPERIMENTAL_OXFMT` | boolean | Enable oxfmt formatter | -| `OPENSCIENCE_EXPERIMENTAL_LSP_TOOL` | boolean | Enable experimental LSP tool | -| `OPENSCIENCE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Disable file watcher | -| `OPENSCIENCE_EXPERIMENTAL_EXA` | boolean | Enable experimental Exa features | -| `OPENSCIENCE_EXPERIMENTAL_LSP_TY` | boolean | Enable experimental LSP type checking | -| `OPENSCIENCE_EXPERIMENTAL_MARKDOWN` | boolean | Enable experimental markdown features | -| `OPENSCIENCE_EXPERIMENTAL_PLAN_MODE` | boolean | Enable plan mode | diff --git a/docs/config.mdx b/docs/config.mdx deleted file mode 100644 index 834a8d6..0000000 --- a/docs/config.mdx +++ /dev/null @@ -1,475 +0,0 @@ ---- -title: "Config" -description: "Configure OpenScience with the openscience.json config file." -icon: "settings" -keywords: ["config", "openscience.json", "jsonc", "schema", "precedence"] ---- - -You can configure OpenScience using a JSON config file. - -## Format - -OpenScience supports both JSON and JSONC (JSON with comments): - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - // Theme configuration - "theme": "openscience", - "model": "anthropic/claude-sonnet-4-5", - "autoupdate": true, -} -``` - -The config file has a schema defined at [`openscience.sh/config.json`](https://openscience.sh/config.json). Your editor can validate and autocomplete based on the schema. - -## Locations - -Config files are merged together, not replaced. Later configs override earlier ones only for conflicting keys; non-conflicting settings from all configs are preserved. - -Config sources are loaded in this order (later sources override earlier ones): - -1. Remote config (from `.well-known/openscience`): organizational defaults -2. Global config (`~/.config/openscience/openscience.json`): user preferences -3. Custom config (`OPENSCIENCE_CONFIG` env var): custom overrides -4. Project config (`openscience.json` in project): project-specific settings -5. `.openscience` directories: agents, commands, plugins -6. Inline config (`OPENSCIENCE_CONFIG_CONTENT` env var): runtime overrides - - -The `.openscience` and `~/.config/openscience` directories use plural names for subdirectories: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, and `themes/`. Singular names (for example `agent/`) are also supported for backwards compatibility. - - -### Remote - -Organizations can provide default configuration via a `.well-known/openscience` endpoint. It is fetched automatically when you authenticate with a provider that supports it, and serves as the base layer that all other config sources can override. - -For example, if your organization provides MCP servers that are disabled by default, you can enable specific servers in your local config: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - -### Global - -Place your global config in `~/.config/openscience/openscience.json`. Use it for user-wide preferences like themes, providers, or your default model. - -### Per project - -Add `openscience.json` in your project root. Project config has the highest precedence among standard config files. When OpenScience starts, it looks for a config file in the current directory and traverses up to the nearest Git directory. - -Project config is safe to check into Git and uses the same schema as the global one. - -### Custom path - -Specify a custom config file path with the `OPENSCIENCE_CONFIG` environment variable: - -```bash -export OPENSCIENCE_CONFIG=/path/to/my/custom-config.json -openscience run "Hello world" -``` - -Custom config is loaded between global and project configs. - -### Custom directory - -Specify a custom config directory with `OPENSCIENCE_CONFIG_DIR`. It is searched for agents, commands, modes, and plugins just like the standard `.openscience` directory, and follows the same structure: - -```bash -export OPENSCIENCE_CONFIG_DIR=/path/to/my/config-directory -openscience run "Hello world" -``` - -The custom directory is loaded after the global config and `.openscience` directories, so it can override their settings. - -## Options - -### Models - -Configure providers and models through the `provider`, `model`, and `small_model` options: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "provider": {}, - "model": "anthropic/claude-sonnet-4-5", - "small_model": "anthropic/claude-haiku-4-5" -} -``` - -The `small_model` option configures a separate model for lightweight tasks like title generation. By default, OpenScience tries to use a cheaper model from your provider if one is available, otherwise it falls back to your main model. - -Provider options can include `timeout` and `setCacheKey`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "anthropic": { - "options": { - "timeout": 600000, - "setCacheKey": true - } - } - } -} -``` - -- `timeout`: request timeout in milliseconds (default: 300000). Set to `false` to disable. -- `setCacheKey`: ensure a cache key is always set for the provider. - -See [Models](/models) and [Providers](/providers) for details, including provider-specific options like the AWS `region`, `profile`, and `endpoint` settings for [Amazon Bedrock](/providers#amazon-bedrock). - -### Themes - -Set the workspace theme through the `theme` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "theme": "tokyonight" -} -``` - -See [Themes](/themes). - -### Agents - -Configure specialized agents through the `agent` option: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "agent": { - "code-reviewer": { - "description": "Reviews code for best practices and potential issues", - "model": "anthropic/claude-sonnet-4-5", - "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", - "tools": { - // Disable file modification tools for review-only agent - "write": false, - "edit": false, - }, - }, - }, -} -``` - -You can also define agents using markdown files in `~/.config/openscience/agents/` or `.openscience/agents/`. See [Agents](/agents). - -### Default agent - -Set the default agent with the `default_agent` option. This determines which agent is used when none is explicitly specified: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "default_agent": "plan" -} -``` - -The default agent must be a primary agent (not a subagent). It can be a built-in agent like `"research"`, `"biology"`, `"physics"`, `"ml"`, or `"plan"`, or a [custom agent](/agents) you have defined. If the specified agent does not exist or is a subagent, OpenScience falls back to `"research"` with a warning. - -This setting applies across all interfaces: the browser workspace, the CLI (`openscience run`), and the GitHub agent. - -### Permissions - -By default, OpenScience allows all operations without requiring explicit approval. Change this with the `permission` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "edit": "ask", - "bash": "ask" - } -} -``` - -See [Permissions](/permissions). - -### Sharing - -Configure the [share](/share) feature through the `share` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "share": "manual" -} -``` - -- `"manual"`: allow manual sharing via commands (default) -- `"auto"`: automatically share new conversations -- `"disabled"`: disable sharing entirely - -### Commands - -Configure custom commands for repetitive tasks through the `command` option: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "command": { - "test": { - "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", - "description": "Run tests with coverage", - "agent": "research", - "model": "anthropic/claude-haiku-4-5", - }, - "component": { - "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", - "description": "Create a new component", - }, - }, -} -``` - -You can also define commands using markdown files in `~/.config/openscience/commands/` or `.openscience/commands/`. - -### Server - -Configure the `openscience serve` and `openscience web` commands through the `server` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "server": { - "port": 4096, - "hostname": "0.0.0.0", - "mdns": true, - "cors": ["http://localhost:5173"] - } -} -``` - -- `port`: port to listen on. -- `hostname`: hostname to listen on. When `mdns` is enabled and no hostname is set, defaults to `0.0.0.0`. -- `mdns`: enable mDNS service discovery so other devices on the network can discover your OpenScience server. -- `cors`: additional origins to allow for CORS when using the HTTP server from a browser-based client. Values must be full origins (scheme + host + optional port), for example `https://app.example.com`. - -### Autoupdate - -OpenScience automatically downloads new updates when it starts up. Disable this with the `autoupdate` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "autoupdate": false -} -``` - -Set `autoupdate` to `"notify"` to be notified about new versions without installing them. This only works if OpenScience was not installed with a package manager. - -### Formatters - -Configure code formatters through the `formatter` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "formatter": { - "prettier": { - "disabled": true - }, - "custom-prettier": { - "command": ["npx", "prettier", "--write", "$FILE"], - "environment": { - "NODE_ENV": "development" - }, - "extensions": [".js", ".ts", ".jsx", ".tsx"] - } - } -} -``` - -### Compaction - -Control context compaction behavior through the `compaction` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "compaction": { - "auto": true, - "prune": true - } -} -``` - -- `auto`: automatically compact the session when context is full (default: `true`). -- `prune`: remove old tool outputs to save tokens (default: `true`). - -### Watcher - -Configure file watcher ignore patterns through the `watcher` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "watcher": { - "ignore": ["node_modules/**", "dist/**", ".git/**"] - } -} -``` - -Patterns follow glob syntax. Use this to exclude noisy directories from file watching. - -### MCP servers - -Configure MCP servers through the `mcp` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": {} -} -``` - -See [MCP servers](/mcp-servers). - -### Plugins - -Plugins extend OpenScience with custom tools, hooks, and integrations. Place plugin files in `.openscience/plugins/` or `~/.config/openscience/plugins/`, or load plugins from npm through the `plugin` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "plugin": ["openscience-helicone-session", "@my-org/custom-plugin"] -} -``` - -### Instructions - -Configure instruction files for the model through the `instructions` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] -} -``` - -This takes an array of paths and glob patterns to instruction files. See [Rules](/rules). - -### Billing - -If you use [Atlas](/atlas), pin the spend mode explicitly through the `billing` option: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "billing": { - "llm": "byok", - "compute": "byok" - } -} -``` - -- `llm`: `"managed"` bills LLM calls to your Atlas wallet; `"byok"` uses your own provider keys or subscriptions and is never billed. Unset means auto-detect from the resolved credential. -- `compute`: the same toggle for cloud compute. Defaults to `"byok"`. - -See [Atlas](/atlas#spend-modes). - -### Disabled providers - -Disable providers that are loaded automatically through the `disabled_providers` option. This prevents providers from being loaded even if their credentials are available: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "disabled_providers": ["openai", "gemini"] -} -``` - -When a provider is disabled: - -- It is not loaded even if environment variables are set. -- It is not loaded even if API keys are configured through the `/connect` command. -- The provider's models do not appear in the model selection list. - -### Enabled providers - -Specify an allowlist of providers through the `enabled_providers` option. When set, only the specified providers are enabled and all others are ignored: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "enabled_providers": ["anthropic", "openai"] -} -``` - - -If a provider appears in both `enabled_providers` and `disabled_providers`, `disabled_providers` takes priority. - - -### Experimental - -The `experimental` key contains options that are under active development: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "experimental": {} -} -``` - - -Experimental options are not stable. They may change or be removed without notice. - - -## Variables - -You can use variable substitution in config files to reference environment variables and file contents. - -### Env vars - -Use `{env:VARIABLE_NAME}` to substitute environment variables: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "model": "{env:OPENSCIENCE_MODEL}", - "provider": { - "anthropic": { - "models": {}, - "options": { - "apiKey": "{env:ANTHROPIC_API_KEY}" - } - } - } -} -``` - -If the environment variable is not set, it is replaced with an empty string. - -### Files - -Use `{file:path/to/file}` to substitute the contents of a file: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "instructions": ["./custom-instructions.md"], - "provider": { - "openai": { - "options": { - "apiKey": "{file:~/.secrets/openai-key}" - } - } - } -} -``` - -File paths can be relative to the config file directory, or absolute paths starting with `/` or `~`. - -These are useful for keeping sensitive data like API keys in separate files, including large instruction files without cluttering your config, and sharing common configuration snippets across multiple config files. diff --git a/docs/contributing.mdx b/docs/contributing.mdx deleted file mode 100644 index 8898266..0000000 --- a/docs/contributing.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "Contributing" -description: "How to contribute to OpenScience." -icon: "git-pull-request" -keywords: ["contributing", "development", "bun", "build", "pull requests"] ---- - -OpenScience is open source under the Apache 2.0 license. Contributions are welcome. The full guide lives in [CONTRIBUTING.md](https://github.com/synthetic-sciences/openscience/blob/main/CONTRIBUTING.md) in the repository. - -## What to contribute - -These changes are the most likely to be merged: - -- Bug fixes -- New LSPs and formatters -- Better model performance -- Support for new providers -- Fixes for environment-specific quirks -- Missing standard behavior -- Documentation improvements - -Any UI or core product feature should go through a design discussion with the maintainers before you build it. If you are not sure whether a change would be accepted, ask in an issue or look for issues labeled [`help wanted`](https://github.com/synthetic-sciences/openscience/issues?q=is%3Aissue+state%3Aopen+label%3A%22help+wanted%22) or [`good first issue`](https://github.com/synthetic-sciences/openscience/issues?q=is%3Aissue+state%3Aopen+label%3A%22good+first+issue%22). - -## Repository layout - -The repo is a single Git repository, organized by runtime boundary, with `main` as the default branch: - -| Path | Contents | -| ----------- | --------------------------------------------------------------------- | -| `frontend/` | Workspace (browser UI), docs/share site, and shared UI | -| `backend/` | CLI/server, skills, sessions, and provider integrations | -| `tooling/` | SDK, plugin runtime, repo automation, launcher, utilities, and patches | - -## Development - -You need [Bun](https://bun.sh) 1.3 or newer. Install dependencies and run the CLI from source: - -```bash -bun install -bun dev -``` - -`bun dev` is the local equivalent of the built `openscience` command. It runs against the `backend/cli` directory by default. To run it elsewhere: - -```bash -bun dev # run in a specific directory -bun dev . # run in the repo root -``` - -Common commands work the same in dev and in the built binary: - -```bash -bun dev --help # list commands -bun dev serve # headless API server (port 4096 by default) -bun dev web # start the server and open the workspace -``` - -Typecheck and test: - -```bash -bun run typecheck -bun run --cwd backend/cli test -``` - -## Building a standalone binary - -```bash -./backend/cli/script/build.ts --single -./backend/cli/dist/@synsci/openscience-/bin/openscience -``` - -Replace `` with your platform, for example `darwin-arm64` or `linux-x64`. diff --git a/docs/docs.json b/docs/docs.json deleted file mode 100644 index 888fb9b..0000000 --- a/docs/docs.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "$schema": "https://mintlify.com/docs.json", - "theme": "mint", - "name": "OpenScience", - "colors": { - "primary": "#0d9488", - "light": "#14b8a6", - "dark": "#0d9488" - }, - "logo": { - "light": "/images/wordmark.svg", - "dark": "/images/wordmark.svg", - "href": "https://openscience.sh" - }, - "favicon": "/favicon.svg", - "appearance": { - "default": "dark" - }, - "navbar": { - "links": [ - { - "type": "github", - "href": "https://github.com/synthetic-sciences/openscience" - } - ] - }, - "navigation": { - "global": { - "anchors": [ - { - "anchor": "GitHub", - "icon": "github", - "href": "https://github.com/synthetic-sciences/openscience" - }, - { - "anchor": "npm", - "icon": "package", - "href": "https://www.npmjs.com/package/@synsci/openscience" - } - ] - }, - "groups": [ - { - "group": "Getting started", - "pages": ["index", "installation"] - }, - { - "group": "Configuration", - "pages": ["config", "models", "providers", "permissions", "rules", "themes"] - }, - { - "group": "Agents and tools", - "pages": ["agents", "tools", "mcp-servers", "skills"] - }, - { - "group": "Platform", - "pages": ["atlas", "share"] - }, - { - "group": "Reference", - "pages": ["cli", "troubleshooting", "contributing"] - } - ] - }, - "footer": { - "socials": { - "github": "https://github.com/synthetic-sciences/openscience" - } - } -} diff --git a/docs/favicon.svg b/docs/favicon.svg deleted file mode 100644 index 7410f40..0000000 --- a/docs/favicon.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - diff --git a/docs/images/wordmark.svg b/docs/images/wordmark.svg deleted file mode 100644 index 9f294c9..0000000 --- a/docs/images/wordmark.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - ██████╗ ██████╗ ███████╗███╗ ██╗ - ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ - ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ - ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ - ╚██████╔╝██║ ███████╗██║ ╚████║ - ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ - ███████╗ ██████╗██╗███████╗███╗ ██╗ ██████╗███████╗ - ██╔════╝██╔════╝██║██╔════╝████╗ ██║██╔════╝██╔════╝ - ███████╗██║ ██║█████╗ ██╔██╗ ██║██║ █████╗ - ╚════██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██╔══╝ - ███████║╚██████╗██║███████╗██║ ╚████║╚██████╗███████╗ - ╚══════╝ ╚═════╝╚═╝╚══════╝╚═╝ ╚═══╝ ╚═════╝╚══════╝ - diff --git a/docs/index.mdx b/docs/index.mdx deleted file mode 100644 index 33d54da..0000000 --- a/docs/index.mdx +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: "Introduction" -description: "Get started with OpenScience, the open-source AI workbench for scientific research." -sidebarTitle: "Introduction" -icon: "rocket" -keywords: ["openscience", "quickstart", "getting started", "ai research agent"] ---- - -OpenScience is an open-source, model-agnostic AI research agent. You give it a goal, and it reads the relevant literature, forms a hypothesis, writes and runs code, runs the experiments, and writes up the result. Running `openscience` opens a workspace in your browser. It also has a [CLI](/cli) for scripting. - -It works with any frontier or open-weight model from Anthropic, OpenAI, Google, and dozens of other providers, using your own API keys. No account is required. - -## Install - -The quickest way to install OpenScience is the install script: - -```bash -curl -fsSL https://openscience.sh/install | bash -``` - -Or install it with npm: - -```bash -npm install -g @synsci/openscience -``` - -Both install the `openscience` command. To install and open the workspace in a single step, run the launcher instead: - -```bash -npx synsci -``` - -See [Installation](/installation) for other package managers, Windows, and platform binaries. - -## Quickstart - - - - Set an API key from any provider (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, and so on) in your shell: - - ```bash - export ANTHROPIC_API_KEY=sk-ant-... - ``` - - You can also add keys from the Credentials panel in the workspace, or with the `/connect` command. Keys stay on your machine and requests go straight to the provider. See [Providers](/providers) for the full list. - - - Navigate to a project and run OpenScience: - - ```bash - cd /path/to/project - openscience - ``` - - This opens the workspace in your browser. Pick a model with the `/models` command. - - - Run the `/init` command in the workspace: - - ```text - /init - ``` - - This analyzes your project and creates an `AGENTS.md` file in the project root. It helps OpenScience understand the project structure and the patterns used. Commit it to Git so your team shares the same context. See [Rules](/rules). - - - Ask it anything. Use the `@` key to fuzzy-search for files in the project: - - ```text - How is authentication handled in @packages/functions/src/api/index.ts - ``` - - - - -If you are new to LLM providers, [Atlas](/atlas) is Synthetic Sciences' optional managed platform with a curated set of tested models billed from a prepaid wallet. Bring-your-own-key usage is free, first-class, and needs no account. - - -## Working with OpenScience - -### Plan first - -OpenScience has a plan mode that turns off its ability to make changes and instead suggests how it will approach the work. Switch to it with the mode selector in the workspace, describe what you want, then iterate on the plan: - -```text -When a user deletes a note, flag it as deleted in the database. -Then create a screen that shows all the recently deleted notes. -``` - -Once you are comfortable with the plan, switch back to the research agent and ask it to make the changes. You can drag and drop images into the workspace to add them to a prompt. - -### Make changes directly - -For straightforward changes, skip the plan and describe the change with enough context: - -```text -We need to add authentication to the /settings route. Take a look at how this is -handled in the /notes route in @packages/functions/src/notes.ts and implement -the same logic in @packages/functions/src/settings.ts -``` - -### Undo and redo - -If a change is not what you wanted, revert it with the `/undo` command: - -```text -/undo -``` - -You can run `/undo` multiple times to step back through changes, and `/redo` to reapply them. - -### Share a session - -Conversations can be [shared with your team](/share): - -```text -/share -``` - -This creates a link to the current conversation and copies it to your clipboard. Conversations are not shared by default. - -## Next steps - - - - Configure OpenScience with the openscience.json config file. - - - Pick a model and set a default. - - - Use the built-in research agents or create your own. - - - Commands, flags, and environment variables. - - diff --git a/docs/installation.mdx b/docs/installation.mdx deleted file mode 100644 index b2798de..0000000 --- a/docs/installation.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: "Installation" -description: "Install OpenScience on Linux, macOS, or Windows." -icon: "download" -keywords: ["install", "npm", "curl", "binary", "windows", "upgrade", "uninstall"] ---- - -OpenScience ships as native binaries for Linux, macOS, and Windows. All of the methods below install the `openscience` command. - -## Install script - -On Linux and macOS, the install script downloads the right binary for your platform and adds it to your `PATH`: - -```bash -curl -fsSL https://openscience.sh/install | bash -``` - -To install a specific version: - -```bash -curl -fsSL https://openscience.sh/install | bash -s -- --version 1.0.180 -``` - -Pass `--no-modify-path` if you do not want the script to touch your shell config files. - -## Package managers - - - - ```bash - npm install -g @synsci/openscience - ``` - - - ```bash - bun install -g @synsci/openscience - ``` - - - ```bash - pnpm install -g @synsci/openscience - ``` - - - ```bash - yarn global add @synsci/openscience - ``` - - - -## Launcher - -To install and open the workspace in a single step, run the launcher: - -```bash -npx synsci -``` - -## Windows - -Install with npm: - -```bash -npm install -g @synsci/openscience -``` - -Support for installing OpenScience on Windows using Bun is in progress. - - -Mise (`mise use -g github:synthetic-sciences/openscience`) is a community-maintained install method and is not tested by the OpenScience team. - - -## Binaries - -Platform binaries are attached to each [GitHub release](https://github.com/synthetic-sciences/openscience/releases). Download the archive for your platform, extract it, and put the `openscience` binary on your `PATH`. - -## Upgrade - -OpenScience checks for updates on startup by default. To upgrade manually: - -```bash -openscience upgrade -``` - -To upgrade to a specific version: - -```bash -openscience upgrade v0.1.48 -``` - -You can disable automatic updates with the [`autoupdate` config option](/config#autoupdate). - -## Uninstall - -To remove OpenScience and its data: - -```bash -openscience uninstall -``` - -Pass `--keep-config` to keep configuration files or `--keep-data` to keep session data. Use `--dry-run` to see what would be removed first. See the [CLI reference](/cli#uninstall) for all flags. diff --git a/docs/mcp-servers.mdx b/docs/mcp-servers.mdx deleted file mode 100644 index 51cf0ac..0000000 --- a/docs/mcp-servers.mdx +++ /dev/null @@ -1,408 +0,0 @@ ---- -title: "MCP servers" -description: "Add local and remote MCP tools." -icon: "server" -keywords: ["mcp", "model context protocol", "oauth", "remote servers", "local servers"] ---- - -You can add external tools to OpenScience using the Model Context Protocol (MCP). OpenScience supports both local and remote servers. Once added, MCP tools are automatically available to the LLM alongside built-in tools. - - -Every MCP server adds to the context. Certain servers, like the GitHub MCP server, add a lot of tokens and can easily exceed the context limit. Be selective about which servers you enable. - - -## Enable - -Define MCP servers in your [OpenScience config](/config) under `mcp`. Add each server with a unique name; you can refer to that name when prompting the LLM: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "name-of-mcp-server": { - // ... - "enabled": true, - }, - "name-of-other-mcp-server": { - // ... - }, - }, -} -``` - -Set `enabled` to `false` to temporarily disable a server without removing it from your config. - -You can also add servers interactively with `openscience mcp add`, and list them with `openscience mcp list`. See the [CLI reference](/cli#mcp). - -### Overriding remote defaults - -Organizations can provide default MCP servers via their `.well-known/openscience` endpoint. These servers may be disabled by default, letting users opt in to the ones they need. To enable a server from your organization's remote config, add it to your local config with `enabled: true`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - -Your local config values override the remote defaults. See [config precedence](/config#locations). - -## Local - -Add local MCP servers by setting `type` to `"local"`: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-local-mcp-server": { - "type": "local", - // Or ["bun", "x", "my-mcp-command"] - "command": ["npx", "-y", "my-mcp-command"], - "enabled": true, - "environment": { - "MY_ENV_VAR": "my_env_var_value", - }, - }, - }, -} -``` - -The command is how the local MCP server is started, and `environment` passes environment variables to it. - -For example, here is the test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) server: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "mcp_everything": { - "type": "local", - "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], - }, - }, -} -``` - -To use it, mention it in your prompt: - -```text -use the mcp_everything tool to add the number 3 and 4 -``` - -### Options - -| Option | Type | Required | Description | -| ------------- | ------- | -------- | ------------------------------------------------------------------------------------ | -| `type` | String | Yes | Type of MCP server connection, must be `"local"`. | -| `command` | Array | Yes | Command and arguments to run the MCP server. | -| `environment` | Object | | Environment variables to set when running the server. | -| `enabled` | Boolean | | Enable or disable the MCP server on startup. | -| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). | - -## Remote - -Add remote MCP servers by setting `type` to `"remote"`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-remote-mcp": { - "type": "remote", - "url": "https://my-mcp-server.com", - "enabled": true, - "headers": { - "Authorization": "Bearer MY_API_KEY" - } - } - } -} -``` - -### Options - -| Option | Type | Required | Description | -| --------- | --------------- | -------- | ------------------------------------------------------------------------------------ | -| `type` | String | Yes | Type of MCP server connection, must be `"remote"`. | -| `url` | String | Yes | URL of the remote MCP server. | -| `enabled` | Boolean | | Enable or disable the MCP server on startup. | -| `headers` | Object | | Headers to send with the request. | -| `oauth` | Object \| false | | OAuth authentication configuration. See [OAuth](#oauth). | -| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). | - -## OAuth - -OpenScience automatically handles OAuth authentication for remote MCP servers. When a server requires authentication, OpenScience: - -1. Detects the 401 response and initiates the OAuth flow -2. Uses Dynamic Client Registration (RFC 7591) if the server supports it -3. Stores tokens securely for future requests - -### Automatic - -For most OAuth-enabled MCP servers, no special configuration is needed. Just configure the remote server: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp" - } - } -} -``` - -If the server requires authentication, OpenScience prompts you when you first try to use it. You can also [trigger the flow manually](#authenticating) with `openscience mcp auth `. - -### Pre-registered - -If you have client credentials from the MCP server provider, configure them: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": { - "clientId": "{env:MY_MCP_CLIENT_ID}", - "clientSecret": "{env:MY_MCP_CLIENT_SECRET}", - "scope": "tools:read tools:execute" - } - } - } -} -``` - -### Authenticating - -Authenticate with a specific MCP server: - -```bash -openscience mcp auth my-oauth-server -``` - -List all MCP servers and their auth status: - -```bash -openscience mcp list -``` - -Remove stored credentials: - -```bash -openscience mcp logout my-oauth-server -``` - -The `mcp auth` command opens your browser for authorization. After you authorize, OpenScience stores the tokens in `~/.local/share/openscience/mcp-auth.json`. - -### Disabling OAuth - -To disable automatic OAuth for a server (for example, servers that use API keys instead), set `oauth` to `false`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-api-key-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": false, - "headers": { - "Authorization": "Bearer {env:MY_API_KEY}" - } - } - } -} -``` - -### OAuth options - -| Option | Type | Description | -| -------------- | --------------- | ---------------------------------------------------------------------------------- | -| `oauth` | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection. | -| `clientId` | String | OAuth client ID. If not provided, dynamic client registration is attempted. | -| `clientSecret` | String | OAuth client secret, if required by the authorization server. | -| `scope` | String | OAuth scopes to request during authorization. | - -### Debugging - -If a remote MCP server fails to authenticate: - -```bash -# View auth status for all OAuth-capable servers -openscience mcp auth list - -# Debug connection and OAuth flow for a specific server -openscience mcp debug my-oauth-server -``` - -The `mcp debug` command shows the current auth status, tests HTTP connectivity, and attempts the OAuth discovery flow. - -## Manage - -MCP tools are available alongside built-in tools, so you manage them through the config like any other tool. - -### Global - -Enable or disable them globally: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp*": false - } -} -``` - -Here the glob pattern `my-mcp*` disables all matching MCP tools. - -### Per agent - -If you have a large number of MCP servers, you can disable them globally and enable them only for specific agents: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "my-mcp": { - "type": "local", - "command": ["bun", "x", "my-mcp-command"], - "enabled": true - } - }, - "tools": { - "my-mcp*": false - }, - "agent": { - "my-agent": { - "tools": { - "my-mcp*": true - } - } - } -} -``` - -### Glob patterns - -- `*` matches zero or more of any character (for example, `"my-mcp*"` matches `my-mcp_search`, `my-mcp_list`, and so on) -- `?` matches exactly one character -- All other characters match literally - - -MCP server tools are registered with the server name as a prefix, so to disable all tools for a server use `"mymcpservername_*": false`. - - -## Examples - -### Sentry - -Add the [Sentry MCP server](https://mcp.sentry.dev) to interact with your Sentry projects and issues: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "sentry": { - "type": "remote", - "url": "https://mcp.sentry.dev/mcp", - "oauth": {} - } - } -} -``` - -Then authenticate with Sentry: - -```bash -openscience mcp auth sentry -``` - -This opens a browser window to complete the OAuth flow. Once authenticated, you can query issues, projects, and error data: - -```text -Show me the latest unresolved issues in my project. use sentry -``` - -### Context7 - -Add the [Context7 MCP server](https://github.com/upstash/context7) to search through docs: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp" - } - } -} -``` - -With a free account you can use an API key for higher rate limits: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp", - "headers": { - "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}" - } - } - } -} -``` - -Add `use context7` to your prompts, or add a rule to your [AGENTS.md](/rules): - -```markdown AGENTS.md -When you need to search docs, use `context7` tools. -``` - -### Grep by Vercel - -Add the [Grep by Vercel](https://grep.app) MCP server to search code on GitHub: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "mcp": { - "gh_grep": { - "type": "remote", - "url": "https://mcp.grep.app" - } - } -} -``` - -Since the server is named `gh_grep`, add `use the gh_grep tool` to your prompts, or add a rule to your [AGENTS.md](/rules): - -```markdown AGENTS.md -If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. -``` diff --git a/docs/models.mdx b/docs/models.mdx deleted file mode 100644 index 825727a..0000000 --- a/docs/models.mdx +++ /dev/null @@ -1,185 +0,0 @@ ---- -title: "Models" -description: "Configure an LLM provider and model." -icon: "cpu" -keywords: ["models", "model selection", "variants", "small model", "default model"] ---- - -OpenScience uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support 75+ LLM providers, and it supports running local models. - -## Providers - -Most popular providers are preloaded by default. If you have added credentials for a provider through the `/connect` command, they are available when you start OpenScience. - -See [Providers](/providers) for setup guides. - -## Select a model - -Once you have configured your provider, select a model in the workspace: - -```text -/models -``` - -## Recommended models - -New models come out every week, but only a few are good at both generating code and tool calling. These models work well with OpenScience, in no particular order (the list is not exhaustive or necessarily up to date): - -- GPT 5.2 -- GPT 5.1 Codex -- Claude Opus 4.5 -- Claude Sonnet 4.5 -- Minimax M2.1 -- Gemini 3 Pro - -## Set a default - -Set the `model` key in your OpenScience config: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "model": "anthropic/claude-sonnet-4-5" -} -``` - -The full ID is `provider_id/model_id`. For example, if you use [Atlas](/atlas), `synsci/gpt-5-nano` selects GPT 5 Nano through the managed `synsci` provider. - -If you have configured a [custom provider](/providers#custom-provider), the `provider_id` is the key from the `provider` section of your config, and the `model_id` is the key from `provider.models`. - -## Configure models - -You can globally configure a model's options through the config: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "openai": { - "models": { - "gpt-5": { - "options": { - "reasoningEffort": "high", - "textVerbosity": "low", - "reasoningSummary": "auto", - "include": ["reasoning.encrypted_content"], - }, - }, - }, - }, - "anthropic": { - "models": { - "claude-sonnet-4-5-20250929": { - "options": { - "thinking": { - "type": "enabled", - "budgetTokens": 16000, - }, - }, - }, - }, - }, - }, -} -``` - -This configures global settings for two built-in models: `gpt-5` when accessed via the `openai` provider, and `claude-sonnet-4-5-20250929` when accessed via the `anthropic` provider. Built-in provider and model names are listed on [Models.dev](https://models.dev). - -You can also configure these options per [agent](/agents#additional-options). Agent config overrides the global options. - -## Variants - -Many models support multiple variants with different configurations. Variants let you configure different settings for the same model without creating duplicate entries. - -### Built-in variants - -OpenScience ships with default variants for popular providers. - -**Anthropic**: - -- `high`: high thinking budget (default) -- `max`: maximum thinking budget - -**OpenAI** (varies by model): - -- `none`: no reasoning -- `minimal`: minimal reasoning effort -- `low`: low reasoning effort -- `medium`: medium reasoning effort -- `high`: high reasoning effort -- `xhigh`: extra high reasoning effort - -**Google**: - -- `low`: lower effort/token budget -- `high`: higher effort/token budget - -This list is not comprehensive; many other providers have built-in defaults too. - -### Custom variants - -You can override existing variants or add your own: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "openai": { - "models": { - "gpt-5": { - "variants": { - "thinking": { - "reasoningEffort": "high", - "textVerbosity": "low", - }, - "fast": { - "disabled": true, - }, - }, - }, - }, - }, - }, -} -``` - -Variants also work for models served through the managed `synsci` provider: - -```jsonc openscience.jsonc -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "synsci": { - "models": { - "gpt-5": { - "variants": { - "high": { - "reasoningEffort": "high", - "textVerbosity": "low", - "reasoningSummary": "auto", - }, - "low": { - "reasoningEffort": "low", - "textVerbosity": "low", - "reasoningSummary": "auto", - }, - }, - }, - }, - }, - }, -} -``` - -### Cycle variants - -Use the `variant_cycle` keybind to switch between variants during a session. - -## Loading models - -When OpenScience starts up, it checks for models in the following priority order: - -1. The `--model` or `-m` command line flag, in the form `provider_id/model_id`. -2. The `model` key in the OpenScience config. -3. The last used model. -4. The first model using an internal priority. diff --git a/docs/permissions.mdx b/docs/permissions.mdx deleted file mode 100644 index 9a4a56b..0000000 --- a/docs/permissions.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: "Permissions" -description: "Control which actions require approval to run." -icon: "shield" -keywords: ["permissions", "allow", "ask", "deny", "bash", "edit", "external directories"] ---- - -OpenScience uses the `permission` config to decide whether a given action should run automatically, prompt you, or be blocked. - -As of `v1.1.1`, the legacy `tools` boolean config is deprecated and has been merged into `permission`. The old `tools` config is still supported for backwards compatibility. - -## Actions - -Each permission rule resolves to one of: - -- `"allow"`: run without approval -- `"ask"`: prompt for approval -- `"deny"`: block the action - -## Configuration - -You can set permissions globally (with `*`) and override specific tools: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "*": "ask", - "bash": "allow", - "edit": "deny" - } -} -``` - -You can also set all permissions at once: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": "allow" -} -``` - -## Granular rules - -For most permissions, you can use an object to apply different actions based on the tool input: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "npm *": "allow", - "rm *": "deny", - "grep *": "allow" - }, - "edit": { - "*": "deny", - "docs/*.mdx": "allow" - } - } -} -``` - -Rules are evaluated by pattern match, with the last matching rule winning. A common pattern is to put the catch-all `"*"` rule first, and more specific rules after it. - -### Wildcards - -Permission patterns use simple wildcard matching: - -- `*` matches zero or more of any character -- `?` matches exactly one character -- All other characters match literally - -### Home directory expansion - -You can use `~` or `$HOME` at the start of a pattern to reference your home directory. This is particularly useful for [`external_directory`](#external-directories) rules. - -- `~/projects/*` expands to `/Users/username/projects/*` -- `$HOME/projects/*` expands to `/Users/username/projects/*` -- `~` expands to `/Users/username` - -### External directories - -Use `external_directory` to allow tool calls that touch paths outside the working directory where OpenScience was started. This applies to any tool that takes a path as input (for example `read`, `edit`, `list`, `glob`, `grep`, and many `bash` commands). - -Home expansion (like `~/...`) only affects how a pattern is written. It does not make an external path part of the current workspace, so paths outside the working directory must still be allowed via `external_directory`. - -For example, this allows access to everything under `~/projects/personal/`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "external_directory": { - "~/projects/personal/**": "allow" - } - } -} -``` - -Any directory allowed here inherits the same defaults as the current workspace. Since [`read` defaults to `allow`](#defaults), reads are also allowed for entries under `external_directory` unless overridden. Add explicit rules when a tool should be restricted in these paths, such as blocking edits while keeping reads: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "external_directory": { - "~/projects/personal/**": "allow" - }, - "edit": { - "~/projects/personal/**": "deny" - } - } -} -``` - -Keep the list focused on trusted paths, and layer extra allow or deny rules as needed for other tools. - -## Available permissions - -Permissions are keyed by tool name, plus a couple of safety guards: - -- `read`: reading a file (matches the file path) -- `edit`: all file modifications (covers `edit`, `write`, `patch`, `multiedit`) -- `glob`: file globbing (matches the glob pattern) -- `grep`: content search (matches the regex pattern) -- `list`: listing files in a directory (matches the directory path) -- `bash`: running shell commands (matches parsed commands like `git status --porcelain`) -- `task`: launching subagents (matches the subagent type) -- `skill`: loading a skill (matches the skill name) -- `lsp`: running LSP queries (currently non-granular) -- `todoread`, `todowrite`: reading/updating the todo list -- `webfetch`: fetching a URL (matches the URL) -- `websearch`, `codesearch`: web/code search (matches the query) -- `external_directory`: triggered when a tool touches paths outside the project working directory -- `doom_loop`: triggered when the same tool call repeats 3 times with identical input - -## Defaults - -If you do not specify anything, OpenScience starts from permissive defaults: - -- Most permissions default to `"allow"`. -- `doom_loop` and `external_directory` default to `"ask"`. -- `read` is `"allow"`, but `.env` files are denied by default: - -```json openscience.json -{ - "permission": { - "read": { - "*": "allow", - "*.env": "deny", - "*.env.*": "deny", - "*.env.example": "allow" - } - } -} -``` - -## What "ask" does - -When OpenScience prompts for approval, the UI offers three outcomes: - -- `once`: approve just this request -- `always`: approve future requests matching the suggested patterns, for the rest of the current session -- `reject`: deny the request - -The set of patterns that `always` would approve is provided by the tool. For example, bash approvals typically allowlist a safe command prefix like `git status*`. - -## Agents - -You can override permissions per agent. Agent permissions are merged with the global config, and agent rules take precedence: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "git commit *": "deny", - "git push *": "deny", - "grep *": "allow" - } - }, - "agent": { - "research": { - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "git commit *": "ask", - "git push *": "deny", - "grep *": "allow" - } - } - } - } -} -``` - -You can also configure agent permissions in markdown agent definitions: - -```markdown ~/.config/openscience/agents/review.md ---- -description: Code review without edits -mode: subagent -permission: - edit: deny - bash: ask - webfetch: deny ---- - -Only analyze code and suggest changes. -``` - - -Use pattern matching for commands with arguments. `"grep *"` allows `grep pattern file.txt`, while `"grep"` alone would block it. Commands like `git status` work for default behavior but require explicit permission (like `"git status *"`) when arguments are passed. - - -See [Agents](/agents#permissions) for more on per-agent configuration. diff --git a/docs/providers.mdx b/docs/providers.mdx deleted file mode 100644 index c4f8f88..0000000 --- a/docs/providers.mdx +++ /dev/null @@ -1,406 +0,0 @@ ---- -title: "Providers" -description: "Use any LLM provider with OpenScience." -icon: "plug" -keywords: ["providers", "anthropic", "openai", "google", "bedrock", "ollama", "byok", "api keys"] ---- - -OpenScience uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support 75+ LLM providers, plus local models. - -To add a provider: - -1. Add the provider's API key with the `/connect` command in the workspace, or `openscience auth login` in your terminal. -2. Optionally customize the provider in your [OpenScience config](/config). - -### Credentials - -When you add a provider's API key, it is stored locally in `~/.local/share/openscience/auth.json`. Keys never leave your machine; requests go straight to the provider. OpenScience also picks up keys from your environment and from a `.env` file in your project. - -### Base URL - -You can customize the base URL for any provider with the `baseURL` option. This is useful for proxy services or custom endpoints: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "anthropic": { - "options": { - "baseURL": "https://api.anthropic.com/v1" - } - } - } -} -``` - -## Atlas - -[Atlas](/atlas) is Synthetic Sciences' managed platform. It includes a curated set of models that have been tested and verified to work well with OpenScience, served through the managed `synsci` provider and billed from a prepaid wallet. - -1. Sign in from the CLI and approve the sign-in from your browser: - - ```bash - openscience connect login - ``` - -2. On headless or CI machines, create an API key at [app.syntheticsciences.ai](https://app.syntheticsciences.ai/cli) and pass it directly: - - ```bash - openscience connect login --key thk_... - ``` - -3. Run the `/models` command to select one of the curated `synsci/...` models. - -Atlas works like any other provider and is completely optional. Bring-your-own-key usage is free and needs no account. - -## Directory - -Setup guides for common providers. For providers not listed here, the flow is usually the same: create an API key in the provider's console, run `/connect`, search for the provider, paste the key, then pick a model with `/models`. Any OpenAI-compatible API can also be added as a [custom provider](#custom-provider). - -### Anthropic - -1. Run the `/connect` command and select Anthropic. - -2. Select the **Claude Pro/Max** option to authenticate in your browser, or: - - **Create an API Key**: opens your browser, logs you in to Anthropic, and gives you a code to paste into the workspace. - - **Manually enter API Key**: paste an existing key. - -3. All Anthropic models are now available through the `/models` command. - - -Using a Claude Pro/Max subscription in OpenScience is not officially supported by Anthropic. - - -### OpenAI - -1. Run the `/connect` command and select OpenAI. - -2. Select the **ChatGPT Plus/Pro** option to authenticate in your browser, or select **Manually enter API Key** and paste an API key. - -3. All OpenAI models are now available through the `/models` command. - -### Google Vertex AI - -1. Check the models available in your region in the Model Garden in the Google Cloud Console. You need a Google Cloud project with the Vertex AI API enabled. - -2. Set the required environment variables: - - ```bash ~/.bash_profile - export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json - export GOOGLE_CLOUD_PROJECT=your-project-id - export VERTEX_LOCATION=global - ``` - - - `GOOGLE_CLOUD_PROJECT`: your Google Cloud project ID. - - `VERTEX_LOCATION` (optional): the region for Vertex AI (defaults to `global`). - - Authentication: set `GOOGLE_APPLICATION_CREDENTIALS` to a service account JSON key file, or authenticate with `gcloud auth application-default login`. - -3. Run the `/models` command to select a model. - - -The `global` region improves availability and reduces errors at no extra cost. Use regional endpoints (for example `us-central1`) for data residency requirements. - - -### Amazon Bedrock - -1. Request access to the models you want in the Model catalog in the Amazon Bedrock console. - -2. Configure authentication using environment variables: - - ```bash - # Option 1: AWS access keys - AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY openscience - - # Option 2: named AWS profile - AWS_PROFILE=my-profile openscience - - # Option 3: Bedrock bearer token - AWS_BEARER_TOKEN_BEDROCK=XXX openscience - ``` - - Or use the config file (config options take precedence over environment variables): - - ```json openscience.json - { - "$schema": "https://openscience.sh/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "my-aws-profile" - } - } - } - } - ``` - - - `region`: AWS region (defaults to `AWS_REGION` or `us-east-1`). - - `profile`: AWS named profile from `~/.aws/credentials`. - - `endpoint`: custom endpoint URL for VPC endpoints. This is an alias for the generic `baseURL` option; if both are specified, `endpoint` takes precedence. - -3. Run the `/models` command to select a model. - -Authentication precedence for Bedrock: - -1. Bearer token: `AWS_BEARER_TOKEN_BEDROCK` or a token from `/connect`. -2. AWS credential chain: profile, access keys, shared credentials, IAM roles, Web Identity Tokens (EKS IRSA), instance metadata. - - -For custom inference profiles, use the model and provider name in the key and set the `id` property to the ARN so caching works correctly: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "amazon-bedrock": { - "models": { - "anthropic-claude-sonnet-4.5": { - "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" - } - } - } - } -} -``` - - -### Azure OpenAI - -1. Create an **Azure OpenAI** resource in the [Azure portal](https://portal.azure.com/). You need the resource name (part of your endpoint, `https://RESOURCE_NAME.openai.azure.com/`) and an API key (`KEY 1` or `KEY 2`). - -2. Deploy a model in [Azure AI Foundry](https://ai.azure.com/). The deployment name must match the model name. - -3. Run the `/connect` command, search for **Azure**, and enter your API key. - -4. Set your resource name as an environment variable: - - ```bash ~/.bash_profile - export AZURE_RESOURCE_NAME=XXX - ``` - -5. Run the `/models` command to select your deployed model. - - -If you encounter "I'm sorry, but I cannot assist with that request" errors, try changing the content filter from **DefaultV2** to **Default** in your Azure resource. - - -### GitHub Copilot - -1. Run the `/connect` command and search for GitHub Copilot. - -2. Navigate to [github.com/login/device](https://github.com/login/device) and enter the code shown in the workspace. - -3. Run the `/models` command to select a model. - - -Some models require a Pro+ subscription, and some need to be manually enabled in your GitHub Copilot settings. - - -### OpenRouter - -1. Create an API key in the [OpenRouter dashboard](https://openrouter.ai/settings/keys). - -2. Run the `/connect` command, search for OpenRouter, and enter the key. - -3. Many OpenRouter models are preloaded by default; run `/models` to select one. You can add additional models and customize routing through your config: - - ```json openscience.json - { - "$schema": "https://openscience.sh/config.json", - "provider": { - "openrouter": { - "models": { - "moonshotai/kimi-k2": { - "options": { - "provider": { - "order": ["baseten"], - "allow_fallbacks": false - } - } - } - } - } - } - } - ``` - -### Other API-key providers - -The same create-key, `/connect`, `/models` flow works for 302.AI, Baseten, Cerebras, Cortecs, DeepSeek, Deep Infra, Fireworks AI, Groq, Hugging Face, IO.NET, MiniMax, Moonshot AI, Nebius Token Factory, Ollama Cloud, OVHcloud AI Endpoints, Scaleway, Together AI, Venice AI, Vercel AI Gateway, xAI, Z.AI, ZenMux, and more. Run `/connect` and search for the provider by name. - -## Local models - -Run local models through any OpenAI-compatible server by defining a custom provider in your config. - - - -```json Ollama -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "ollama": { - "npm": "@ai-sdk/openai-compatible", - "name": "Ollama (local)", - "options": { - "baseURL": "http://localhost:11434/v1" - }, - "models": { - "llama2": { - "name": "Llama 2" - } - } - } - } -} -``` - -```json LM Studio -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "lmstudio": { - "npm": "@ai-sdk/openai-compatible", - "name": "LM Studio (local)", - "options": { - "baseURL": "http://127.0.0.1:1234/v1" - }, - "models": { - "google/gemma-3n-e4b": { - "name": "Gemma 3n-e4b (local)" - } - } - } - } -} -``` - -```json llama.cpp -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "llama.cpp": { - "npm": "@ai-sdk/openai-compatible", - "name": "llama-server (local)", - "options": { - "baseURL": "http://127.0.0.1:8080/v1" - }, - "models": { - "qwen3-coder:a3b": { - "name": "Qwen3-Coder: a3b-30b (local)", - "limit": { - "context": 128000, - "output": 65536 - } - } - } - } - } -} -``` - - - -In these examples: - -- The provider key (`ollama`, `lmstudio`, `llama.cpp`) is a custom provider ID. It can be any string. -- `npm` specifies the package for the provider. `@ai-sdk/openai-compatible` works for any OpenAI-compatible API. -- `name` is the display name in the UI. -- `options.baseURL` is the endpoint for the local server. -- `models` maps model IDs to their configurations. - - -If tool calls are not working with Ollama, try increasing `num_ctx`. Start around 16k to 32k. - - -## Custom provider - -To add any OpenAI-compatible provider that is not listed in the `/connect` command: - -1. Run the `/connect` command and scroll down to **Other**. - -2. Enter a unique ID for the provider. Choose a memorable ID; you will use it in your config file. - -3. Enter your API key for the provider. - -4. Create or update `openscience.json` in your project directory: - - ```json openscience.json - { - "$schema": "https://openscience.sh/config.json", - "provider": { - "myprovider": { - "npm": "@ai-sdk/openai-compatible", - "name": "My Provider Display Name", - "options": { - "baseURL": "https://api.myprovider.com/v1" - }, - "models": { - "my-model-name": { - "name": "My Model Display Name" - } - } - } - } - } - ``` - -5. Run the `/models` command; your custom provider and models appear in the selection list. - -Configuration options: - -- `npm`: AI SDK package to use. `@ai-sdk/openai-compatible` for OpenAI-compatible providers. -- `name`: display name in the UI. -- `models`: available models. -- `options.baseURL`: API endpoint URL. -- `options.apiKey`: optionally set the API key, if not using `/connect`. -- `options.headers`: optionally set custom headers. - -Here is an example setting the `apiKey`, `headers`, and model `limit` options: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "provider": { - "myprovider": { - "npm": "@ai-sdk/openai-compatible", - "name": "My Provider Display Name", - "options": { - "baseURL": "https://api.myprovider.com/v1", - "apiKey": "{env:MYPROVIDER_API_KEY}", - "headers": { - "Authorization": "Bearer custom-token" - } - }, - "models": { - "my-model-name": { - "name": "My Model Display Name", - "limit": { - "context": 200000, - "output": 65536 - } - } - } - } - } -} -``` - -- `apiKey`: set using the [`{env:...}` variable syntax](/config#env-vars). -- `headers`: custom headers sent with each request. -- `limit.context`: maximum input tokens the model accepts. -- `limit.output`: maximum tokens the model can generate. - -The `limit` fields let OpenScience track how much context you have left. Standard providers pull these from Models.dev automatically. - -## Troubleshooting - -If a provider is not working: - -1. **Check the auth setup.** Run `openscience auth list` to see if credentials for the provider are stored. This does not apply to providers like Amazon Bedrock that rely on environment variables. - -2. **For custom providers**, check that: - - The provider ID used in the `/connect` command matches the ID in your config. - - The right npm package is used. For example, `@ai-sdk/cerebras` for Cerebras, and `@ai-sdk/openai-compatible` for other OpenAI-compatible providers. - - The correct API endpoint is set in `options.baseURL`. - -See [Troubleshooting](/troubleshooting) for more. diff --git a/docs/rules.mdx b/docs/rules.mdx deleted file mode 100644 index f9e7fc1..0000000 --- a/docs/rules.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Rules" -description: "Set custom instructions for OpenScience with AGENTS.md." -icon: "list-checks" -keywords: ["rules", "AGENTS.md", "CLAUDE.md", "instructions", "custom instructions"] ---- - -You can provide custom instructions to OpenScience by creating an `AGENTS.md` file. It contains instructions that are included in the LLM's context to customize its behavior for your project. - -## Initialize - -To create a new `AGENTS.md` file, run the `/init` command in the workspace: - -```text -/init -``` - -This scans your project to understand what it is about and generates an `AGENTS.md` file. If you have an existing `AGENTS.md`, it adds to it. - - -Commit your project's `AGENTS.md` file to Git so your team shares the same context. - - -## Example - -You can also create the file manually: - -```markdown AGENTS.md -# SST v3 Monorepo Project - -This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. - -## Project Structure - -- `packages/` - Contains all workspace packages (functions, core, web, etc.) -- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) -- `sst.config.ts` - Main SST configuration with dynamic imports - -## Code Standards - -- Use TypeScript with strict mode enabled -- Shared code goes in `packages/core/` with proper exports configuration -- Functions go in `packages/functions/` -- Infrastructure should be split into logical files in `infra/` - -## Monorepo Conventions - -- Import shared modules using workspace names: `@my-app/core/example` -``` - -## Locations - -OpenScience reads `AGENTS.md` from multiple locations, each used for a different purpose. - -### Project - -Place an `AGENTS.md` in your project root for project-specific rules. These only apply when you are working in this directory or its subdirectories. - -### Global - -You can also have global rules in `~/.config/openscience/AGENTS.md`. This applies across all OpenScience sessions. - -Since this is not committed to Git or shared with your team, use it for personal rules that the LLM should follow. - -### Claude Code compatibility - -For users migrating from Claude Code, OpenScience supports Claude Code's file conventions as fallbacks: - -- Project rules: `CLAUDE.md` in your project directory (used if no `AGENTS.md` exists) -- Global rules: `~/.claude/CLAUDE.md` (used if no `~/.config/openscience/AGENTS.md` exists) -- Skills: `~/.claude/skills/`, see [Skills](/skills) - -To disable Claude Code compatibility, set one of these environment variables: - -```bash -export OPENSCIENCE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support -export OPENSCIENCE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md -export OPENSCIENCE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills -``` - -## Precedence - -When OpenScience starts, it looks for rule files in this order: - -1. Local files, by traversing up from the current directory (`AGENTS.md`, `CLAUDE.md`) -2. Global file at `~/.config/openscience/AGENTS.md` -3. Claude Code file at `~/.claude/CLAUDE.md` (unless disabled) - -The first matching file wins in each category. If you have both `AGENTS.md` and `CLAUDE.md`, only `AGENTS.md` is used. Similarly, `~/.config/openscience/AGENTS.md` takes precedence over `~/.claude/CLAUDE.md`. - -## Custom instructions - -You can specify custom instruction files in your `openscience.json` or the global `~/.config/openscience/openscience.json`. This lets you and your team reuse existing rules rather than duplicating them into `AGENTS.md`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] -} -``` - -You can also use remote URLs to load instructions from the web: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] -} -``` - -Remote instructions are fetched with a 5 second timeout. All instruction files are combined with your `AGENTS.md` files. - -## Referencing external files - -OpenScience does not automatically parse file references in `AGENTS.md`, but you can get similar behavior in two ways. - -### Using openscience.json - -The recommended approach is the `instructions` field in `openscience.json`: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] -} -``` - -### Manual instructions in AGENTS.md - -You can teach OpenScience to read external files by providing explicit instructions in your `AGENTS.md`: - -```markdown AGENTS.md -# TypeScript Project Rules - -## External File Loading - -CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. - -Instructions: - -- Do NOT preemptively load all references - use lazy loading based on actual need -- When loaded, treat content as mandatory instructions that override defaults -- Follow references recursively when needed - -## Development Guidelines - -For TypeScript code style and best practices: @docs/typescript-guidelines.md -For React component architecture and hooks patterns: @docs/react-patterns.md -For REST API design and error handling: @docs/api-standards.md -For testing strategies and coverage requirements: @test/testing-guidelines.md - -## General Guidelines - -Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. -``` - -This approach lets you: - -- Create modular, reusable rule files -- Share rules across projects via symlinks or Git submodules -- Keep `AGENTS.md` concise while referencing detailed guidelines -- Ensure OpenScience loads files only when needed for the specific task - - -For monorepos or projects with shared standards, using `openscience.json` with glob patterns (like `packages/*/AGENTS.md`) is more maintainable than manual instructions. - diff --git a/docs/share.mdx b/docs/share.mdx deleted file mode 100644 index 51890b2..0000000 --- a/docs/share.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: "Share" -description: "Share your OpenScience conversations." -icon: "share-2" -keywords: ["share", "unshare", "session links", "privacy"] ---- - -The share feature creates public links to your OpenScience conversations, so you can collaborate with teammates or get help from others. - - -Shared conversations are publicly accessible to anyone with the link. - - -## How it works - -When you share a conversation, OpenScience: - -1. Creates a unique public URL for your session -2. Syncs your conversation history to the share servers -3. Makes the conversation accessible at a shareable link: `syntheticsciences.ai/s/` - -## Sharing modes - -OpenScience supports three sharing modes that control how conversations are shared. - -### Manual (default) - -Sessions are not shared automatically, but you can share them with the `/share` command: - -```text -/share -``` - -This generates a unique URL and copies it to your clipboard. - -To explicitly set manual mode in your [config](/config): - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "share": "manual" -} -``` - -### Auto-share - -Enable automatic sharing for all new conversations: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "share": "auto" -} -``` - -With auto-share enabled, every new conversation is shared and a link is generated. - -### Disabled - -Disable sharing entirely: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "share": "disabled" -} -``` - -To enforce this across your team for a given project, add it to the `openscience.json` in your project and check it into Git. - -## Un-sharing - -To stop sharing a conversation and remove it from public access: - -```text -/unshare -``` - -This removes the share link and deletes the data related to the conversation. - -## Privacy - -### Data retention - -Shared conversations remain accessible until you explicitly unshare them. This includes: - -- Full conversation history -- All messages and responses -- Session metadata - -### Recommendations - -- Only share conversations that do not contain sensitive information. -- Review conversation content before sharing. -- Unshare conversations when collaboration is complete. -- Avoid sharing conversations with proprietary code or confidential data. -- For sensitive projects, disable sharing entirely. diff --git a/docs/skills.mdx b/docs/skills.mdx deleted file mode 100644 index 85ebf9e..0000000 --- a/docs/skills.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: "Skills" -description: "Define reusable behavior with SKILL.md files." -icon: "book-open" -keywords: ["skills", "SKILL.md", "agent skills", "reusable instructions"] ---- - -Agent skills let OpenScience discover reusable instructions from your repo or home directory. Skills are loaded on demand via the native `skill` tool: agents see the available skills and load the full content when needed. - -## Place files - -Create one folder per skill name and put a `SKILL.md` inside it. OpenScience searches these locations: - -- Project config: `.openscience/skills//SKILL.md` -- Global config: `~/.config/openscience/skills//SKILL.md` -- Project Claude-compatible: `.claude/skills//SKILL.md` -- Global Claude-compatible: `~/.claude/skills//SKILL.md` - -## Discovery - -For project-local paths, OpenScience walks up from your current working directory until it reaches the Git worktree. It loads any matching `skills/*/SKILL.md` in `.openscience/` and any matching `.claude/skills/*/SKILL.md` along the way. - -Global definitions are also loaded from `~/.config/openscience/skills/*/SKILL.md` and `~/.claude/skills/*/SKILL.md`. - -## Frontmatter - -Each `SKILL.md` must start with YAML frontmatter. Only these fields are recognized: - -- `name` (required) -- `description` (required) -- `license` (optional) -- `compatibility` (optional) -- `metadata` (optional, string-to-string map) - -Unknown frontmatter fields are ignored. - -### Name rules - -`name` must: - -- Be 1-64 characters -- Be lowercase alphanumeric with single hyphen separators -- Not start or end with `-` -- Not contain consecutive `--` -- Match the directory name that contains `SKILL.md` - -Equivalent regex: - -```text -^[a-z0-9]+(-[a-z0-9]+)*$ -``` - -### Description rules - -`description` must be 1-1024 characters. Keep it specific enough for the agent to choose correctly. - -## Example - -Create `.openscience/skills/git-release/SKILL.md`: - -```markdown SKILL.md ---- -name: git-release -description: Create consistent releases and changelogs -license: Apache-2.0 -compatibility: openscience -metadata: - audience: maintainers - workflow: github ---- - -## What I do - -- Draft release notes from merged PRs -- Propose a version bump -- Provide a copy-pasteable `gh release create` command - -## When to use me - -Use this when you are preparing a tagged release. -Ask clarifying questions if the target versioning scheme is unclear. -``` - -## Tool description - -OpenScience lists available skills in the `skill` tool description. Each entry includes the skill name and description: - -```xml - - - git-release - Create consistent releases and changelogs - - -``` - -The agent loads a skill by calling the tool: - -```text -skill({ name: "git-release" }) -``` - -## Permissions - -Control which skills agents can access using pattern-based [permissions](/permissions): - -```json openscience.json -{ - "permission": { - "skill": { - "*": "allow", - "pr-review": "allow", - "internal-*": "deny", - "experimental-*": "ask" - } - } -} -``` - -| Permission | Behavior | -| ---------- | ------------------------------------------ | -| `allow` | Skill loads immediately | -| `deny` | Skill hidden from agent, access rejected | -| `ask` | User prompted for approval before loading | - -Patterns support wildcards: `internal-*` matches `internal-docs`, `internal-tools`, and so on. - -### Per agent - -Give specific agents different permissions than the global defaults. - -For custom agents, in the agent frontmatter: - -```yaml ---- -permission: - skill: - "documents-*": "allow" ---- -``` - -For built-in agents, in `openscience.json`: - -```json openscience.json -{ - "agent": { - "plan": { - "permission": { - "skill": { - "internal-*": "allow" - } - } - } - } -} -``` - -### Disable the skill tool - -Completely disable skills for agents that should not use them. - -For custom agents: - -```yaml ---- -tools: - skill: false ---- -``` - -For built-in agents: - -```json openscience.json -{ - "agent": { - "plan": { - "tools": { - "skill": false - } - } - } -} -``` - -When disabled, the `` section is omitted entirely. - -## Troubleshooting - -If a skill does not show up: - -1. Verify `SKILL.md` is spelled in all caps -2. Check that the frontmatter includes `name` and `description` -3. Ensure skill names are unique across all locations -4. Check permissions, since skills with `deny` are hidden from agents diff --git a/docs/themes.mdx b/docs/themes.mdx deleted file mode 100644 index da881ed..0000000 --- a/docs/themes.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: "Themes" -description: "Select a built-in theme or define your own." -icon: "palette" -keywords: ["themes", "custom themes", "colors", "appearance"] ---- - -You can select from several built-in themes, use a theme that follows your system's light or dark appearance, or define your own custom theme. - -By default, OpenScience uses its own `openscience` theme. - -## Built-in themes - -| Name | Description | -| ---------------------- | ----------------------------------------------------------------------------- | -| `system` | Follows your system's light or dark appearance | -| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme | -| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | -| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | -| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | -| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | -| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | -| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | -| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | -| `matrix` | Hacker-style green on black theme | -| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | - -More themes are added regularly. - -## System theme - -The `system` theme follows your operating system's light or dark appearance instead of using fixed colors. It picks a gray scale that keeps good contrast against the workspace background, and it uses `none` for text and background so the workspace keeps its default look. - -Use it if you want OpenScience to match your system appearance and stay consistent with your other applications. - -## Using a theme - -Select a theme with the `/theme` command in the workspace, or set it in your [config](/config): - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "theme": "tokyonight" -} -``` - -## Custom themes - -OpenScience supports a JSON-based theme system. - -### Hierarchy - -Themes are loaded from multiple directories in the following order, where later directories override earlier ones: - -1. Built-in themes: embedded in the binary -2. User config directory: `~/.config/openscience/themes/*.json` or `$XDG_CONFIG_HOME/openscience/themes/*.json` -3. Project root directory: `/.openscience/themes/*.json` -4. Current working directory: `./.openscience/themes/*.json` - -If multiple directories contain a theme with the same name, the theme from the higher-priority directory is used. - -### Creating a theme - -Create a JSON file in one of the theme directories. - -For user-wide themes: - -```bash -mkdir -p ~/.config/openscience/themes -vim ~/.config/openscience/themes/my-theme.json -``` - -For project-specific themes: - -```bash -mkdir -p .openscience/themes -vim .openscience/themes/my-theme.json -``` - -### JSON format - -Themes support: - -- Hex colors: `"#ffffff"` -- ANSI colors: `3` (0-255) -- Color references: `"primary"` or custom definitions from `defs` -- Dark/light variants: `{"dark": "#000", "light": "#fff"}` -- No color: `"none"` uses the default color or transparent - -The `defs` section is optional and defines reusable colors that can be referenced in the theme. - -The special value `"none"` can be used for any color to inherit the default color or stay transparent. This is useful for themes that follow the surrounding appearance: - -- `"text": "none"` uses the default foreground color -- `"background": "none"` uses the default background color - -### Example - -```json my-theme.json -{ - "$schema": "https://openscience.sh/theme.json", - "defs": { - "nord0": "#2E3440", - "nord1": "#3B4252", - "nord2": "#434C5E", - "nord3": "#4C566A", - "nord4": "#D8DEE9", - "nord6": "#ECEFF4", - "nord7": "#8FBCBB", - "nord8": "#88C0D0", - "nord9": "#81A1C1", - "nord10": "#5E81AC", - "nord11": "#BF616A", - "nord12": "#D08770", - "nord13": "#EBCB8B", - "nord14": "#A3BE8C", - "nord15": "#B48EAD" - }, - "theme": { - "primary": { "dark": "nord8", "light": "nord10" }, - "secondary": { "dark": "nord9", "light": "nord9" }, - "accent": { "dark": "nord7", "light": "nord7" }, - "error": { "dark": "nord11", "light": "nord11" }, - "warning": { "dark": "nord12", "light": "nord12" }, - "success": { "dark": "nord14", "light": "nord14" }, - "info": { "dark": "nord8", "light": "nord10" }, - "text": { "dark": "nord4", "light": "nord0" }, - "textMuted": { "dark": "nord3", "light": "nord1" }, - "background": { "dark": "nord0", "light": "nord6" }, - "backgroundPanel": { "dark": "nord1", "light": "nord4" }, - "backgroundElement": { "dark": "nord1", "light": "nord4" }, - "border": { "dark": "nord2", "light": "nord3" }, - "borderActive": { "dark": "nord3", "light": "nord2" }, - "borderSubtle": { "dark": "nord2", "light": "nord3" }, - "diffAdded": { "dark": "nord14", "light": "nord14" }, - "diffRemoved": { "dark": "nord11", "light": "nord11" }, - "diffContext": { "dark": "nord3", "light": "nord3" }, - "diffHunkHeader": { "dark": "nord3", "light": "nord3" }, - "diffHighlightAdded": { "dark": "nord14", "light": "nord14" }, - "diffHighlightRemoved": { "dark": "nord11", "light": "nord11" }, - "diffAddedBg": { "dark": "#3B4252", "light": "#E5E9F0" }, - "diffRemovedBg": { "dark": "#3B4252", "light": "#E5E9F0" }, - "diffContextBg": { "dark": "nord1", "light": "nord4" }, - "diffLineNumber": { "dark": "nord2", "light": "nord4" }, - "diffAddedLineNumberBg": { "dark": "#3B4252", "light": "#E5E9F0" }, - "diffRemovedLineNumberBg": { "dark": "#3B4252", "light": "#E5E9F0" }, - "markdownText": { "dark": "nord4", "light": "nord0" }, - "markdownHeading": { "dark": "nord8", "light": "nord10" }, - "markdownLink": { "dark": "nord9", "light": "nord9" }, - "markdownLinkText": { "dark": "nord7", "light": "nord7" }, - "markdownCode": { "dark": "nord14", "light": "nord14" }, - "markdownBlockQuote": { "dark": "nord3", "light": "nord3" }, - "markdownEmph": { "dark": "nord12", "light": "nord12" }, - "markdownStrong": { "dark": "nord13", "light": "nord13" }, - "markdownHorizontalRule": { "dark": "nord3", "light": "nord3" }, - "markdownListItem": { "dark": "nord8", "light": "nord10" }, - "markdownListEnumeration": { "dark": "nord7", "light": "nord7" }, - "markdownImage": { "dark": "nord9", "light": "nord9" }, - "markdownImageText": { "dark": "nord7", "light": "nord7" }, - "markdownCodeBlock": { "dark": "nord4", "light": "nord0" }, - "syntaxComment": { "dark": "nord3", "light": "nord3" }, - "syntaxKeyword": { "dark": "nord9", "light": "nord9" }, - "syntaxFunction": { "dark": "nord8", "light": "nord8" }, - "syntaxVariable": { "dark": "nord7", "light": "nord7" }, - "syntaxString": { "dark": "nord14", "light": "nord14" }, - "syntaxNumber": { "dark": "nord15", "light": "nord15" }, - "syntaxType": { "dark": "nord7", "light": "nord7" }, - "syntaxOperator": { "dark": "nord9", "light": "nord9" }, - "syntaxPunctuation": { "dark": "nord4", "light": "nord0" } - } -} -``` diff --git a/docs/tools.mdx b/docs/tools.mdx deleted file mode 100644 index 193ffa7..0000000 --- a/docs/tools.mdx +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: "Tools" -description: "Manage the tools the LLM can use." -icon: "wrench" -keywords: ["tools", "bash", "edit", "read", "grep", "glob", "webfetch", "skill"] ---- - -Tools let the LLM perform actions in your project. OpenScience comes with a set of built-in tools, and you can extend it with custom tools or [MCP servers](/mcp-servers). - -By default, all tools are enabled and do not need permission to run. You control tool behavior through [permissions](/permissions): - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "edit": "deny", - "bash": "ask", - "webfetch": "allow" - } -} -``` - -You can use wildcards to control multiple tools at once, for example to require approval for all tools from an MCP server: - -```json openscience.json -{ - "$schema": "https://openscience.sh/config.json", - "permission": { - "mymcp_*": "ask" - } -} -``` - -## Built-in tools - -### bash - -Execute shell commands in your project environment. The `bash` permission matches parsed commands, so you can write granular rules like `"git *": "allow"`. - -### edit - -Modify existing files using exact string replacements. This is the primary way the LLM modifies code. - -### write - -Create new files or overwrite existing ones. - - -The `write` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`). - - -### patch - -Apply patch files to your codebase. Also controlled by the `edit` permission. - -### read - -Read file contents. Supports reading specific line ranges for large files. `read` defaults to `allow`, but `.env` files are denied by default; see [permission defaults](/permissions#defaults). - -### grep - -Search file contents using regular expressions. Supports full regex syntax and file pattern filtering. - -### glob - -Find files by pattern matching, like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time. - -### list - -List files and directories in a given path. Accepts glob patterns to filter results. - -### lsp (experimental) - -Interact with your configured LSP servers for code intelligence: definitions, references, hover info, and call hierarchy. Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`. - - -This tool is only available when `OPENSCIENCE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENSCIENCE_EXPERIMENTAL=true`). - - -### skill - -Load a [skill](/skills) (a `SKILL.md` file) and return its content into the conversation. The `skill` permission matches the skill name. - -### todowrite and todoread - -Create, update, and read task lists that track progress during complex, multi-step operations. - - -The todo tools are disabled for subagents by default, but you can enable them per agent. See [agent permissions](/agents#permissions). - - -### webfetch - -Fetch and read web pages. Useful for looking up documentation or researching online resources. The `webfetch` permission matches the URL. - -### question - -Ask you questions during execution. Useful for: - -- Gathering preferences or requirements -- Clarifying ambiguous instructions -- Getting decisions on implementation choices - -Each question includes a header, the question text, and a list of options. You can select from the options or type a custom answer. When there are multiple questions, you can navigate between them before submitting all answers. - -## Custom tools - -Custom tools let you define your own functions that the LLM can call. Place tool files in `.openscience/tools/` or `~/.config/openscience/tools/`. - -## MCP servers - -MCP (Model Context Protocol) servers integrate external tools and services, including database access, API integrations, and third-party services. See [MCP servers](/mcp-servers). - -## Internals - -Internally, tools like `grep`, `glob`, and `list` use [ripgrep](https://github.com/BurntSushi/ripgrep). By default, ripgrep respects `.gitignore` patterns, so files and directories listed in your `.gitignore` are excluded from searches and listings. - -### Ignore patterns - -To include files that would normally be ignored, create a `.ignore` file in your project root: - -```text .ignore -!node_modules/ -!dist/ -!build/ -``` - -This example allows ripgrep to search within `node_modules/`, `dist/`, and `build/` even if they are listed in `.gitignore`. diff --git a/docs/troubleshooting.mdx b/docs/troubleshooting.mdx deleted file mode 100644 index 034ab2e..0000000 --- a/docs/troubleshooting.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: "Troubleshooting" -description: "Common issues and how to resolve them." -icon: "life-buoy" -keywords: ["troubleshooting", "logs", "storage", "errors", "provider errors"] ---- - -To debug issues with OpenScience, start by checking the logs and the local data it stores on disk. - -## Logs - -Log files are written to: - -- **macOS/Linux**: `~/.local/share/openscience/log/` -- **Windows**: press `WIN+R` and paste `%USERPROFILE%\.local\share\openscience\log` - -Log files are named with timestamps (for example, `2025-01-09T123456.log`) and the most recent 10 log files are kept. - -Set the log level with the `--log-level` flag for more detailed debug information: - -```bash -openscience --log-level DEBUG -``` - -## Storage - -OpenScience stores session data and other application data on disk at: - -- **macOS/Linux**: `~/.local/share/openscience/` -- **Windows**: press `WIN+R` and paste `%USERPROFILE%\.local\share\openscience` - -This directory contains: - -- `auth.json`: authentication data like API keys and OAuth tokens -- `log/`: application logs -- `project/`: project-specific data like session and message data - - If the project is within a Git repo, it is stored in `.//storage/` - - If it is not a Git repo, it is stored in `./global/storage/` - -## Getting help - -Report bugs or request features through the GitHub repository: - -[github.com/synthetic-sciences/openscience/issues](https://github.com/synthetic-sciences/openscience/issues) - -Before creating a new issue, search existing issues to see if your problem has already been reported. - -## Common issues - -### OpenScience won't start - -1. Check the logs for error messages -2. Try running with `--print-logs` to print logs to the console -3. Ensure you have the latest version with `openscience upgrade` - -### Authentication issues - -1. Try re-authenticating with the `/connect` command in the workspace -2. Check that your API keys are valid -3. Ensure your network allows connections to the provider's API - -### Model not available - -1. Check that you have authenticated with the provider -2. Verify the model name in your config is correct -3. Some models may require specific access or subscriptions - -If you encounter `ProviderModelNotFoundError`, you are most likely referencing a model incorrectly. Models are referenced as `/`: - -- `openai/gpt-4.1` -- `openrouter/google/gemini-2.5-flash` -- `synsci/gpt-5-nano` - -To see which models you have access to, run `openscience models`. - -### ProviderInitError - -A `ProviderInitError` usually means an invalid or corrupted configuration. - -1. Verify your provider is set up correctly by following the [providers guide](/providers) -2. If the issue persists, try clearing your stored configuration: - - ```bash - rm -rf ~/.local/share/openscience - ``` - - On Windows, press `WIN+R` and delete `%USERPROFILE%\.local\share\openscience`. - -3. Re-authenticate with your provider using the `/connect` command in the workspace. - -### AI_APICallError and provider package issues - -API call errors can be caused by outdated provider packages. OpenScience dynamically installs provider packages (OpenAI, Anthropic, Google, and so on) as needed and caches them locally. - -1. Clear the provider package cache: - - ```bash - rm -rf ~/.cache/openscience - ``` - - On Windows, press `WIN+R` and delete `%USERPROFILE%\.cache\openscience`. - -2. Restart OpenScience to reinstall the latest provider packages. - -This forces OpenScience to download the most recent provider packages, which often resolves compatibility issues with model parameters and API changes. - -### Copy/paste not working on Linux - -Linux users need one of the following clipboard utilities installed. - -For X11 systems: - -```bash -apt install -y xclip -# or -apt install -y xsel -``` - -For Wayland systems: - -```bash -apt install -y wl-clipboard -``` - -For headless environments: - -```bash -apt install -y xvfb -# and run: -Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & -export DISPLAY=:99.0 -``` - -OpenScience detects Wayland and prefers `wl-clipboard`, otherwise it tries clipboard tools in order: `xclip`, then `xsel`. diff --git a/frontend/docs/.gitignore b/frontend/docs/.gitignore index 6240da8..d09a1fe 100644 --- a/frontend/docs/.gitignore +++ b/frontend/docs/.gitignore @@ -1,21 +1,6 @@ -# build output -dist/ -# generated types -.astro/ - -# dependencies node_modules/ - -# logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - - -# environment variables -.env -.env.production - -# macOS-specific files +dist/ +.vite/ +.vercel +*.local .DS_Store diff --git a/frontend/docs/README.md b/frontend/docs/README.md index 9027774..1dff518 100644 --- a/frontend/docs/README.md +++ b/frontend/docs/README.md @@ -1,23 +1,29 @@ -# docs +# OpenScience docs -The OpenScience documentation and session-share site, built with [Astro Starlight](https://starlight.astro.build/). +The documentation site for OpenScience, the open-source AI workbench for scientific research. It ships at [openscience.sh/docs](https://openscience.sh/docs). -This package is part of the bun workspace, so install dependencies from the repo root: +It is a small Vite + React app that renders a folder of MDX pages — no docs framework, no CMS, no server. Pages live in `src/content/openscience/` as `.mdx` files plus a `docs.json` that drives the sidebar. Routing is hash-based (`#/openscience/`), so the whole thing is a static single-page app. + +## Develop ```bash -bun install +bun install # from the repo root +bun run --cwd frontend/docs dev # hot-reloads .mdx edits ``` -Then run the dev server: +## Build ```bash -bun run --cwd frontend/docs dev +bun run --cwd frontend/docs build # emits dist/ with assets under /docs/ +bun run --cwd frontend/docs typecheck # tsc --noEmit ``` -Or build the site: +## Add a page -```bash -bun run --cwd frontend/docs build -``` +1. Create `src/content/openscience/.mdx` with `title` and `description` frontmatter. +2. Add the page to `src/content/openscience/docs.json` under the right group. +3. Internal links use `/openscience/`; they resolve to hash routes at build. + +## Deploy -Pages live in `src/content/docs/` as `.md`/`.mdx` files, each exposed as a route based on its file name. +Vite `base` is `/docs/` so asset URLs resolve beneath the `/docs` path. The build command is `bun run build`, the output directory is `dist`, and deep links under `/docs` fall back to `index.html` (see `vercel.json`). Merges to `main` deploy automatically. diff --git a/frontend/docs/astro.config.mjs b/frontend/docs/astro.config.mjs deleted file mode 100644 index 7a9fb23..0000000 --- a/frontend/docs/astro.config.mjs +++ /dev/null @@ -1,143 +0,0 @@ -// @ts-check -import { defineConfig } from "astro/config" -import starlight from "@astrojs/starlight" -import solidJs from "@astrojs/solid-js" -import cloudflare from "@astrojs/cloudflare" -import theme from "toolbeam-docs-theme" -import config from "./config.mjs" -import { rehypeHeadingIds } from "@astrojs/markdown-remark" -import rehypeAutolinkHeadings from "rehype-autolink-headings" -import { spawnSync } from "child_process" - -// https://astro.build/config -export default defineConfig({ - site: config.url, - base: "/docs", - output: "server", - adapter: cloudflare({ - imageService: "passthrough", - }), - devToolbar: { - enabled: false, - }, - server: { - host: "0.0.0.0", - }, - markdown: { - rehypePlugins: [rehypeHeadingIds, [rehypeAutolinkHeadings, { behavior: "wrap" }]], - }, - build: {}, - integrations: [ - configSchema(), - solidJs(), - starlight({ - title: "OpenScience", - favicon: "/favicon-v3.svg", - head: [ - { - tag: "link", - attrs: { - rel: "icon", - href: "/favicon-v3.ico", - sizes: "32x32", - }, - }, - { - tag: "link", - attrs: { - rel: "icon", - type: "image/png", - href: "/favicon-96x96-v3.png", - sizes: "96x96", - }, - }, - { - tag: "link", - attrs: { - rel: "apple-touch-icon", - href: "/apple-touch-icon-v3.png", - sizes: "180x180", - }, - }, - ], - lastUpdated: true, - expressiveCode: { themes: ["github-light", "github-dark"] }, - social: [ - { icon: "github", label: "GitHub", href: config.github }, - { icon: "discord", label: "Discord", href: config.discord }, - ], - editLink: { - baseUrl: `${config.github}/edit/main/frontend/docs/`, - }, - markdown: { - headingLinks: false, - }, - customCss: ["./src/styles/custom.css"], - logo: { - light: "./src/assets/logo-light.svg", - dark: "./src/assets/logo-dark.svg", - replacesTitle: true, - }, - sidebar: [ - "", - "config", - "providers", - "network", - "enterprise", - "troubleshooting", - "1-0", - { - label: "Usage", - items: ["web", "cli", "atlas", "share", "github", "gitlab"], - }, - - { - label: "Configure", - items: [ - "tools", - "rules", - "agents", - "models", - "themes", - "commands", - "formatters", - "permissions", - "lsp", - "mcp-servers", - "acp", - "skills", - "custom-tools", - ], - }, - - { - label: "Develop", - items: ["sdk", "server", "plugins", "ecosystem"], - }, - ], - components: { - Hero: "./src/components/Hero.astro", - Head: "./src/components/Head.astro", - Header: "./src/components/Header.astro", - SiteTitle: "./src/components/SiteTitle.astro", - }, - plugins: [ - theme({ - headerLinks: config.headerLinks, - }), - ], - }), - ], -}) - -function configSchema() { - return { - name: "configSchema", - hooks: { - "astro:build:done": async () => { - console.log("generating config schema") - spawnSync("../../backend/cli/script/schema.ts", ["./dist/config.json"]) - }, - }, - } -} diff --git a/frontend/docs/config.mjs b/frontend/docs/config.mjs deleted file mode 100644 index 62c266a..0000000 --- a/frontend/docs/config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -const stage = process.env.SST_STAGE || "dev" - -export default { - url: stage === "production" ? "https://syntheticsciences.ai" : `https://${stage}.syntheticsciences.ai`, - console: stage === "production" ? "https://syntheticsciences.ai/auth" : `https://${stage}.syntheticsciences.ai/auth`, - email: "contact@syntheticsciences.ai", - socialCard: "https://syntheticsciences.ai/social-cards", - github: "https://github.com/synthetic-sciences/OpenScience", - discord: "https://syntheticsciences.ai/discord", - headerLinks: [ - { name: "Home", url: "/" }, - { name: "Docs", url: "/docs/" }, - ], -} diff --git a/frontend/docs/index.html b/frontend/docs/index.html new file mode 100644 index 0000000..bf15b58 --- /dev/null +++ b/frontend/docs/index.html @@ -0,0 +1,22 @@ + + + + + + + OpenScience Docs + + + + + + + + +
+ + + diff --git a/frontend/docs/package.json b/frontend/docs/package.json index c846481..4759379 100644 --- a/frontend/docs/package.json +++ b/frontend/docs/package.json @@ -1,41 +1,27 @@ { "name": "@synsci/docs", + "private": true, "type": "module", - "license": "Apache-2.0", "version": "1.2.2", + "license": "Apache-2.0", "scripts": { - "dev": "astro dev", - "dev:remote": "VITE_API_URL=https://api.syntheticsciences.ai astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview", - "astro": "astro" + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "typecheck": "tsc --noEmit" }, "dependencies": { - "@astrojs/cloudflare": "12.6.3", - "@astrojs/markdown-remark": "6.3.1", - "@astrojs/solid-js": "5.1.0", - "@astrojs/starlight": "0.34.3", - "@fontsource/ibm-plex-mono": "5.2.5", - "@shikijs/transformers": "3.4.2", - "@types/luxon": "catalog:", - "ai": "catalog:", - "astro": "5.7.13", - "diff": "catalog:", - "js-base64": "3.7.7", - "lang-map": "0.4.0", - "luxon": "catalog:", - "marked": "catalog:", - "marked-shiki": "catalog:", - "rehype-autolink-headings": "7.1.0", - "remeda": "catalog:", - "shiki": "catalog:", - "solid-js": "catalog:", - "toolbeam-docs-theme": "0.4.8" + "lucide-react": "^0.453.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-markdown": "^9.0.1", + "remark-gfm": "^4.0.0" }, "devDependencies": { - "@synsci/openscience": "workspace:*", - "@types/node": "catalog:", - "typescript": "catalog:" + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.6.3", + "vite": "^6.0.5" } } diff --git a/frontend/docs/public/apple-touch-icon-v3.png b/frontend/docs/public/apple-touch-icon-v3.png deleted file mode 120000 index a6f48a6..0000000 --- a/frontend/docs/public/apple-touch-icon-v3.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/apple-touch-icon-v3.png \ No newline at end of file diff --git a/frontend/docs/public/apple-touch-icon-v4.png b/frontend/docs/public/apple-touch-icon-v4.png deleted file mode 120000 index c1522b9..0000000 --- a/frontend/docs/public/apple-touch-icon-v4.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/apple-touch-icon-v4.png \ No newline at end of file diff --git a/frontend/docs/public/apple-touch-icon.png b/frontend/docs/public/apple-touch-icon.png deleted file mode 120000 index fb6e8b1..0000000 --- a/frontend/docs/public/apple-touch-icon.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/apple-touch-icon.png \ No newline at end of file diff --git a/frontend/docs/public/favicon-96x96-v3.png b/frontend/docs/public/favicon-96x96-v3.png deleted file mode 120000 index 5d21163..0000000 --- a/frontend/docs/public/favicon-96x96-v3.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-96x96-v3.png \ No newline at end of file diff --git a/frontend/docs/public/favicon-96x96-v4.png b/frontend/docs/public/favicon-96x96-v4.png deleted file mode 120000 index 3639600..0000000 --- a/frontend/docs/public/favicon-96x96-v4.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-96x96-v4.png \ No newline at end of file diff --git a/frontend/docs/public/favicon-96x96.png b/frontend/docs/public/favicon-96x96.png deleted file mode 120000 index 155c5ed..0000000 --- a/frontend/docs/public/favicon-96x96.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-96x96.png \ No newline at end of file diff --git a/frontend/docs/public/favicon-v3.ico b/frontend/docs/public/favicon-v3.ico deleted file mode 120000 index b3da91f..0000000 --- a/frontend/docs/public/favicon-v3.ico +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-v3.ico \ No newline at end of file diff --git a/frontend/docs/public/favicon-v3.svg b/frontend/docs/public/favicon-v3.svg deleted file mode 120000 index fc95f68..0000000 --- a/frontend/docs/public/favicon-v3.svg +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-v3.svg \ No newline at end of file diff --git a/frontend/docs/public/favicon-v4.ico b/frontend/docs/public/favicon-v4.ico deleted file mode 120000 index 8b44346..0000000 --- a/frontend/docs/public/favicon-v4.ico +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-v4.ico \ No newline at end of file diff --git a/frontend/docs/public/favicon-v4.svg b/frontend/docs/public/favicon-v4.svg deleted file mode 120000 index 8afce04..0000000 --- a/frontend/docs/public/favicon-v4.svg +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon-v4.svg \ No newline at end of file diff --git a/frontend/docs/public/favicon.ico b/frontend/docs/public/favicon.ico deleted file mode 120000 index 1c90f01..0000000 --- a/frontend/docs/public/favicon.ico +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon.ico \ No newline at end of file diff --git a/frontend/docs/public/favicon.svg b/frontend/docs/public/favicon.svg deleted file mode 120000 index 80804d2..0000000 --- a/frontend/docs/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/favicon.svg \ No newline at end of file diff --git a/frontend/docs/public/favicon.svg b/frontend/docs/public/favicon.svg new file mode 100644 index 0000000..7410f40 --- /dev/null +++ b/frontend/docs/public/favicon.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/frontend/docs/public/fonts/cmc/OFL.txt b/frontend/docs/public/fonts/cmc/OFL.txt new file mode 100644 index 0000000..a55bb6b --- /dev/null +++ b/frontend/docs/public/fonts/cmc/OFL.txt @@ -0,0 +1,103 @@ +Copyright (C) Authors of original metafont fonts: +Donald Ervin Knuth (cm, concrete fonts) +1995, 1996, 1997 J"org Knappen, 1990, 1992 Norbert Schwarz (ec fonts) +1992-2006 A.Khodulev, O.Lapko, A.Berdnikov, V.Volovich (lh fonts) +1997-2005 Claudio Beccari (cb greek fonts) +2002 FUKUI Rei (tipa fonts) +2003-2005 Han The Thanh (Vietnamese fonts) +1996-2005 Walter Schmidt (cmbright fonts) + +Copyright (C) 2003-2009, Andrey V. Panov (panov@canopus.iacp.dvo.ru), +with Reserved Font Family Name "Computer Modern Unicode fonts". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/frontend/docs/public/fonts/cmc/cmunobx.woff2 b/frontend/docs/public/fonts/cmc/cmunobx.woff2 new file mode 100644 index 0000000..bd558fc Binary files /dev/null and b/frontend/docs/public/fonts/cmc/cmunobx.woff2 differ diff --git a/frontend/docs/public/fonts/cmc/cmunorm.woff2 b/frontend/docs/public/fonts/cmc/cmunorm.woff2 new file mode 100644 index 0000000..75b62ec Binary files /dev/null and b/frontend/docs/public/fonts/cmc/cmunorm.woff2 differ diff --git a/frontend/docs/public/robots.txt b/frontend/docs/public/robots.txt deleted file mode 100644 index bddac69..0000000 --- a/frontend/docs/public/robots.txt +++ /dev/null @@ -1,6 +0,0 @@ -User-agent: * -Allow: / - -# Disallow shared content pages -Disallow: /s/ -Disallow: /share/ \ No newline at end of file diff --git a/frontend/docs/public/site.webmanifest b/frontend/docs/public/site.webmanifest deleted file mode 120000 index a116d78..0000000 --- a/frontend/docs/public/site.webmanifest +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/site.webmanifest \ No newline at end of file diff --git a/frontend/docs/public/social-share.png b/frontend/docs/public/social-share.png deleted file mode 120000 index 88bf2d4..0000000 --- a/frontend/docs/public/social-share.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/images/social-share.png \ No newline at end of file diff --git a/frontend/docs/public/theme.json b/frontend/docs/public/theme.json deleted file mode 100644 index 7c80776..0000000 --- a/frontend/docs/public/theme.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "$schema": { - "type": "string", - "description": "JSON schema reference for configuration validation" - }, - "defs": { - "type": "object", - "description": "Color definitions that can be referenced in the theme", - "patternProperties": { - "^[a-zA-Z][a-zA-Z0-9_]*$": { - "oneOf": [ - { - "type": "string", - "pattern": "^#[0-9a-fA-F]{6}$", - "description": "Hex color value" - }, - { - "type": "integer", - "minimum": 0, - "maximum": 255, - "description": "ANSI color code (0-255)" - }, - { - "type": "string", - "enum": ["none"], - "description": "No color (uses terminal default)" - } - ] - } - }, - "additionalProperties": false - }, - "theme": { - "type": "object", - "description": "Theme color definitions", - "properties": { - "primary": { "$ref": "#/definitions/colorValue" }, - "secondary": { "$ref": "#/definitions/colorValue" }, - "accent": { "$ref": "#/definitions/colorValue" }, - "error": { "$ref": "#/definitions/colorValue" }, - "warning": { "$ref": "#/definitions/colorValue" }, - "success": { "$ref": "#/definitions/colorValue" }, - "info": { "$ref": "#/definitions/colorValue" }, - "text": { "$ref": "#/definitions/colorValue" }, - "textMuted": { "$ref": "#/definitions/colorValue" }, - "selectedListItemText": { "$ref": "#/definitions/colorValue" }, - "background": { "$ref": "#/definitions/colorValue" }, - "backgroundPanel": { "$ref": "#/definitions/colorValue" }, - "backgroundElement": { "$ref": "#/definitions/colorValue" }, - "border": { "$ref": "#/definitions/colorValue" }, - "borderActive": { "$ref": "#/definitions/colorValue" }, - "borderSubtle": { "$ref": "#/definitions/colorValue" }, - "diffAdded": { "$ref": "#/definitions/colorValue" }, - "diffRemoved": { "$ref": "#/definitions/colorValue" }, - "diffContext": { "$ref": "#/definitions/colorValue" }, - "diffHunkHeader": { "$ref": "#/definitions/colorValue" }, - "diffHighlightAdded": { "$ref": "#/definitions/colorValue" }, - "diffHighlightRemoved": { "$ref": "#/definitions/colorValue" }, - "diffAddedBg": { "$ref": "#/definitions/colorValue" }, - "diffRemovedBg": { "$ref": "#/definitions/colorValue" }, - "diffContextBg": { "$ref": "#/definitions/colorValue" }, - "diffLineNumber": { "$ref": "#/definitions/colorValue" }, - "diffAddedLineNumberBg": { "$ref": "#/definitions/colorValue" }, - "diffRemovedLineNumberBg": { "$ref": "#/definitions/colorValue" }, - "markdownText": { "$ref": "#/definitions/colorValue" }, - "markdownHeading": { "$ref": "#/definitions/colorValue" }, - "markdownLink": { "$ref": "#/definitions/colorValue" }, - "markdownLinkText": { "$ref": "#/definitions/colorValue" }, - "markdownCode": { "$ref": "#/definitions/colorValue" }, - "markdownBlockQuote": { "$ref": "#/definitions/colorValue" }, - "markdownEmph": { "$ref": "#/definitions/colorValue" }, - "markdownStrong": { "$ref": "#/definitions/colorValue" }, - "markdownHorizontalRule": { "$ref": "#/definitions/colorValue" }, - "markdownListItem": { "$ref": "#/definitions/colorValue" }, - "markdownListEnumeration": { "$ref": "#/definitions/colorValue" }, - "markdownImage": { "$ref": "#/definitions/colorValue" }, - "markdownImageText": { "$ref": "#/definitions/colorValue" }, - "markdownCodeBlock": { "$ref": "#/definitions/colorValue" }, - "syntaxComment": { "$ref": "#/definitions/colorValue" }, - "syntaxKeyword": { "$ref": "#/definitions/colorValue" }, - "syntaxFunction": { "$ref": "#/definitions/colorValue" }, - "syntaxVariable": { "$ref": "#/definitions/colorValue" }, - "syntaxString": { "$ref": "#/definitions/colorValue" }, - "syntaxNumber": { "$ref": "#/definitions/colorValue" }, - "syntaxType": { "$ref": "#/definitions/colorValue" }, - "syntaxOperator": { "$ref": "#/definitions/colorValue" }, - "syntaxPunctuation": { "$ref": "#/definitions/colorValue" } - }, - "required": ["primary", "secondary", "accent", "text", "textMuted", "background"], - "additionalProperties": false - } - }, - "required": ["theme"], - "additionalProperties": false, - "definitions": { - "colorValue": { - "oneOf": [ - { - "type": "string", - "pattern": "^#[0-9a-fA-F]{6}$", - "description": "Hex color value (same for dark and light)" - }, - { - "type": "integer", - "minimum": 0, - "maximum": 255, - "description": "ANSI color code (0-255, same for dark and light)" - }, - { - "type": "string", - "enum": ["none"], - "description": "No color (uses terminal default)" - }, - { - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", - "description": "Reference to another color in the theme or defs" - }, - { - "type": "object", - "properties": { - "dark": { - "oneOf": [ - { - "type": "string", - "pattern": "^#[0-9a-fA-F]{6}$", - "description": "Hex color value for dark mode" - }, - { - "type": "integer", - "minimum": 0, - "maximum": 255, - "description": "ANSI color code for dark mode" - }, - { - "type": "string", - "enum": ["none"], - "description": "No color (uses terminal default)" - }, - { - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", - "description": "Reference to another color for dark mode" - } - ] - }, - "light": { - "oneOf": [ - { - "type": "string", - "pattern": "^#[0-9a-fA-F]{6}$", - "description": "Hex color value for light mode" - }, - { - "type": "integer", - "minimum": 0, - "maximum": 255, - "description": "ANSI color code for light mode" - }, - { - "type": "string", - "enum": ["none"], - "description": "No color (uses terminal default)" - }, - { - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$", - "description": "Reference to another color for light mode" - } - ] - } - }, - "required": ["dark", "light"], - "additionalProperties": false, - "description": "Separate colors for dark and light modes" - } - ] - } - } -} diff --git a/frontend/docs/public/web-app-manifest-192x192.png b/frontend/docs/public/web-app-manifest-192x192.png deleted file mode 120000 index 8cfdf8c..0000000 --- a/frontend/docs/public/web-app-manifest-192x192.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/web-app-manifest-192x192.png \ No newline at end of file diff --git a/frontend/docs/public/web-app-manifest-512x512.png b/frontend/docs/public/web-app-manifest-512x512.png deleted file mode 120000 index 4165998..0000000 --- a/frontend/docs/public/web-app-manifest-512x512.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/favicon/web-app-manifest-512x512.png \ No newline at end of file diff --git a/frontend/docs/src/App.tsx b/frontend/docs/src/App.tsx new file mode 100644 index 0000000..853a100 --- /dev/null +++ b/frontend/docs/src/App.tsx @@ -0,0 +1,5 @@ +import { DocumentationPage } from "./DocsApp" + +export function App() { + return +} diff --git a/frontend/docs/src/DocsApp.tsx b/frontend/docs/src/DocsApp.tsx new file mode 100644 index 0000000..874841d --- /dev/null +++ b/frontend/docs/src/DocsApp.tsx @@ -0,0 +1,1779 @@ +import { useEffect, useMemo, useState, type CSSProperties, type ReactNode } from "react" +import ReactMarkdown, { type Components } from "react-markdown" +import remarkGfm from "remark-gfm" +import { + ArrowUpRight, + BookOpen, + Bot, + ChevronLeft, + ChevronRight, + Check, + Copy, + FlaskConical, + GitBranch, + Layers, + Moon, + PackageCheck, + Rocket, + Search, + ShieldCheck, + Star, + Sun, + Terminal, +} from "lucide-react" +import { useTheme } from "./theme" + +const mono = `"JetBrains Mono", "SF Mono", ui-monospace, monospace` + +const DOCS_SERIF = `"Computer Modern Concrete", "Concrete Roman", Georgia, "Times New Roman", serif` + +type DocsConfig = { + name?: string + navigation: { + tabs: Array<{ + tab: string + groups: Array<{ + group: string + pages: Array + }> + }> + global?: { + anchors?: Array<{ + anchor: string + href: string + }> + } + } + navbar?: { + links?: Array<{ + label: string + href: string + }> + primary?: { + label: string + href: string + } + } +} + +type DocsPage = { + path: string + title: string + description: string + icon: ReactNode + body: string + headings: string[] +} + +type SearchResult = Pick & { + section: SectionKey + sectionLabel: string +} + +type MintlifyCard = { + title: string + href: string + icon?: string + body: string + horizontal?: boolean +} + +type SectionKey = "openscience" + +type Section = { + key: SectionKey + label: string + short: string + tagline: string + lead: boolean +} + +const SECTIONS: Section[] = [ + { key: "openscience", label: "OpenScience", short: "OpenScience", tagline: "Open-source AI workbench", lead: false }, +] + +const SECTION_KEYS = SECTIONS.map((section) => section.key) + +// All MDX content and per-section configs, loaded at build time. Adding a page is +// just dropping an .mdx file into the right content/
/ folder. +const RAW_PAGES = import.meta.glob("./content/**/*.{mdx,md}", { + query: "?raw", + import: "default", + eager: true, +}) as Record + +const RAW_CONFIGS = import.meta.glob("./content/**/docs.json", { + import: "default", + eager: true, +}) as Record + +const ICONS: Record = { + index: , + quickstart: , + workspace: , + agents: , + models: , + skills: , + sessions: , + atlas: , + commands: , + security: , +} + +const SECTION_FALLBACK_ICON: Record = { + openscience: , +} + +const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?/ + +function parseFrontmatter(source: string): { title: string; description: string; body: string } { + const match = source.match(FRONTMATTER_RE) + if (!match) return { title: "Untitled", description: "", body: source } + const frontmatter = match[1] + const body = source.slice(match[0].length) + const field = (name: string) => { + const line = frontmatter.split("\n").find((entry) => entry.trim().startsWith(`${name}:`)) + return line + ? line + .split(":") + .slice(1) + .join(":") + .trim() + .replace(/^["']|["']$/g, "") + : "" + } + return { + title: field("title") || "Untitled", + description: field("description"), + body, + } +} + +function extractHeadings(markdown: string): string[] { + return markdown + .split("\n") + .filter((line) => line.startsWith("## ")) + .map((line) => line.replace(/^##\s+/, "").trim()) + .slice(0, 10) +} + +function flattenPages(items: Array): string[] { + return items.flatMap((item) => (typeof item === "string" ? [item] : item.pages)) +} + +function iconForPath(path: string, section: SectionKey): ReactNode { + const leaf = path.split("/").pop() ?? path + return ICONS[path] ?? ICONS[leaf] ?? SECTION_FALLBACK_ICON[section] +} + +function buildSectionPages(section: SectionKey): Record { + const prefix = `./content/${section}/` + const pages: Record = {} + for (const [key, source] of Object.entries(RAW_PAGES)) { + if (!key.startsWith(prefix)) continue + const path = key.slice(prefix.length).replace(/\.(mdx|md)$/, "") + const parsed = parseFrontmatter(source) + pages[path] = { + path, + title: parsed.title, + description: parsed.description, + icon: iconForPath(path, section), + body: parsed.body, + headings: extractHeadings(parsed.body), + } + } + return pages +} + +const SECTION_DOC_PAGES: Record> = { + openscience: buildSectionPages("openscience"), +} + +const SECTION_CONFIGS: Record = { + openscience: RAW_CONFIGS["./content/openscience/docs.json"], +} + +function pageExists(section: SectionKey, path: string): boolean { + return Boolean(SECTION_DOC_PAGES[section]?.[path]) +} + +// Retired first URL segments that redirect into the openscience scheme. +const SECTION_ALIASES: Record = { + "agent-cli": "openscience", +} + +// Old CLI page names that moved during the OpenScience rebuild. +const PAGE_ALIASES: Record = { + "first-session": "sessions", + "sub-agents": "agents", + "web-ui": "workspace", + credentials: "atlas", +} + +// Redirects from the oldest single-segment URLs to the #/
/ scheme. +const LEGACY_REDIRECTS: Record = { + "cli:index": { section: "openscience", path: "index" }, + "cli:installation": { section: "openscience", path: "quickstart" }, + "cli:quickstart": { section: "openscience", path: "quickstart" }, + "cli:first-session": { section: "openscience", path: "sessions" }, + "cli:sessions": { section: "openscience", path: "sessions" }, + "cli:models": { section: "openscience", path: "models" }, + "cli:codex": { section: "openscience", path: "models" }, + "cli:sub-agents": { section: "openscience", path: "agents" }, + "cli:skills": { section: "openscience", path: "skills" }, + "cli:cli-runtime": { section: "openscience", path: "commands" }, + "cli:connect": { section: "openscience", path: "atlas" }, + "cli:credentials": { section: "openscience", path: "atlas" }, + "cli:security": { section: "openscience", path: "security" }, + "cli:feature-map": { section: "openscience", path: "commands" }, + "cli:commands": { section: "openscience", path: "commands" }, + "cli:web-ui": { section: "openscience", path: "workspace" }, + "cli:server-mode": { section: "openscience", path: "workspace" }, +} + +type Route = { section: SectionKey; path: string } + +function defaultRoute(): Route { + return { section: "openscience", path: "index" } +} + +function routeFromHash(): Route { + if (typeof window === "undefined") return defaultRoute() + const raw = decodeURIComponent(window.location.hash.replace(/^#\/?/, "")).replace(/\/$/, "") + if (!raw) return defaultRoute() + const segments = raw.split("/") + const maybeSection = segments[0] as SectionKey + if (SECTION_KEYS.includes(maybeSection)) { + const path = segments.slice(1).join("/") || "index" + if (pageExists(maybeSection, path)) return { section: maybeSection, path } + return { section: maybeSection, path: "index" } + } + // Retired section names redirect into the openscience scheme. + const aliasSection = SECTION_ALIASES[segments[0]] + if (aliasSection) { + const rawPath = segments.slice(1).join("/") || "index" + const path = PAGE_ALIASES[rawPath] ?? rawPath + if (pageExists(aliasSection, path)) return { section: aliasSection, path } + return { section: aliasSection, path: "index" } + } + // Legacy single-segment URL from the old CLI docs. + const redirect = LEGACY_REDIRECTS[`cli:${raw}`] + if (redirect && pageExists(redirect.section, redirect.path)) return redirect + return defaultRoute() +} + +function pageHref(section: SectionKey, path: string): string { + return `#/${section}/${path}` +} + +// Module-level pointers updated on each render so the markdown renderer (which +// can't take props through react-markdown) can resolve links and card icons. +let CURRENT_SECTION: SectionKey = "openscience" + +function resolveHref(href: string | undefined): string | undefined { + if (!href) return href + if (href.startsWith("http") || href.startsWith("#") || href.startsWith("mailto:")) return href + if (href.startsWith("/")) { + const clean = href.slice(1).replace(/\/$/, "") + if (!clean) return pageHref(CURRENT_SECTION, "index") + const segments = clean.split("/") + const maybeSection = segments[0] as SectionKey + if (SECTION_KEYS.includes(maybeSection)) { + const path = segments.slice(1).join("/") || "index" + if (pageExists(maybeSection, path)) return pageHref(maybeSection, path) + } + if (pageExists(CURRENT_SECTION, clean)) return pageHref(CURRENT_SECTION, clean) + } + return href +} + +function sectionForHref(href: string): SectionKey { + const clean = href.replace(/^#\/?/, "").replace(/\/$/, "") + const segments = clean.split("/") + const maybeSection = segments[0] as SectionKey + return SECTION_KEYS.includes(maybeSection) ? maybeSection : CURRENT_SECTION +} + +function parseMdxAttrs(attrs: string): Record { + const parsed: Record = {} + for (const match of attrs.matchAll(/([\w-]+)(?:=(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/g)) { + const key = match[1] + if (!key) continue + parsed[key] = match[2] ?? match[3] ?? match[4] ?? true + } + return parsed +} + +function dedent(source: string): string { + const lines = source.replace(/\t/g, " ").split("\n") + let min = Infinity + for (const line of lines) { + if (line.trim() === "") continue + const leading = line.match(/^( *)/) + if (leading) min = Math.min(min, leading[1].length) + } + if (!Number.isFinite(min) || min === 0) return source + return lines.map((line) => (line.length >= min ? line.slice(min) : line)).join("\n") +} + +function parseCards(source: string): MintlifyCard[] { + return Array.from(source.matchAll(/]*)>\s*([\s\S]*?)\s*<\/Card>/g)).map((match) => { + const attrs = parseMdxAttrs(match[1] ?? "") + return { + title: String(attrs.title ?? "Untitled"), + href: String(attrs.href ?? "#"), + icon: attrs.icon ? String(attrs.icon) : undefined, + horizontal: Boolean(attrs.horizontal), + body: dedent(match[2] ?? "").trim(), + } + }) +} + +function iconForCard(card: MintlifyCard): ReactNode { + const resolved = resolveHref(card.href) + if (resolved && resolved.startsWith("#/")) { + const section = sectionForHref(resolved) + const path = resolved.replace(/^#\/?/, "").replace(/\/$/, "").split("/").slice(1).join("/") + const page = SECTION_DOC_PAGES[section]?.[path] + if (page) return page.icon + } + return +} + +const OPENSCIENCE_REPO = "synthetic-sciences/openscience" + +function formatStars(count: number): string { + return count >= 1000 ? `${(count / 1000).toFixed(1).replace(/\.0$/, "")}k` : String(count) +} + +function GitHubStars() { + const [stars, setStars] = useState(null) + + useEffect(() => { + let cancelled = false + const cacheKey = `docs-gh-stars:${OPENSCIENCE_REPO}` + try { + const cached = JSON.parse(window.localStorage.getItem(cacheKey) ?? "null") as { stars: number; at: number } | null + if (cached && Date.now() - cached.at < 60 * 60 * 1000) { + setStars(cached.stars) + return + } + } catch { + /* ignore */ + } + fetch(`https://api.github.com/repos/${OPENSCIENCE_REPO}`) + .then((response) => (response.ok ? response.json() : null)) + .then((data: { stargazers_count?: number } | null) => { + const count = data?.stargazers_count + if (typeof count !== "number" || cancelled) return + setStars(count) + try { + window.localStorage.setItem(cacheKey, JSON.stringify({ stars: count, at: Date.now() })) + } catch { + /* ignore */ + } + }) + .catch(() => undefined) + return () => { + cancelled = true + } + }, []) + + return ( + + ) +} + +function CopyButton({ text }: { text: string }) { + const [copied, setCopied] = useState(false) + return ( + + ) +} + +const markdownComponents: Components = { + h2({ children }) { + const id = String(children) + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-|-$/g, "") + return

{children}

+ }, + a({ href, children }) { + const external = href?.startsWith("http") + const internalDocsHref = href ? resolveHref(href) : undefined + return ( + + {children} + {external ? : null} + + ) + }, + pre({ children }) { + const text = extractCodeText(children) + return ( +
+ +
{children}
+
+ ) + }, + code({ className, children }) { + const isBlock = className?.startsWith("language-") + return {children} + }, + table({ children }) { + return ( +
+ {children}
+
+ ) + }, + blockquote({ children }) { + return
{children}
+ }, +} + +function extractCodeText(node: ReactNode): string { + if (typeof node === "string") return node + if (Array.isArray(node)) return node.map(extractCodeText).join("") + if (node && typeof node === "object" && "props" in node) { + const props = (node as { props?: { children?: ReactNode } }).props + return extractCodeText(props?.children ?? "") + } + return "" +} + +function MarkdownChunk({ children }: { children: string }) { + if (!children.trim()) return null + return ( + + {children} + + ) +} + +function MintlifyCardView({ card }: { card: MintlifyCard }) { + const external = card.href.startsWith("http") + return ( + + {iconForCard(card)} + + {card.title} + {card.body} + + + + ) +} + +function MintlifyCardGrid({ source, cols }: { source: string; cols: number }) { + const cards = parseCards(source) + if (cards.length === 0) return null + return ( +
+ {cards.map((card) => ( + + ))} +
+ ) +} + +function MintlifySteps({ source }: { source: string }) { + const steps = Array.from(source.matchAll(/]*)>\s*([\s\S]*?)\s*<\/Step>/g)).map((match) => { + const attrs = parseMdxAttrs(match[1] ?? "") + return { + title: String(attrs.title ?? "Step"), + body: dedent(match[2] ?? "").trim(), + } + }) + if (steps.length === 0) return null + return ( +
+ {steps.map((step, index) => ( +
+ {index + 1} +
+

{step.title}

+ {step.body} +
+
+ ))} +
+ ) +} + +function MintlifyCallout({ children }: { children: string }) { + return ( +
+ {dedent(children).trim()} +
+ ) +} + +function renderMintlifyContent(source: string): ReactNode[] { + const nodes: ReactNode[] = [] + const componentRe = + /<(Columns|CardGroup)\b([^>]*)>\s*([\s\S]*?)\s*<\/\1>|]*)>\s*([\s\S]*?)\s*<\/Card>|\s*([\s\S]*?)\s*<\/Steps>|\s*([\s\S]*?)\s*<\/Warning>|/g + let lastIndex = 0 + let index = 0 + + for (const match of source.matchAll(componentRe)) { + const matchIndex = match.index ?? 0 + const before = source.slice(lastIndex, matchIndex) + if (before.trim()) nodes.push({before}) + + if (match[1]) { + const attrs = parseMdxAttrs(match[2] ?? "") + const cols = Number(attrs.cols ?? 2) + nodes.push( + 0 ? cols : 2} + />, + ) + } else if (match[4] !== undefined) { + const card = parseCards(`${match[5] ?? ""}`)[0] + if (card) nodes.push() + } else if (match[6] !== undefined) { + nodes.push() + } else if (match[7] !== undefined) { + nodes.push({match[7] ?? ""}) + } else if (match[0].startsWith(") + } + + lastIndex = matchIndex + match[0].length + } + + const tail = source.slice(lastIndex) + if (tail.trim()) nodes.push({tail}) + return nodes +} + +export function DocumentationPage() { + const { theme, toggle: toggleTheme } = useTheme() + const [route, setRouteState] = useState(() => routeFromHash()) + const section = route.section + CURRENT_SECTION = section + const docPages = SECTION_DOC_PAGES[section] + const config = SECTION_CONFIGS[section] + const sectionMeta = SECTIONS.find((entry) => entry.key === section) ?? SECTIONS[0] + const activePage = docPages[route.path] ?? docPages.index + const [query, setQuery] = useState("") + const [searchOpen, setSearchOpen] = useState(false) + + const navTabs = config.navigation.tabs + const orderedPaths = useMemo( + () => + navTabs + .flatMap((tab) => tab.groups.flatMap((group) => flattenPages(group.pages))) + .filter((path) => docPages[path]), + [navTabs, docPages], + ) + const activeTab = useMemo( + () => + navTabs.find((tab) => tab.groups.some((group) => flattenPages(group.pages).includes(activePage.path))) ?? + navTabs[0], + [activePage.path, navTabs], + ) + const activeGroup = useMemo( + () => activeTab?.groups.find((group) => flattenPages(group.pages).includes(activePage.path)), + [activePage.path, activeTab], + ) + const activeIndex = orderedPaths.indexOf(activePage.path) + const previousPage = activeIndex > 0 ? docPages[orderedPaths[activeIndex - 1]] : null + const nextPage = + activeIndex >= 0 && activeIndex < orderedPaths.length - 1 ? docPages[orderedPaths[activeIndex + 1]] : null + + // Search spans every section so people can jump anywhere from one box. + const searchResults = useMemo(() => { + const all: SearchResult[] = SECTIONS.flatMap((entry) => { + const pages = SECTION_CONFIGS[entry.key].navigation.tabs + .flatMap((tab) => tab.groups.flatMap((group) => flattenPages(group.pages))) + .map((path) => SECTION_DOC_PAGES[entry.key][path]) + .filter(Boolean) + return pages.map((page) => ({ + path: page.path, + title: page.title, + description: page.description, + icon: page.icon, + section: entry.key, + sectionLabel: entry.label, + })) + }) + const normalizedQuery = query.trim().toLowerCase() + if (!normalizedQuery) { + return all.filter((page) => page.section === section).slice(0, 6) + } + return all + .filter((page) => { + const body = SECTION_DOC_PAGES[page.section][page.path]?.body ?? "" + const haystack = `${page.title} ${page.description} ${page.sectionLabel} ${body}`.toLowerCase() + return haystack.includes(normalizedQuery) + }) + .slice(0, 8) + }, [query, section]) + + const navigate = (next: Route) => { + window.location.hash = pageHref(next.section, next.path) + setRouteState(next) + } + + useEffect(() => { + const onHashChange = () => setRouteState(routeFromHash()) + window.addEventListener("hashchange", onHashChange) + return () => window.removeEventListener("hashchange", onHashChange) + }, []) + + // Keep the URL canonical (legacy + bare hashes resolve to #/
/). + useEffect(() => { + const canonical = pageHref(route.section, route.path) + if (window.location.hash !== canonical) { + window.history.replaceState(null, "", canonical) + } + }, [route.section, route.path]) + + useEffect(() => { + const onKeyDown = (event: KeyboardEvent) => { + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") { + event.preventDefault() + setSearchOpen(true) + document.querySelector(".docs-search-input")?.focus() + } + } + window.addEventListener("keydown", onKeyDown) + return () => window.removeEventListener("keydown", onKeyDown) + }, []) + + return ( +
+
+ + + + OpenScience + Docs + + +
+ + window.setTimeout(() => setSearchOpen(false), 120)} + onChange={(event) => { + setQuery(event.target.value) + setSearchOpen(true) + }} + onFocus={() => setSearchOpen(true)} + placeholder="Search all docs..." + type="search" + /> + ⌘K + {searchOpen ? ( + + ) : null} +
+ +
+ +
+ + +
+ +
+

{activePage.title}

+ {activePage.description ?

{activePage.description}

: null} +
+ +
{renderMintlifyContent(activePage.body)}
+ + +
+ + +
+ + +
+ ) +} + +const docsCss = ` + .docs-page { + --color-bg: #fafbfc; + --color-bg-subtle: #f1f3f5; + --color-bg-elevated: #ffffff; + --color-border: rgba(15, 23, 42, 0.10); + --color-text: #0f172a; + --color-text-muted: #475569; + --color-text-faint: #94a3b8; + --docs-accent: #2f6f54; + min-height: 100dvh; + color: var(--color-text); + background: var(--color-bg); + font-family: ${DOCS_SERIF}; + font-feature-settings: "kern", "liga"; + } + + /* No italics anywhere - the font family ships regular and bold only. */ + .docs-page em, + .docs-page i, + .docs-page cite, + .docs-page dfn, + .docs-page address { + font-style: normal; + } + + .dark .docs-page { + --color-bg: #0a0a0b; + --color-bg-subtle: #141417; + --color-bg-elevated: #1c1c20; + --color-border: rgba(255, 255, 255, 0.10); + --color-text: #f1f5f9; + --color-text-muted: #b8bbc4; + --color-text-faint: #6c7280; + --docs-accent: #9bd6b4; + } + + .docs-topbar { + height: 60px; + display: grid; + grid-template-columns: minmax(200px, 1fr) minmax(240px, 520px) minmax(200px, 1fr); + align-items: center; + gap: 20px; + padding: 0 28px; + border-bottom: 1px solid var(--color-border); + background: color-mix(in srgb, var(--color-bg) 94%, transparent); + backdrop-filter: blur(14px); + position: sticky; + top: 0; + z-index: 30; + } + + .docs-topbar nav, + .docs-topbar nav a, + .docs-search, + .docs-copy, + .docs-markdown a { + display: flex; + align-items: center; + } + + .docs-brand { + display: inline-flex; + align-items: center; + gap: 12px; + color: var(--color-text); + text-decoration: none; + min-width: 0; + padding: 4px 6px; + border-radius: 6px; + transition: background 120ms ease; + } + + .docs-brand:hover { + background: var(--color-bg-elevated); + } + + .docs-brand img { + width: 28px; + height: 28px; + flex-shrink: 0; + } + + .docs-brand-text { + display: flex; + flex-direction: column; + gap: 1px; + min-width: 0; + line-height: 1.1; + } + + .docs-brand-text small { + font-family: ${mono}; + font-size: 9.5px; + font-weight: 500; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--color-text-faint); + } + + .docs-brand-text strong { + font-family: ${DOCS_SERIF}; + font-size: 15px; + font-weight: 400; + letter-spacing: 0; + color: var(--color-text); + } + + .docs-search { + position: relative; + height: 34px; + gap: 9px; + border: 1px solid var(--color-border); + border-radius: 6px; + background: var(--color-bg-elevated); + padding: 0 8px 0 12px; + color: var(--color-text-faint); + transition: border-color 120ms ease, background 120ms ease; + } + + .docs-search:focus-within { + border-color: var(--color-text-faint); + background: var(--color-bg); + } + + .docs-search input { + min-width: 0; + flex: 1; + border: 0; + outline: 0; + background: transparent; + color: var(--color-text); + font-family: ${DOCS_SERIF}; + font-size: 14px; + } + + .docs-search input::placeholder { + color: var(--color-text-faint); + font-family: ${DOCS_SERIF}; + } + + .docs-search kbd { + min-width: 32px; + height: 20px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid var(--color-border); + border-radius: 4px; + background: var(--color-bg); + color: var(--color-text-faint); + font-family: ${mono}; + font-size: 10.5px; + font-weight: 500; + flex-shrink: 0; + } + + .docs-search-results { + position: absolute; + top: calc(100% + 8px); + left: 0; + right: 0; + display: flex; + flex-direction: column; + gap: 3px; + padding: 7px; + border: 1px solid var(--color-border); + border-radius: 8px; + background: var(--color-bg-elevated); + box-shadow: 0 18px 48px rgba(0, 0, 0, 0.12); + z-index: 50; + } + + .docs-search-results a { + display: grid; + grid-template-columns: 24px minmax(0, 1fr); + gap: 1px 8px; + align-items: center; + padding: 8px; + border-radius: 7px; + color: var(--color-text); + text-decoration: none; + } + + .docs-search-results a:hover { + background: var(--color-bg-subtle); + } + + .docs-search-results a > span { + grid-row: span 2; + color: var(--color-text-faint); + } + + .docs-search-results strong { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 13px; + font-weight: 700; + } + + .docs-search-results small, + .docs-search-empty { + overflow: hidden; + color: var(--color-text-muted); + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + } + + .docs-search-empty { + padding: 10px; + } + + .docs-topbar nav { + gap: 8px; + justify-content: flex-end; + } + + .docs-actions { + justify-content: flex-end; + gap: 8px; + } + + .docs-topbar nav a { + gap: 6px; + height: 34px; + padding: 0 14px; + border-radius: 6px; + color: var(--color-text-muted); + text-decoration: none; + font-family: ${DOCS_SERIF}; + font-size: 14px; + font-weight: 400; + border: 1px solid transparent; + transition: background 120ms ease, color 120ms ease, border-color 120ms ease; + } + + .docs-topbar nav a:hover { + color: var(--color-text); + background: var(--color-bg-elevated); + border-color: var(--color-border); + } + + .docs-topbar-cta { + color: var(--color-text) !important; + border-color: var(--color-border) !important; + background: var(--color-bg-elevated); + } + + .docs-theme-toggle { + display: inline-flex; + align-items: center; + gap: 6px; + height: 34px; + padding: 0 12px; + border-radius: 6px; + border: 1px solid transparent; + background: transparent; + color: var(--color-text-muted); + font-family: ${DOCS_SERIF}; + font-size: 14px; + font-weight: 400; + line-height: 1; + cursor: pointer; + transition: background 120ms ease, color 120ms ease, border-color 120ms ease; + } + + .docs-theme-toggle:hover { + color: var(--color-text); + background: var(--color-bg-elevated); + border-color: var(--color-border); + } + + .docs-theme-toggle:focus-visible { + outline: 2px solid var(--docs-accent); + outline-offset: 2px; + } + + .docs-shell { + display: grid; + grid-template-columns: 236px minmax(0, 760px) 176px; + gap: 34px; + max-width: 1240px; + margin: 0 auto; + padding: 30px 28px 84px; + } + + .docs-sidebar, + .docs-toc { + position: sticky; + top: 84px; + align-self: start; + max-height: calc(100dvh - 104px); + overflow: auto; + } + + .docs-sidebar { + padding-right: 4px; + } + + .docs-sidebar-title { + display: flex; + flex-direction: column; + gap: 2px; + margin: 0 0 14px 4px; + } + + .docs-sidebar-title span { + font-size: 13px; + font-weight: 700; + } + + .docs-sidebar-title small { + color: var(--color-text-faint); + font-family: ${mono}; + font-size: 11px; + } + + .docs-section-tabs { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 4px; + margin: 0 0 20px; + padding: 3px; + border: 1px solid var(--color-border); + border-radius: 8px; + background: var(--color-bg-subtle); + } + + .docs-section-tabs a { + display: flex; + min-height: 28px; + align-items: center; + justify-content: center; + border-radius: 6px; + color: var(--color-text-muted); + text-decoration: none; + font-size: 12px; + } + + .docs-section-tabs a.active { + color: var(--color-text); + background: var(--color-bg-elevated); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03); + } + + .docs-sidebar-group { + display: flex; + flex-direction: column; + gap: 2px; + margin-bottom: 20px; + } + + .docs-sidebar-group > span, + .docs-toc > span, + .docs-toc-empty, + .docs-copy { + font-family: ${mono}; + font-size: 11px; + letter-spacing: 0; + } + + .docs-sidebar-group > span, + .docs-toc > span, + .docs-toc-empty { + color: var(--color-text-faint); + } + + .docs-sidebar-group > span { + margin: 0 0 7px 4px; + text-transform: uppercase; + } + + .docs-sidebar a, + .docs-toc a { + color: var(--color-text-muted); + text-decoration: none; + font-size: 13px; + line-height: 1.45; + } + + .docs-sidebar a { + display: flex; + align-items: center; + gap: 9px; + min-height: 30px; + padding: 0 6px; + border-radius: 6px; + } + + .docs-sidebar a span { + color: var(--color-text-faint); + line-height: 0; + } + + .docs-sidebar a:hover { + color: var(--color-text); + background: var(--color-bg-subtle); + } + + .docs-sidebar a.active { + color: var(--color-text); + background: color-mix(in srgb, var(--color-bg-subtle) 82%, var(--docs-accent) 8%); + font-weight: 700; + } + + .docs-sidebar a.active span { + color: var(--color-text); + } + + .docs-main { + min-width: 0; + } + + .docs-breadcrumbs { + display: flex; + align-items: center; + gap: 7px; + margin: 2px 0 16px; + color: var(--color-text-faint); + font-size: 13px; + } + + .docs-breadcrumbs a { + color: inherit; + text-decoration: none; + } + + .docs-breadcrumbs a:hover { + color: var(--color-text); + } + + .docs-hero { + padding: 0 0 24px; + border-bottom: 1px solid var(--color-border); + margin-bottom: 30px; + } + + .docs-hero h1 { + margin: 0; + font-family: ${DOCS_SERIF}; + font-size: 40px; + line-height: 1.08; + font-weight: 700; + letter-spacing: -0.005em; + color: var(--color-text); + } + + .docs-hero p { + max-width: 680px; + margin: 12px 0 0; + font-family: ${DOCS_SERIF}; + color: var(--color-text-muted); + font-size: 17px; + line-height: 1.55; + } + + .docs-markdown { + color: var(--color-text); + font-family: ${DOCS_SERIF}; + } + + .docs-markdown > *:first-child { + margin-top: 0; + } + + .docs-markdown p, + .docs-markdown li, + .docs-markdown td { + color: var(--color-text-muted); + font-family: ${DOCS_SERIF}; + font-size: 16px; + line-height: 1.7; + font-feature-settings: "kern", "liga", "onum"; + } + + .docs-markdown p { + margin: 0 0 16px; + } + + .docs-markdown h2 { + margin: 36px 0 12px; + padding-top: 6px; + font-family: ${DOCS_SERIF}; + font-size: 24px; + line-height: 1.2; + font-weight: 700; + letter-spacing: 0; + color: var(--color-text); + scroll-margin-top: 84px; + } + + .docs-markdown h3 { + margin: 26px 0 10px; + font-family: ${DOCS_SERIF}; + font-size: 18px; + line-height: 1.28; + font-weight: 700; + letter-spacing: 0; + color: var(--color-text); + } + + .docs-markdown strong { + font-weight: 700; + color: var(--color-text); + } + + .docs-markdown em { + font-style: normal; + color: var(--color-text); + font-weight: 700; + } + + .docs-markdown ul, + .docs-markdown ol { + margin: 0 0 18px; + padding-left: 20px; + } + + .docs-markdown a { + display: inline-flex; + gap: 5px; + color: var(--color-text); + text-decoration: underline; + text-decoration-color: var(--color-text-faint); + text-underline-offset: 3px; + } + + .docs-ghstars { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; + margin: 2px 0 26px; + } + + .docs-ghstars a { + display: inline-flex; + align-items: center; + gap: 7px; + height: 30px; + padding: 0 13px; + border: 1px solid var(--color-border); + border-radius: 999px; + background: var(--color-bg-elevated); + color: var(--color-text-muted); + text-decoration: none; + font-family: ${mono}; + font-size: 12px; + transition: border-color 120ms ease, color 120ms ease, background 120ms ease; + } + + .docs-ghstars a:hover { + color: var(--color-text); + border-color: color-mix(in srgb, var(--docs-accent) 44%, var(--color-border)); + } + + .docs-ghstars-primary { + color: var(--color-text) !important; + font-weight: 500; + } + + .docs-ghstars-primary em { + font-style: normal; + font-weight: 700; + padding-left: 8px; + border-left: 1px solid var(--color-border); + color: var(--docs-accent); + } + + .docs-card-grid { + display: grid; + grid-template-columns: repeat(var(--docs-card-cols, 2), minmax(0, 1fr)); + gap: 10px; + margin: 18px 0 26px; + } + + .docs-card { + position: relative; + display: grid !important; + grid-template-columns: minmax(0, 1fr) 14px; + gap: 10px; + align-items: start !important; + min-height: 96px; + padding: 15px; + border: 1px solid var(--color-border); + border-radius: 8px; + background: var(--color-bg-elevated); + color: var(--color-text) !important; + text-decoration: none !important; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.02); + } + + .docs-card:hover { + border-color: color-mix(in srgb, var(--docs-accent) 34%, var(--color-border)); + background: var(--color-bg-subtle); + } + + .docs-card-horizontal { + min-height: 78px; + } + + .docs-card-icon { + display: none; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: 1px solid var(--color-border); + border-radius: 8px; + color: var(--color-text); + background: var(--color-bg); + } + + .docs-card-copy { + display: flex; + flex-direction: column; + gap: 7px; + min-width: 0; + } + + .docs-card-copy strong { + font-size: 13.5px; + line-height: 1.25; + font-weight: 700; + } + + .docs-card-copy small { + color: var(--color-text-muted); + font-size: 12.75px; + line-height: 1.55; + } + + .docs-code-wrap { + position: relative; + margin: 16px 0 22px; + overflow: hidden; + border: 1px solid var(--color-border); + border-radius: 8px; + background: #11150f; + } + + .docs-code-wrap pre { + margin: 0; + padding: 18px 16px; + overflow: auto; + font-family: ${mono}; + font-size: 12px; + line-height: 1.72; + color: #eef4ee; + } + + .docs-copy { + position: absolute; + top: 8px; + right: 8px; + gap: 6px; + min-height: 25px; + padding: 0 8px; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 6px; + background: rgba(255, 255, 255, 0.06); + color: rgba(238, 244, 238, 0.78); + cursor: pointer; + } + + .docs-inline-code { + font-family: ${mono}; + font-size: 12px; + border: 1px solid var(--color-border); + background: var(--color-bg-subtle); + border-radius: 5px; + color: var(--color-text); + padding: 1px 5px; + } + + .docs-table-wrap { + overflow: auto; + border: 1px solid var(--color-border); + border-radius: 8px; + margin: 16px 0 22px; + } + + .docs-table-wrap table { + width: 100%; + border-collapse: collapse; + min-width: 560px; + } + + .docs-table-wrap th, + .docs-table-wrap td { + padding: 10px 13px; + border-bottom: 1px solid var(--color-border); + text-align: left; + vertical-align: top; + } + + .docs-table-wrap th { + font-family: ${mono}; + font-size: 11px; + color: var(--color-text-faint); + background: var(--color-bg-subtle); + } + + .docs-callout { + margin: 18px 0; + padding: 14px 16px; + border: 1px solid rgba(164, 120, 48, 0.28); + border-left: 3px solid rgba(164, 120, 48, 0.64); + border-radius: 7px; + background: color-mix(in srgb, var(--color-bg-subtle) 74%, rgba(164, 120, 48, 0.12)); + } + + .docs-callout p { + margin: 0; + color: var(--color-text); + } + + .docs-callout .docs-markdown p { + margin: 0; + } + + .docs-step-list { + display: flex; + flex-direction: column; + gap: 10px; + margin: 18px 0 28px; + } + + .docs-step { + display: grid; + grid-template-columns: 30px minmax(0, 1fr); + gap: 13px; + padding: 15px; + border: 1px solid var(--color-border); + border-radius: 8px; + background: var(--color-bg-elevated); + } + + .docs-step > span { + width: 27px; + height: 27px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid var(--color-border); + border-radius: 999px; + background: var(--color-bg-subtle); + color: var(--color-text); + font-family: ${mono}; + font-size: 12px; + font-weight: 700; + } + + .docs-step h3 { + margin: 2px 0 8px; + } + + .docs-toc { + display: flex; + flex-direction: column; + gap: 7px; + padding-left: 4px; + } + + .docs-toc > span { + margin-bottom: 4px; + } + + .docs-toc a { + line-height: 1.45; + } + + .docs-agent-links { + display: flex; + flex-direction: column; + gap: 7px; + margin-top: 20px; + padding-top: 14px; + border-top: 1px solid var(--color-border); + } + + .docs-agent-links > span { + font-family: ${mono}; + font-size: 11px; + color: var(--color-text-faint); + } + + .docs-agent-links a { + display: inline-flex; + gap: 5px; + align-items: center; + } + + .docs-pagination { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + margin-top: 48px; + padding-top: 24px; + border-top: 1px solid var(--color-border); + } + + .docs-pagination a { + display: flex; + align-items: center; + gap: 10px; + min-height: 68px; + padding: 13px 14px; + border: 1px solid var(--color-border); + border-radius: 8px; + color: var(--color-text); + text-decoration: none; + background: var(--color-bg); + } + + .docs-pagination a:hover { + background: var(--color-bg-subtle); + } + + .docs-pagination a:last-child { + justify-content: flex-end; + text-align: right; + } + + .docs-pagination small { + display: block; + margin-bottom: 4px; + color: var(--color-text-faint); + font-family: ${mono}; + font-size: 11px; + } + + @media (max-width: 1180px) { + .docs-shell { + grid-template-columns: 224px minmax(0, 1fr); + gap: 30px; + } + .docs-toc { + display: none; + } + } + + @media (max-width: 860px) { + .docs-topbar { + grid-template-columns: minmax(0, 1fr) auto; + padding: 0 16px; + } + + .docs-search { + grid-column: 1 / -1; + order: 2; + display: none; + } + + .docs-topbar nav a:not(.docs-topbar-cta) { + display: none; + } + + .docs-shell { + display: block; + padding: 22px 16px 64px; + } + + .docs-sidebar { + position: static; + border: 1px solid var(--color-border); + border-radius: 10px; + padding: 14px 12px; + margin-bottom: 22px; + max-height: none; + } + + .docs-hero h1 { + font-size: 34px; + } + + .docs-pagination { + grid-template-columns: 1fr; + } + + .docs-card-grid { + grid-template-columns: 1fr; + } + } +` diff --git a/frontend/docs/src/assets/lander/check.svg b/frontend/docs/src/assets/lander/check.svg deleted file mode 100644 index 22de6f2..0000000 --- a/frontend/docs/src/assets/lander/check.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/frontend/docs/src/assets/lander/copy.svg b/frontend/docs/src/assets/lander/copy.svg deleted file mode 100644 index f1baac3..0000000 --- a/frontend/docs/src/assets/lander/copy.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/frontend/docs/src/assets/lander/screenshot-github.png b/frontend/docs/src/assets/lander/screenshot-github.png deleted file mode 100644 index fda74e6..0000000 Binary files a/frontend/docs/src/assets/lander/screenshot-github.png and /dev/null differ diff --git a/frontend/docs/src/assets/lander/screenshot-splash.png b/frontend/docs/src/assets/lander/screenshot-splash.png deleted file mode 100644 index c5e6547..0000000 Binary files a/frontend/docs/src/assets/lander/screenshot-splash.png and /dev/null differ diff --git a/frontend/docs/src/assets/lander/screenshot.png b/frontend/docs/src/assets/lander/screenshot.png deleted file mode 100644 index b9d8bf4..0000000 Binary files a/frontend/docs/src/assets/lander/screenshot.png and /dev/null differ diff --git a/frontend/docs/src/assets/logo-dark.svg b/frontend/docs/src/assets/logo-dark.svg deleted file mode 100644 index a158273..0000000 --- a/frontend/docs/src/assets/logo-dark.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/docs/src/assets/logo-light.svg b/frontend/docs/src/assets/logo-light.svg deleted file mode 100644 index 2a856dc..0000000 --- a/frontend/docs/src/assets/logo-light.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/docs/src/assets/logo-ornate-dark.svg b/frontend/docs/src/assets/logo-ornate-dark.svg deleted file mode 100644 index a158273..0000000 --- a/frontend/docs/src/assets/logo-ornate-dark.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/docs/src/assets/logo-ornate-light.svg b/frontend/docs/src/assets/logo-ornate-light.svg deleted file mode 100644 index 2a856dc..0000000 --- a/frontend/docs/src/assets/logo-ornate-light.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/frontend/docs/src/assets/web/web-homepage-active-session.png b/frontend/docs/src/assets/web/web-homepage-active-session.png deleted file mode 100644 index 5d1d7a7..0000000 Binary files a/frontend/docs/src/assets/web/web-homepage-active-session.png and /dev/null differ diff --git a/frontend/docs/src/assets/web/web-homepage-new-session.png b/frontend/docs/src/assets/web/web-homepage-new-session.png deleted file mode 100644 index 821793b..0000000 Binary files a/frontend/docs/src/assets/web/web-homepage-new-session.png and /dev/null differ diff --git a/frontend/docs/src/assets/web/web-homepage-see-servers.png b/frontend/docs/src/assets/web/web-homepage-see-servers.png deleted file mode 100644 index 4480b9b..0000000 Binary files a/frontend/docs/src/assets/web/web-homepage-see-servers.png and /dev/null differ diff --git a/frontend/docs/src/components/Head.astro b/frontend/docs/src/components/Head.astro deleted file mode 100644 index e27e6db..0000000 --- a/frontend/docs/src/components/Head.astro +++ /dev/null @@ -1,50 +0,0 @@ ---- -import { Base64 } from "js-base64"; -import type { Props } from '@astrojs/starlight/props' -import Default from '@astrojs/starlight/components/Head.astro' -import config from '../../config.mjs' - -const base = import.meta.env.BASE_URL.slice(1) - -const slug = Astro.url.pathname.replace(/^\//, "").replace(/\/$/, ""); -const { - entry: { - data: { title , description }, - }, -} = Astro.locals.starlightRoute; -const isDocs = slug.startsWith("docs") - -let encodedTitle = ''; -let ogImage = `${config.url}/social-share.png`; -let truncatedDesc = ''; - -if (isDocs) { - // Truncate to fit S3's max key size - encodedTitle = encodeURIComponent( - Base64.encode( - // Convert to ASCII - encodeURIComponent( - // Truncate to fit S3's max key size - title.substring(0, 700) - ) - ) - ); - - if (description) { - truncatedDesc = encodeURIComponent(description.substring(0, 400)) - } - - ogImage = `${config.socialCard}/openscience-docs/${encodedTitle}.png?desc=${truncatedDesc}`; -} ---- - -{ slug === "" && ( -{title} | OpenScience: orchestrate AI co-scientists -)} - - - -{ (!slug.startsWith(`${base}/s`)) && ( - - -)} diff --git a/frontend/docs/src/components/Header.astro b/frontend/docs/src/components/Header.astro deleted file mode 100644 index 396200a..0000000 --- a/frontend/docs/src/components/Header.astro +++ /dev/null @@ -1,128 +0,0 @@ ---- -import config from '../../config.mjs'; -import astroConfig from 'virtual:starlight/user-config'; -import { Icon } from '@astrojs/starlight/components'; -import { HeaderLinks } from 'toolbeam-docs-theme/components'; -import Default from 'toolbeam-docs-theme/overrides/Header.astro'; -import SocialIcons from 'virtual:starlight/components/SocialIcons'; -import SiteTitle from '@astrojs/starlight/components/SiteTitle.astro'; - -const path = Astro.url.pathname; - -const links = astroConfig.social || []; -const headerLinks = config.headerLinks; - ---- - -{ path.startsWith("/s") -?
-
- -
-
- { - headerLinks?.map(({ name, url }) => ( - {name} - )) - } -
-
- { - links.length > 0 && ( - - ) - } -
-
- : -} - diff --git a/frontend/docs/src/components/Hero.astro b/frontend/docs/src/components/Hero.astro deleted file mode 100644 index f80f852..0000000 --- a/frontend/docs/src/components/Hero.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -import Default from '@astrojs/starlight/components/Hero.astro'; -import Lander from './Lander.astro'; - -const { slug } = Astro.locals.starlightRoute.entry; ---- - -{ slug === "" - ? - : -} diff --git a/frontend/docs/src/components/Lander.astro b/frontend/docs/src/components/Lander.astro deleted file mode 100644 index e530fc0..0000000 --- a/frontend/docs/src/components/Lander.astro +++ /dev/null @@ -1,702 +0,0 @@ ---- -import { Image } from 'astro:assets'; -import config from "virtual:starlight/user-config"; -import type { Props } from '@astrojs/starlight/props'; - -import CopyIcon from "../assets/lander/copy.svg"; -import CheckIcon from "../assets/lander/check.svg"; -import WorkspaceScreenshot from "../assets/lander/screenshot-splash.png"; -import GithubScreenshot from "../assets/lander/screenshot-github.png"; - -const { data } = Astro.locals.starlightRoute.entry; -const { title = data.title, tagline, image, actions = [] } = data.hero || {}; - -const imageAttrs = { - loading: 'eager' as const, - decoding: 'async' as const, - width: 400, - alt: image?.alt || '', -}; - -const github = config.social.filter(s => s.icon === 'github')[0]; -const discord = config.social.filter(s => s.icon === 'discord')[0]; - -const command = "curl -fsSL" -const protocol = "https://" -const url = "openscience.sh/install" -const bash = "| bash" - -let darkImage: ImageMetadata | undefined; -let lightImage: ImageMetadata | undefined; -let rawHtml: string | undefined; -if (image) { - if ('file' in image) { - darkImage = image.file; - } else if ('dark' in image) { - darkImage = image.dark; - lightImage = image.light; - } else { - rawHtml = image.html; - } -} ---- -
-
- -

Orchestrate AI co-scientists in your browser.

-
- -
- -
- -
-
- -
-
    -
  • Browser workspace: Run the agent in a fast, themeable workspace that opens in your browser.
  • -
  • LSP enabled: Automatically loads the right LSPs for the LLM.
  • -
  • Multi-session: Start multiple agents in parallel on the same project.
  • -
  • Shareable links: Share a link to any session for reference or to debug.
  • -
  • GitHub Copilot: Log in with GitHub to use your Copilot account.
  • -
  • ChatGPT Plus/Pro: Log in with OpenAI to use your ChatGPT Plus or Pro account.
  • -
  • Use any model: Supports 75+ LLM providers through Models.dev, including local models.
  • -
-
- -
-
-

npm

- -
-
-

Bun

- -
-
-

Wizard

- -
-
-

Installer

- -
-
-

Mise

- -
-
- -
-
-
-
openscience workspace in the browser
- - openscience workspace in the browser - -
-
-
-
-
openscience in GitHub
- - openscience in GitHub - -
-
-
- - -
- - - - - - diff --git a/frontend/docs/src/components/Share.tsx b/frontend/docs/src/components/Share.tsx deleted file mode 100644 index c47a845..0000000 --- a/frontend/docs/src/components/Share.tsx +++ /dev/null @@ -1,634 +0,0 @@ -import { For, Show, onMount, Suspense, onCleanup, createMemo, createSignal, SuspenseList, createEffect } from "solid-js" -import { DateTime } from "luxon" -import { createStore, reconcile, unwrap } from "solid-js/store" -import { IconArrowDown } from "./icons" -import { IconOpenScience } from "./icons/custom" -import styles from "./share.module.css" -import type { MessageV2 } from "@synsci/openscience/session/message-v2" -import type { Message } from "@synsci/openscience/session/message" -import type { Session } from "@synsci/openscience/session/index" -import { Part, ProviderIcon } from "./share/part" - -type MessageWithParts = MessageV2.Info & { parts: MessageV2.Part[] } - -type Status = "disconnected" | "connecting" | "connected" | "error" | "reconnecting" - -function scrollToAnchor(id: string) { - const el = document.getElementById(id) - if (!el) return - - el.scrollIntoView({ behavior: "smooth" }) -} - -function getStatusText(status: [Status, string?]): string { - switch (status[0]) { - case "connected": - return "Connected, waiting for messages..." - case "connecting": - return "Connecting..." - case "disconnected": - return "Disconnected" - case "reconnecting": - return "Reconnecting..." - case "error": - return status[1] || "Error" - default: - return "Unknown" - } -} - -export default function Share(props: { id: string; api: string; info: Session.Info }) { - let lastScrollY = 0 - let hasScrolledToAnchor = false - let scrollTimeout: number | undefined - let scrollSentinel: HTMLElement | undefined - let scrollObserver: IntersectionObserver | undefined - - const params = new URLSearchParams(window.location.search) - const debug = params.get("debug") === "true" - - const [showScrollButton, setShowScrollButton] = createSignal(false) - const [isButtonHovered, setIsButtonHovered] = createSignal(false) - const [isNearBottom, setIsNearBottom] = createSignal(false) - - const [store, setStore] = createStore<{ - info?: Session.Info - messages: Record - }>({ - info: { - id: props.id, - title: props.info.title, - version: props.info.version, - time: { - created: props.info.time.created, - updated: props.info.time.updated, - }, - }, - messages: {}, - }) - const messages = createMemo(() => [...Object.values(store.messages)].sort((a, b) => a.id?.localeCompare(b.id))) - const [connectionStatus, setConnectionStatus] = createSignal<[Status, string?]>(["disconnected", "Disconnected"]) - createEffect(() => { - console.log(unwrap(store)) - }) - - onMount(() => { - const apiUrl = props.api - - if (!props.id) { - setConnectionStatus(["error", "id not found"]) - return - } - - if (!apiUrl) { - console.error("API URL not found in environment variables") - setConnectionStatus(["error", "API URL not found"]) - return - } - - let reconnectTimer: number | undefined - let socket: WebSocket | null = null - - // Function to create and set up WebSocket with auto-reconnect - const setupWebSocket = () => { - // Close any existing connection - if (socket) { - socket.close() - } - - setConnectionStatus(["connecting"]) - - // Always use secure WebSocket protocol (wss) - const wsBaseUrl = apiUrl.replace(/^https?:\/\//, "wss://") - const wsUrl = `${wsBaseUrl}/share_poll?id=${props.id}` - console.log("Connecting to WebSocket URL:", wsUrl) - - // Create WebSocket connection - socket = new WebSocket(wsUrl) - - // Handle connection opening - socket.onopen = () => { - setConnectionStatus(["connected"]) - console.log("WebSocket connection established") - } - - // Handle incoming messages - socket.onmessage = (event) => { - console.log("WebSocket message received") - try { - const d = JSON.parse(event.data) - const [root, type, ...splits] = d.key.split("/") - if (root !== "session") return - if (type === "info") { - setStore("info", reconcile(d.content)) - return - } - if (type === "message") { - const [, messageID] = splits - if ("metadata" in d.content) { - d.content = fromV1(d.content) - } - d.content.parts = d.content.parts ?? store.messages[messageID]?.parts ?? [] - setStore("messages", messageID, reconcile(d.content)) - } - if (type === "part") { - setStore("messages", d.content.messageID, "parts", (arr) => { - const index = arr.findIndex((x) => x.id === d.content.id) - if (index === -1) arr.push(d.content) - if (index > -1) arr[index] = d.content - return [...arr] - }) - } - } catch (error) { - console.error("Error parsing WebSocket message:", error) - } - } - - // Handle errors - socket.onerror = (error) => { - console.error("WebSocket error:", error) - setConnectionStatus(["error", "Connection failed"]) - } - - // Handle connection close and reconnection - socket.onclose = (event) => { - console.log(`WebSocket closed: ${event.code} ${event.reason}`) - setConnectionStatus(["reconnecting"]) - - // Try to reconnect after 2 seconds - clearTimeout(reconnectTimer) - reconnectTimer = window.setTimeout(setupWebSocket, 2000) as unknown as number - } - } - - // Initial connection - setupWebSocket() - - // Clean up on component unmount - onCleanup(() => { - console.log("Cleaning up WebSocket connection") - if (socket) { - socket.close() - } - clearTimeout(reconnectTimer) - }) - }) - - function checkScrollNeed() { - const currentScrollY = window.scrollY - const isScrollingDown = currentScrollY > lastScrollY - const scrolled = currentScrollY > 200 // Show after scrolling 200px - - // Only show when scrolling down, scrolled enough, and not near bottom - const shouldShow = isScrollingDown && scrolled && !isNearBottom() - - // Update last scroll position - lastScrollY = currentScrollY - - if (shouldShow) { - setShowScrollButton(true) - // Clear existing timeout - if (scrollTimeout) { - clearTimeout(scrollTimeout) - } - // Hide button after 3 seconds of no scrolling (unless hovered) - scrollTimeout = window.setTimeout(() => { - if (!isButtonHovered()) { - setShowScrollButton(false) - } - }, 1500) - } else if (!isButtonHovered()) { - // Only hide if not hovered (to prevent disappearing while user is about to click) - setShowScrollButton(false) - if (scrollTimeout) { - clearTimeout(scrollTimeout) - } - } - } - - onMount(() => { - lastScrollY = window.scrollY // Initialize scroll position - - // Create sentinel element - const sentinel = document.createElement("div") - sentinel.style.height = "1px" - sentinel.style.position = "absolute" - sentinel.style.bottom = "100px" - sentinel.style.width = "100%" - sentinel.style.pointerEvents = "none" - document.body.appendChild(sentinel) - - // Create intersection observer - const observer = new IntersectionObserver((entries) => { - setIsNearBottom(entries[0].isIntersecting) - }) - observer.observe(sentinel) - - // Store references for cleanup - scrollSentinel = sentinel - scrollObserver = observer - - checkScrollNeed() - window.addEventListener("scroll", checkScrollNeed) - window.addEventListener("resize", checkScrollNeed) - }) - - onCleanup(() => { - window.removeEventListener("scroll", checkScrollNeed) - window.removeEventListener("resize", checkScrollNeed) - - // Clean up observer and sentinel - if (scrollObserver) { - scrollObserver.disconnect() - } - if (scrollSentinel) { - document.body.removeChild(scrollSentinel) - } - - if (scrollTimeout) { - clearTimeout(scrollTimeout) - } - }) - - const data = createMemo(() => { - const result = { - rootDir: undefined as string | undefined, - created: undefined as number | undefined, - completed: undefined as number | undefined, - messages: [] as MessageWithParts[], - models: {} as Record, - cost: 0, - tokens: { - input: 0, - output: 0, - reasoning: 0, - }, - } - - if (!store.info) return result - - result.created = store.info.time.created - - const msgs = messages() - for (let i = 0; i < msgs.length; i++) { - const msg = msgs[i] - - result.messages.push(msg) - - if (msg.role === "assistant") { - result.cost += msg.cost - result.tokens.input += msg.tokens.input - result.tokens.output += msg.tokens.output - result.tokens.reasoning += msg.tokens.reasoning - - result.models[`${msg.providerID} ${msg.modelID}`] = [msg.providerID, msg.modelID] - - if (msg.path.root) { - result.rootDir = msg.path.root - } - - if (msg.time.completed) { - result.completed = msg.time.completed - } - } - } - return result - }) - - return ( - -
-
-

{store.info?.title}

-
-
    -
  • -
    - -
    - - v{store.info?.version} - -
  • - {Object.values(data().models).length > 0 ? ( - - {([provider, model]) => ( -
  • -
    - -
    - {model} -
  • - )} -
    - ) : ( -
  • - Models - -
  • - )} -
-
- {DateTime.fromMillis(data().created || 0).toLocaleString(DateTime.DATETIME_MED)} -
-
-
- -
- 0} fallback={

Waiting for messages...

}> -
- - - {(msg, msgIndex) => { - const filteredParts = createMemo(() => - msg.parts.filter((x, index) => { - if (x.type === "step-start" && index > 0) return false - if (x.type === "snapshot") return false - if (x.type === "patch") return false - if (x.type === "step-finish") return false - if (x.type === "text" && x.synthetic === true) return false - if (x.type === "tool" && x.tool === "todoread") return false - if (x.type === "text" && !x.text) return false - if (x.type === "tool" && (x.state.status === "pending" || x.state.status === "running")) - return false - return true - }), - ) - - return ( - - - {(part, partIndex) => { - const last = createMemo( - () => - data().messages.length === msgIndex() + 1 && filteredParts().length === partIndex() + 1, - ) - - onMount(() => { - const hash = window.location.hash.slice(1) - // Wait till all parts are loaded - if ( - hash !== "" && - !hasScrolledToAnchor && - filteredParts().length === partIndex() + 1 && - data().messages.length === msgIndex() + 1 - ) { - hasScrolledToAnchor = true - scrollToAnchor(hash) - } - }) - - return - }} - - - ) - }} - - -
-
- -
-
-

{getStatusText(connectionStatus())}

-
    -
  • - Cost - {data().cost !== undefined ? ( - ${data().cost.toFixed(2)} - ) : ( - - )} -
  • -
  • - Input Tokens - {data().tokens.input ? {data().tokens.input} : } -
  • -
  • - Output Tokens - {data().tokens.output ? ( - {data().tokens.output} - ) : ( - - )} -
  • -
  • - Reasoning Tokens - {data().tokens.reasoning ? ( - {data().tokens.reasoning} - ) : ( - - )} -
  • -
-
-
-
-
-
- - -
-
- 0} fallback={

Waiting for messages...

}> -
    - - {(msg) => ( -
  • -
    - Key: {msg.id} -
    -
    {JSON.stringify(msg, null, 2)}
    -
  • - )} -
    -
-
-
-
-
- - - - -
-
- ) -} - -export function fromV1(v1: Message.Info): MessageWithParts { - if (v1.role === "assistant") { - return { - id: v1.id, - sessionID: v1.metadata.sessionID, - role: "assistant", - time: { - created: v1.metadata.time.created, - completed: v1.metadata.time.completed, - }, - cost: v1.metadata.assistant!.cost, - path: v1.metadata.assistant!.path, - summary: v1.metadata.assistant!.summary, - tokens: v1.metadata.assistant!.tokens ?? { - input: 0, - output: 0, - cache: { - read: 0, - write: 0, - }, - reasoning: 0, - }, - modelID: v1.metadata.assistant!.modelID, - providerID: v1.metadata.assistant!.providerID, - mode: "build", - system: v1.metadata.assistant!.system, - error: v1.metadata.error, - parts: v1.parts.flatMap((part, index): MessageV2.Part[] => { - const base = { - id: index.toString(), - messageID: v1.id, - sessionID: v1.metadata.sessionID, - } - if (part.type === "text") { - return [ - { - ...base, - type: "text", - text: part.text, - }, - ] - } - if (part.type === "step-start") { - return [ - { - ...base, - type: "step-start", - }, - ] - } - if (part.type === "tool-invocation") { - return [ - { - ...base, - type: "tool", - callID: part.toolInvocation.toolCallId, - tool: part.toolInvocation.toolName, - state: (() => { - if (part.toolInvocation.state === "partial-call") { - return { - status: "pending", - } - } - - const { title, time, ...metadata } = v1.metadata.tool[part.toolInvocation.toolCallId] - if (part.toolInvocation.state === "call") { - return { - status: "running", - input: part.toolInvocation.args, - time: { - start: time.start, - }, - } - } - - if (part.toolInvocation.state === "result") { - return { - status: "completed", - input: part.toolInvocation.args, - output: part.toolInvocation.result, - title, - time, - metadata, - } - } - throw new Error("unknown tool invocation state") - })(), - }, - ] - } - return [] - }), - } - } - - if (v1.role === "user") { - return { - id: v1.id, - sessionID: v1.metadata.sessionID, - role: "user", - time: { - created: v1.metadata.time.created, - }, - parts: v1.parts.flatMap((part, index): MessageV2.Part[] => { - const base = { - id: index.toString(), - messageID: v1.id, - sessionID: v1.metadata.sessionID, - } - if (part.type === "text") { - return [ - { - ...base, - type: "text", - text: part.text, - }, - ] - } - if (part.type === "file") { - return [ - { - ...base, - type: "file", - mime: part.mediaType, - filename: part.filename, - url: part.url, - }, - ] - } - return [] - }), - } - } - - throw new Error("unknown message type") -} diff --git a/frontend/docs/src/components/SiteTitle.astro b/frontend/docs/src/components/SiteTitle.astro deleted file mode 100644 index 28a30cb..0000000 --- a/frontend/docs/src/components/SiteTitle.astro +++ /dev/null @@ -1,59 +0,0 @@ ---- -import { logos } from 'virtual:starlight/user-images'; -import config from 'virtual:starlight/user-config'; -const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute; ---- - - - { - config.logo && logos.dark && ( - <> - {config.logo.alt} - {/* Show light alternate if a user configure both light and dark logos. */} - {!('src' in config.logo) && ( - {config.logo.alt} - )} - - ) - } - - {siteTitle} - - - - diff --git a/frontend/docs/src/components/icons/custom.tsx b/frontend/docs/src/components/icons/custom.tsx deleted file mode 100644 index 37dc7bd..0000000 --- a/frontend/docs/src/components/icons/custom.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { type JSX } from "solid-js" - -// https://icones.js.org/collection/ri?s=openai&icon=ri:openai-fill -export function IconOpenAI(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -// https://icones.js.org/collection/ri?s=anthropic&icon=ri:anthropic-fill -export function IconAnthropic(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -// https://icones.js.org/collection/ri?s=gemini&icon=ri:gemini-fill -export function IconGemini(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -export function IconOpenScience(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} - -// https://icones.js.org/collection/ri?s=meta&icon=ri:meta-fill -export function IconMeta(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -// https://icones.js.org/collection/ri?s=robot&icon=ri:robot-2-line -export function IconRobot(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -// https://icones.js.org/collection/ri?s=brain&icon=ri:brain-2-line -export function IconBrain(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} diff --git a/frontend/docs/src/components/icons/index.tsx b/frontend/docs/src/components/icons/index.tsx deleted file mode 100644 index 6244561..0000000 --- a/frontend/docs/src/components/icons/index.tsx +++ /dev/null @@ -1,4454 +0,0 @@ -import { type JSX } from "solid-js" -// heroicons - -export function IconAcademicCap(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconAdjustmentsHorizontal(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconAdjustmentsVertical(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArchiveBoxArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArchiveBoxXMark(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArchiveBox(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownOnSquareStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownOnSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDownTray(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLeftCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLeftOnRectangle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLongDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLongLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLongRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowLongUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowPathRoundedSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowPath(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowRightCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowRightOnRectangle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowSmallDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowSmallLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowSmallRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowSmallUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowTopRightOnSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowTrendingDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowTrendingUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpOnSquareStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpOnSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUpTray(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUturnDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUturnLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUturnRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowUturnUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowsPointingIn(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowsPointingOut(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowsRightLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconArrowsUpDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconAtSymbol(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBackspace(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBackward(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconBanknotes(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars2(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars3BottomLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars3BottomRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars3CenterLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars3(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBars4(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBarsArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBarsArrowUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBattery0(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBattery100(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBattery50(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBeaker(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBellAlert(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBellSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBellSnooze(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBell(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBoltSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBolt(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -export function IconBoltSolid(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBookOpen(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBookmarkSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBookmarkSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBookmark(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBriefcase(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconBugAnt(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBuildingLibrary(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBuildingOffice2(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBuildingOffice(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconBuildingStorefront(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCake(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCalculator(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCalendarDays(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCalendar(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCamera(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconChartBarSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChartBar(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconChartPie(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconChatBubbleBottomCenterText(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleBottomCenter(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleLeftEllipsis(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleLeftRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleOvalLeftEllipsis(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChatBubbleOvalLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCheckBadge(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCheckCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCheck(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronDoubleDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronDoubleLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronDoubleRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronDoubleUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronUpDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconChevronUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCircleStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconClipboardDocumentCheck(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconClipboardDocumentList(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconClipboardDocument(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconClipboard(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconClock(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCloudArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCloudArrowUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCloud(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCodeBracketSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCodeBracket(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCog6Tooth(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconCog8Tooth(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconCog(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCommandLine(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconComputerDesktop(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCpuChip(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCreditCard(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCubeTransparent(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCube(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyBangladeshi(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyDollar(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyEuro(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyPound(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyRupee(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCurrencyYen(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCursorArrowRays(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconCursorArrowRipple(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDevicePhoneMobile(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDeviceTablet(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentArrowUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentChartBar(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentCheck(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentDuplicate(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentMagnifyingGlass(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentMinus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocumentText(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconDocument(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEllipsisHorizontalCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEllipsisHorizontal(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconEllipsisVertical(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconEnvelopeOpen(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEnvelope(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEnvelopeSolid(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconExclamationCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconExclamationTriangle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEyeDropper(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEyeSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconEye(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconFaceFrown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFaceSmile(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFilm(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFingerPrint(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFire(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconFlag(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFolderArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFolderMinus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFolderOpen(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFolderPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconFolder(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconForward(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconFunnel(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGif(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGiftTop(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGift(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGlobeAlt(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGlobeAmericas(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGlobeAsiaAustralia(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconGlobeEuropeAfrica(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHandRaised(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHandThumbDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHandThumbUp(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHashtag(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHeart(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHomeModern(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconHome(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconIdentification(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconInboxArrowDown(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconInboxStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconInbox(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconInformationCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconKey(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLanguage(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLifebuoy(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLightBulb(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLink(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconListBullet(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLockClosed(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLockOpen(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMagnifyingGlassCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMagnifyingGlassMinus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMagnifyingGlassPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMagnifyingGlass(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMapPin(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconMap(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMegaphone(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMicrophone(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMinusCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMinusSmall(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMinus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMoon(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMusicalNote(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconNewspaper(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconNoSymbol(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPaintBrush(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPaperAirplane(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPaperClip(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPauseCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPause(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPencilSquare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPencil(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPhoneArrowDownLeft(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPhoneArrowUpRight(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPhoneXMark(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPhone(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPhoto(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPlayCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconPlayPause(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPlay(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPlusCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPlusSmall(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPower(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPresentationChartBar(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPresentationChartLine(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPrinter(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconPuzzlePiece(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconQrCode(props: JSX.SvgSVGAttributes) { - return ( - - - - - - - - - - - - - - ) -} -export function IconQuestionMarkCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconQueueList(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconRadio(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconReceiptPercent(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconReceiptRefund(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconRectangleGroup(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconRectangleStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconRocketLaunch(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconRss(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconScale(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconScissors(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconServerStack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconServer(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconShare(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconShieldCheck(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconShieldExclamation(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconShoppingBag(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconShoppingCart(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSignalSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSignal(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSparkles(props: JSX.SvgSVGAttributes) { - return ( - - - - - - ) -} -export function IconSpeakerWave(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSpeakerXMark(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSquare2Stack(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSquare3Stack3d(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSquares2x2(props: JSX.SvgSVGAttributes) { - return ( - - - - - - - ) -} -export function IconSquaresPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconStar(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconStopCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconStop(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSun(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSwatch(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTableCells(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTag(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconTicket(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTrash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTrophy(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTruck(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconTv(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconUserCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconUserGroup(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconUserMinus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconUserPlus(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconUser(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconUsers(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconVariable(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconVideoCameraSlash(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconVideoCamera(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconViewColumns(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconViewfinderCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconWallet(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconWifi(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconWindow(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconWrenchScrewdriver(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconWrench(props: JSX.SvgSVGAttributes) { - return ( - - - - - ) -} -export function IconXCircle(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconXMark(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -// index -export function IconCommand(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconLetter(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconMultiSelect(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} -export function IconSettings(props: JSX.SvgSVGAttributes) { - return ( - - - - - - - - - - - - ) -} -export function IconSingleSelect(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} diff --git a/frontend/docs/src/components/share.module.css b/frontend/docs/src/components/share.module.css deleted file mode 100644 index 9930e6b..0000000 --- a/frontend/docs/src/components/share.module.css +++ /dev/null @@ -1,832 +0,0 @@ -.root { - display: flex; - flex-direction: column; - gap: 2.5rem; - line-height: 1; - padding: 1.5rem; - - @media (max-width: 30rem) { - padding: 1rem; - gap: 2rem; - } - - --sm-tool-width: 28rem; - --md-tool-width: 40rem; - --lg-tool-width: 56rem; - - --term-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E"); - - [data-component="header"] { - display: flex; - flex-direction: column; - gap: 1rem; - - @media (max-width: 30rem) { - gap: 1rem; - } - } - - [data-component="header-title"] { - font-size: 2.75rem; - font-weight: 500; - line-height: 1.2; - letter-spacing: -0.05em; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - - @media (max-width: 30rem) { - font-size: 1.75rem; - line-height: 1.25; - -webkit-line-clamp: 3; - } - } - - [data-component="header-details"] { - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - [data-component="header-stats"] { - list-style-type: none; - padding: 0; - margin: 0; - display: flex; - gap: 0.5rem 0.875rem; - flex-wrap: wrap; - max-width: var(--lg-tool-width); - - [data-slot="item"] { - display: flex; - align-items: center; - gap: 0.3125rem; - font-size: 0.875rem; - - span[data-placeholder] { - color: var(--sl-color-text-dimmed); - } - } - - [data-slot="icon"] { - flex: 0 0 auto; - color: var(--sl-color-text-dimmed); - opacity: 0.85; - - svg { - display: block; - } - } - - [data-slot="model"] { - color: var(--sl-color-text); - } - } - - [data-component="header-time"] { - color: var(--sl-color-text-dimmed); - font-size: 0.875rem; - } - - [data-component="text-button"] { - cursor: pointer; - appearance: none; - background-color: transparent; - border: none; - padding: 0; - color: var(--sl-color-text-secondary); - - &:hover { - color: var(--sl-color-text); - } - - &[data-element-button-more] { - display: flex; - align-items: center; - gap: 0.125rem; - - span[data-button-icon] { - line-height: 1; - opacity: 0.85; - - svg { - display: block; - } - } - } - } -} - -.parts { - display: flex; - flex-direction: column; - gap: 0.625rem; - - [data-section="part"] { - display: flex; - gap: 0.625rem; - - & > [data-section="decoration"] { - flex: 0 0 auto; - display: flex; - flex-direction: column; - gap: 0.625rem; - align-items: center; - justify-content: flex-start; - - [data-element-anchor] { - position: relative; - - a:first-child { - display: block; - flex: 0 0 auto; - width: 18px; - opacity: 0.65; - - svg { - color: var(--sl-color-text-secondary); - display: block; - - &:nth-child(3) { - color: var(--sl-color-green-high); - } - } - - svg:nth-child(2), - svg:nth-child(3) { - display: none; - } - - &:hover { - svg:nth-child(1) { - display: none; - } - - svg:nth-child(2) { - display: block; - } - } - } - - [data-element-tooltip] { - position: absolute; - top: 50%; - left: calc(100% + 12px); - transform: translate(0, -50%); - line-height: 1.1; - padding: 0.375em 0.5em calc(0.375em + 2px); - background: var(--sl-color-white); - color: var(--sl-color-text-invert); - font-size: 0.6875rem; - border-radius: 7px; - white-space: nowrap; - - z-index: 1; - opacity: 0; - visibility: hidden; - - &::after { - content: ""; - position: absolute; - top: 50%; - left: -15px; - transform: translateY(-50%); - border: 8px solid transparent; - border-right-color: var(--sl-color-white); - } - } - - &[data-status="copied"] { - [data-element-tooltip] { - opacity: 1; - visibility: visible; - } - - a, - a:hover { - svg:nth-child(1), - svg:nth-child(2) { - display: none; - } - - svg:nth-child(3) { - display: block; - } - } - } - } - - div:last-child { - width: 3px; - height: 100%; - border-radius: 1px; - background-color: var(--sl-color-hairline); - } - } - - & > [data-section="content"] { - flex: 1 1 auto; - min-width: 0; - padding: 0 0 0.375rem; - display: flex; - flex-direction: column; - gap: 1rem; - - [data-part-tool-body] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.375rem; - } - - [data-part-title] { - line-height: 18px; - font-size: 0.875rem; - color: var(--sl-color-text-secondary); - max-width: var(--md-tool-width); - - display: flex; - align-items: flex-start; - gap: 0.375rem; - - span[data-element-label] { - color: var(--sl-color-text-secondary); - } - - b { - color: var(--sl-color-text); - word-break: break-all; - font-weight: 500; - } - } - - span[data-part-footer] { - align-self: flex-start; - font-size: 0.75rem; - color: var(--sl-color-text-dimmed); - } - - span[data-part-model] { - line-height: 1.5; - } - - [data-part-tool-args] { - display: inline-grid; - align-items: center; - grid-template-columns: max-content max-content minmax(0, 1fr); - max-width: var(--md-tool-width); - gap: 0.25rem 0.375rem; - - & > div:nth-child(3n + 1) { - width: 8px; - height: 2px; - border-radius: 1px; - background: var(--sl-color-divider); - } - - & > div:nth-child(3n + 2), - & > div:nth-child(3n + 3) { - font-size: 0.75rem; - line-height: 1.5; - } - - & > div:nth-child(3n + 3) { - padding-left: 0.125rem; - word-break: break-word; - color: var(--sl-color-text-secondary); - } - } - - [data-part-tool-result] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.5rem; - - button { - font-size: 0.75rem; - } - } - - [data-part-tool-edit] { - width: 100%; - max-width: var(--lg-tool-width); - } - } - } - - /* Part types */ - [data-part-type="user-text"], - [data-part-type="ai-text"], - [data-part-type="ai-model"], - [data-part-type="system-text"], - [data-part-type="fallback"] { - & > [data-section="content"] { - padding-bottom: 1rem; - } - } - - [data-part-type="tool-list"], - [data-part-type="tool-glob"], - [data-part-type="tool-read"], - [data-part-type="tool-edit"], - [data-part-type="tool-write"], - [data-part-type="tool-fetch"] { - & > [data-section="content"] > [data-part-tool-body] { - gap: 0.5rem; - } - } - - [data-part-type="tool-grep"] { - &:not(:has([data-part-tool-args])) > [data-section="content"] > [data-part-tool-body] { - gap: 0.5rem; - } - } - - [data-part-type="tool-write"], - [data-part-type="tool-read"], - [data-part-type="tool-fetch"] { - [data-part-tool-result] { - [data-part-tool-code] { - max-width: var(--md-tool-width); - border: 1px solid var(--sl-color-divider); - background-color: var(--sl-color-bg-surface); - border-radius: 0.25rem; - padding: 0.5rem calc(0.5rem + 3px); - - pre { - line-height: 1.6; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - } - } - } - } - - [data-part-type="summary"] { - & > [data-section="decoration"] { - span:first-child { - flex: 0 0 auto; - display: block; - margin: 2px; - width: 14px; - height: 14px; - border-radius: 50%; - background-color: var(--sl-color-divider); - - &[data-status="connected"] { - background-color: var(--sl-color-green); - } - - &[data-status="connecting"] { - background-color: var(--sl-color-orange); - } - - &[data-status="disconnected"] { - background-color: var(--sl-color-divider); - } - - &[data-status="reconnecting"] { - background-color: var(--sl-color-orange); - } - - &[data-status="error"] { - background-color: var(--sl-color-red); - } - } - } - - & > [data-section="content"] { - display: flex; - flex-direction: column; - gap: 0.5rem; - - p[data-section="copy"] { - display: block; - line-height: 18px; - font-size: 0.875rem; - color: var(--sl-color-text-dimmed); - } - - [data-section="stats"] { - list-style-type: none; - padding: 0; - margin: 0; - display: flex; - gap: 0.5rem 0.875rem; - flex-wrap: wrap; - - li { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.75rem; - color: var(--sl-color-text-secondary); - - span[data-placeholder] { - color: var(--sl-color-text-dimmed); - } - } - } - } - } -} - -.message-text { - background-color: var(--sl-color-bg-surface); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - align-self: flex-start; - max-width: var(--md-tool-width); - - &[data-size="sm"] { - pre { - font-size: 0.75rem; - } - } - - &[data-color="dimmed"] { - pre { - color: var(--sl-color-text-dimmed); - } - } - - pre { - line-height: 1.5; - font-size: 0.875rem; - white-space: pre-wrap; - overflow-wrap: anywhere; - color: var(--sl-color-text); - } - - button { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } - - &[data-invert="true"] { - background-color: var(--sl-color-blue-high); - - pre { - color: var(--sl-color-text-invert); - } - - button { - opacity: 0.85; - color: var(--sl-color-text-invert); - - &:hover { - opacity: 1; - } - } - } - - &[data-background="none"] { - background-color: transparent; - } - - &[data-background="blue"] { - background-color: var(--sl-color-blue-low); - } - - &[data-expanded="true"] { - pre { - display: block; - } - } - - &[data-expanded="false"] { - pre { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - overflow: hidden; - } - } -} - -.message-error { - background-color: var(--sl-color-bg-surface); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - align-self: flex-start; - max-width: var(--md-tool-width); - - [data-section="content"] { - pre { - margin-bottom: 0.5rem; - line-height: 1.5; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - - &:last-child { - margin-bottom: 0; - } - - span { - margin-right: 0.25rem; - - &:last-child { - margin-right: 0; - } - } - - span[data-color="red"] { - color: var(--sl-color-red); - } - - span[data-color="dimmed"] { - color: var(--sl-color-text-dimmed); - } - - span[data-marker="label"] { - text-transform: uppercase; - letter-spacing: -0.5px; - } - - span[data-separator] { - margin-right: 0.375rem; - } - } - } - - &[data-expanded="true"] { - [data-section="content"] { - display: block; - } - } - - &[data-expanded="false"] { - [data-section="content"] { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 7; - overflow: hidden; - } - } - - button { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } -} - -.message-terminal { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.5rem; - width: 100%; - max-width: var(--sm-tool-width); - - & > [data-section="body"] { - width: 100%; - border: 1px solid var(--sl-color-divider); - border-radius: 0.25rem; - - [data-section="header"] { - position: relative; - border-bottom: 1px solid var(--sl-color-divider); - width: 100%; - height: 1.625rem; - text-align: center; - padding: 0 3.25rem; - - & > span { - max-width: min(100%, 140ch); - display: inline-block; - white-space: nowrap; - overflow: hidden; - line-height: 1.625rem; - font-size: 0.75rem; - text-overflow: ellipsis; - color: var(--sl-color-text-dimmed); - } - - &::before { - content: ""; - position: absolute; - pointer-events: none; - top: 8px; - left: 10px; - width: 2rem; - height: 0.5rem; - line-height: 0; - background-color: var(--sl-color-hairline); - mask-image: var(--term-icon); - mask-repeat: no-repeat; - } - } - } - - [data-section="content"] { - padding: 0.5rem calc(0.5rem + 3px); - - pre { - --shiki-dark-bg: var(--sl-color-bg) !important; - background-color: var(--sl-color-bg) !important; - line-height: 1.6; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - } - } - - [data-section="error"] { - pre { - color: var(--sl-color-red) !important; - --shiki-dark: var(--sl-color-red) !important; - } - } - - &[data-expanded="true"] { - pre { - display: block; - } - } - - &[data-expanded="false"] { - pre { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 7; - overflow: hidden; - } - } - - button { - flex: 0 0 auto; - padding-left: 1px; - font-size: 0.75rem; - } -} - -.message-markdown { - border: 1px solid var(--sl-color-blue-high); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - align-self: flex-start; - max-width: var(--md-tool-width); - - button { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } - - &[data-highlight="true"] { - background-color: var(--sl-color-blue-low); - } - - &[data-expanded="true"] { - [data-element-markdown] { - display: block; - } - } - - &[data-expanded="false"] { - [data-element-markdown] { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - overflow: hidden; - } - } -} - -.diff-code-block { - pre { - line-height: 1.25; - font-size: 0.75rem; - } -} - -.todos { - list-style-type: none; - padding: 0; - margin: 0; - width: 100%; - max-width: var(--sm-tool-width); - border: 1px solid var(--sl-color-divider); - border-radius: 0.25rem; - - li { - margin: 0; - position: relative; - padding-left: 1.5rem; - font-size: 0.75rem; - padding: 0.375rem 0.625rem 0.375rem 1.75rem; - border-bottom: 1px solid var(--sl-color-divider); - line-height: 1.5; - word-break: break-word; - - &:last-child { - border-bottom: none; - } - - & > span { - position: absolute; - display: inline-block; - left: 0.5rem; - top: calc(0.5rem + 1px); - width: 0.75rem; - height: 0.75rem; - border: 1px solid var(--sl-color-divider); - border-radius: 0.15rem; - - &::before { - } - } - - &[data-status="pending"] { - color: var(--sl-color-text); - } - - &[data-status="in_progress"] { - color: var(--sl-color-text); - - & > span { - border-color: var(--sl-color-orange); - } - - & > span::before { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: calc(0.75rem - 2px - 4px); - height: calc(0.75rem - 2px - 4px); - box-shadow: inset 1rem 1rem var(--sl-color-orange-low); - } - } - - &[data-status="completed"] { - color: var(--sl-color-text-secondary); - - & > span { - border-color: var(--sl-color-green-low); - } - - & > span::before { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: calc(0.75rem - 2px - 4px); - height: calc(0.75rem - 2px - 4px); - box-shadow: inset 1rem 1rem var(--sl-color-green); - - transform-origin: bottom left; - clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); - } - } - } -} - -.scroll-button { - position: fixed; - bottom: 2rem; - right: 2rem; - width: 2.5rem; - height: 2.5rem; - border-radius: 0.25rem; - border: 1px solid var(--sl-color-divider); - background-color: var(--sl-color-bg-surface); - color: var(--sl-color-text-secondary); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: - all 0.15s ease, - opacity 0.5s ease; - z-index: 100; - appearance: none; - opacity: 1; - - &:active { - transform: translateY(1px); - } - - svg { - display: block; - } -} diff --git a/frontend/docs/src/components/share/common.tsx b/frontend/docs/src/components/share/common.tsx deleted file mode 100644 index cab2dbd..0000000 --- a/frontend/docs/src/components/share/common.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { createSignal, onCleanup, splitProps } from "solid-js" -import type { JSX } from "solid-js/jsx-runtime" -import { IconCheckCircle, IconHashtag } from "../icons" - -interface AnchorProps extends JSX.HTMLAttributes { - id: string -} -export function AnchorIcon(props: AnchorProps) { - const [local, rest] = splitProps(props, ["id", "children"]) - const [copied, setCopied] = createSignal(false) - - return ( - - ) -} - -export function createOverflow() { - const [overflow, setOverflow] = createSignal(false) - return { - get status() { - return overflow() - }, - ref(el: HTMLElement) { - const ro = new ResizeObserver(() => { - if (el.scrollHeight > el.clientHeight + 1) { - setOverflow(true) - } - return - }) - ro.observe(el) - - onCleanup(() => { - ro.disconnect() - }) - }, - } -} - -export function formatDuration(ms: number): string { - const ONE_SECOND = 1000 - const ONE_MINUTE = 60 * ONE_SECOND - - if (ms >= ONE_MINUTE) { - const minutes = Math.floor(ms / ONE_MINUTE) - return minutes === 1 ? `1min` : `${minutes}mins` - } - - if (ms >= ONE_SECOND) { - const seconds = Math.floor(ms / ONE_SECOND) - return `${seconds}s` - } - - return `${ms}ms` -} diff --git a/frontend/docs/src/components/share/content-bash.module.css b/frontend/docs/src/components/share/content-bash.module.css deleted file mode 100644 index 0915282..0000000 --- a/frontend/docs/src/components/share/content-bash.module.css +++ /dev/null @@ -1,85 +0,0 @@ -.root { - display: contents; - - [data-slot="expand-button"] { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } - - [data-slot="body"] { - border: 1px solid var(--sl-color-divider); - border-radius: 0.25rem; - overflow: hidden; - width: 100%; - } - - [data-slot="header"] { - position: relative; - border-bottom: 1px solid var(--sl-color-divider); - width: 100%; - height: 1.625rem; - text-align: center; - padding: 0 3.25rem; - - > span { - max-width: min(100%, 140ch); - display: inline-block; - white-space: nowrap; - overflow: hidden; - line-height: 1.625rem; - font-size: 0.75rem; - text-overflow: ellipsis; - color: var(--sl-color-text-dimmed); - } - - &::before { - content: ""; - position: absolute; - pointer-events: none; - top: 8px; - left: 10px; - width: 2rem; - height: 0.5rem; - line-height: 0; - background-color: var(--sl-color-hairline); - mask-image: var(--term-icon); - mask-repeat: no-repeat; - } - } - - [data-slot="content"] { - display: flex; - flex-direction: column; - padding: 0.5rem calc(0.5rem + 3px); - - pre { - --shiki-dark-bg: var(--sl-color-bg) !important; - background-color: var(--sl-color-bg) !important; - line-height: 1.6; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - margin: 0; - - span { - white-space: break-spaces; - } - } - } - - [data-slot="output"] { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 10; - line-clamp: 10; - overflow: hidden; - } - - &[data-expanded] [data-slot="output"] { - display: block; - -webkit-line-clamp: none; - line-clamp: none; - overflow: visible; - } -} diff --git a/frontend/docs/src/components/share/content-bash.tsx b/frontend/docs/src/components/share/content-bash.tsx deleted file mode 100644 index 5ccd95c..0000000 --- a/frontend/docs/src/components/share/content-bash.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import style from "./content-bash.module.css" -import { createResource, createSignal } from "solid-js" -import { createOverflow } from "./common" -import { codeToHtml } from "shiki" - -interface Props { - command: string - output: string - description?: string - expand?: boolean -} - -export function ContentBash(props: Props) { - const [commandHtml] = createResource( - () => props.command, - async (command) => { - return codeToHtml(command || "", { - lang: "bash", - themes: { - light: "github-light", - dark: "github-dark", - }, - }) - }, - ) - - const [outputHtml] = createResource( - () => props.output, - async (output) => { - return codeToHtml(output || "", { - lang: "console", - themes: { - light: "github-light", - dark: "github-dark", - }, - }) - }, - ) - - const [expanded, setExpanded] = createSignal(false) - const overflow = createOverflow() - - return ( -
-
-
- {props.description} -
-
-
-
-
-
- - {!props.expand && overflow.status && ( - - )} -
- ) -} diff --git a/frontend/docs/src/components/share/content-code.module.css b/frontend/docs/src/components/share/content-code.module.css deleted file mode 100644 index ec159d6..0000000 --- a/frontend/docs/src/components/share/content-code.module.css +++ /dev/null @@ -1,26 +0,0 @@ -.root { - border: 1px solid var(--sl-color-divider); - background-color: var(--sl-color-bg-surface); - border-radius: 0.25rem; - padding: 0.5rem calc(0.5rem + 3px); - - &[data-flush="true"] { - border: none; - background-color: transparent; - padding: 0; - border-radius: 0; - } - - pre { - --shiki-dark-bg: var(--sl-color-bg-surface) !important; - background-color: var(--sl-color-bg-surface) !important; - line-height: 1.6; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - - span { - white-space: break-spaces; - } - } -} diff --git a/frontend/docs/src/components/share/content-code.tsx b/frontend/docs/src/components/share/content-code.tsx deleted file mode 100644 index 2f383b8..0000000 --- a/frontend/docs/src/components/share/content-code.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { codeToHtml, bundledLanguages } from "shiki" -import { createResource, Suspense } from "solid-js" -import { transformerNotationDiff } from "@shikijs/transformers" -import style from "./content-code.module.css" - -interface Props { - code: string - lang?: string - flush?: boolean -} -export function ContentCode(props: Props) { - const [html] = createResource( - () => [props.code, props.lang], - async ([code, lang]) => { - // TODO: For testing delays - // await new Promise((resolve) => setTimeout(resolve, 3000)) - return (await codeToHtml(code || "", { - lang: lang && lang in bundledLanguages ? lang : "text", - themes: { - light: "github-light", - dark: "github-dark", - }, - transformers: [transformerNotationDiff()], - })) as string - }, - ) - return ( - -
- - ) -} diff --git a/frontend/docs/src/components/share/content-diff.module.css b/frontend/docs/src/components/share/content-diff.module.css deleted file mode 100644 index 1dfb077..0000000 --- a/frontend/docs/src/components/share/content-diff.module.css +++ /dev/null @@ -1,153 +0,0 @@ -.root { - display: flex; - flex-direction: column; - border: 1px solid var(--sl-color-divider); - background-color: var(--sl-color-bg-surface); - border-radius: 0.25rem; - - [data-component="desktop"] { - display: block; - } - - [data-component="mobile"] { - display: none; - } - - [data-component="diff-block"] { - display: flex; - flex-direction: column; - } - - [data-component="diff-row"] { - display: grid; - grid-template-columns: 1fr 1fr; - align-items: stretch; - - &:first-child { - [data-slot="before"], - [data-slot="after"] { - padding-top: 0.25rem; - } - } - - &:last-child { - [data-slot="before"], - [data-slot="after"] { - padding-bottom: 0.25rem; - } - } - - [data-slot="before"], - [data-slot="after"] { - position: relative; - display: flex; - flex-direction: column; - overflow-x: visible; - min-width: 0; - align-items: stretch; - padding: 0 1rem 0 2.2ch; - - &[data-diff-type="removed"] { - background-color: var(--sl-color-red-low); - - pre { - --shiki-dark-bg: var(--sl-color-red-low) !important; - background-color: var(--sl-color-red-low) !important; - } - - &::before { - content: "-"; - position: absolute; - left: 0.6ch; - top: 1px; - user-select: none; - color: var(--sl-color-red-high); - } - } - - &[data-diff-type="added"] { - background-color: var(--sl-color-green-low); - - pre { - --shiki-dark-bg: var(--sl-color-green-low) !important; - background-color: var(--sl-color-green-low) !important; - } - - &::before { - content: "+"; - position: absolute; - user-select: none; - color: var(--sl-color-green-high); - left: 0.6ch; - top: 1px; - } - } - } - - [data-slot="before"] { - border-right: 1px solid var(--sl-color-divider); - } - } - - [data-component="mobile"] { - & > [data-component="diff-block"]:first-child > div { - padding-top: 0.25rem; - } - - & > [data-component="diff-block"]:last-child > div { - padding-bottom: 0.25rem; - } - - & > [data-component="diff-block"] > div { - padding: 0 1rem 0 2.2ch; - - &[data-diff-type="removed"] { - position: relative; - background-color: var(--sl-color-red-low); - - pre { - --shiki-dark-bg: var(--sl-color-red-low) !important; - background-color: var(--sl-color-red-low) !important; - } - - &::before { - content: "-"; - position: absolute; - left: 0.6ch; - top: 1px; - user-select: none; - color: var(--sl-color-red-high); - } - } - - &[data-diff-type="added"] { - position: relative; - background-color: var(--sl-color-green-low); - - pre { - --shiki-dark-bg: var(--sl-color-green-low) !important; - background-color: var(--sl-color-green-low) !important; - } - - &::before { - content: "+"; - position: absolute; - left: 0.6ch; - top: 1px; - user-select: none; - color: var(--sl-color-green-high); - } - } - } - } - - @media (max-width: 40rem) { - [data-component="desktop"] { - display: none; - } - - [data-component="mobile"] { - display: block; - } - } -} diff --git a/frontend/docs/src/components/share/content-diff.tsx b/frontend/docs/src/components/share/content-diff.tsx deleted file mode 100644 index 9ccd554..0000000 --- a/frontend/docs/src/components/share/content-diff.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import { parsePatch } from "diff" -import { createMemo } from "solid-js" -import { ContentCode } from "./content-code" -import styles from "./content-diff.module.css" - -type DiffRow = { - left: string - right: string - type: "added" | "removed" | "unchanged" | "modified" -} - -interface Props { - diff: string - lang?: string -} - -export function ContentDiff(props: Props) { - const rows = createMemo(() => { - const diffRows: DiffRow[] = [] - - try { - const patches = parsePatch(props.diff) - - for (const patch of patches) { - for (const hunk of patch.hunks) { - const lines = hunk.lines - let i = 0 - - while (i < lines.length) { - const line = lines[i] - const content = line.slice(1) - const prefix = line[0] - - if (prefix === "-") { - // Look ahead for consecutive additions to pair with removals - const removals: string[] = [content] - let j = i + 1 - - // Collect all consecutive removals - while (j < lines.length && lines[j][0] === "-") { - removals.push(lines[j].slice(1)) - j++ - } - - // Collect all consecutive additions that follow - const additions: string[] = [] - while (j < lines.length && lines[j][0] === "+") { - additions.push(lines[j].slice(1)) - j++ - } - - // Pair removals with additions - const maxLength = Math.max(removals.length, additions.length) - for (let k = 0; k < maxLength; k++) { - const hasLeft = k < removals.length - const hasRight = k < additions.length - - if (hasLeft && hasRight) { - // Replacement - left is removed, right is added - diffRows.push({ - left: removals[k], - right: additions[k], - type: "modified", - }) - } else if (hasLeft) { - // Pure removal - diffRows.push({ - left: removals[k], - right: "", - type: "removed", - }) - } else if (hasRight) { - // Pure addition - only create if we actually have content - diffRows.push({ - left: "", - right: additions[k], - type: "added", - }) - } - } - - i = j - } else if (prefix === "+") { - // Standalone addition (not paired with removal) - diffRows.push({ - left: "", - right: content, - type: "added", - }) - i++ - } else if (prefix === " ") { - diffRows.push({ - left: content === "" ? " " : content, - right: content === "" ? " " : content, - type: "unchanged", - }) - i++ - } else { - i++ - } - } - } - } - } catch (error) { - console.error("Failed to parse patch:", error) - return [] - } - - return diffRows - }) - - const mobileRows = createMemo(() => { - const mobileBlocks: { - type: "removed" | "added" | "unchanged" - lines: string[] - }[] = [] - const currentRows = rows() - - let i = 0 - while (i < currentRows.length) { - const removedLines: string[] = [] - const addedLines: string[] = [] - - // Collect consecutive modified/removed/added rows - while ( - i < currentRows.length && - (currentRows[i].type === "modified" || currentRows[i].type === "removed" || currentRows[i].type === "added") - ) { - const row = currentRows[i] - if (row.left && (row.type === "removed" || row.type === "modified")) { - removedLines.push(row.left) - } - if (row.right && (row.type === "added" || row.type === "modified")) { - addedLines.push(row.right) - } - i++ - } - - // Add grouped blocks - if (removedLines.length > 0) { - mobileBlocks.push({ type: "removed", lines: removedLines }) - } - if (addedLines.length > 0) { - mobileBlocks.push({ type: "added", lines: addedLines }) - } - - // Add unchanged rows as-is - if (i < currentRows.length && currentRows[i].type === "unchanged") { - mobileBlocks.push({ - type: "unchanged", - lines: [currentRows[i].left], - }) - i++ - } - } - - return mobileBlocks - }) - - return ( -
-
- {rows().map((r) => ( -
-
- -
-
- -
-
- ))} -
- -
- {mobileRows().map((block) => ( -
- {block.lines.map((line) => ( -
- -
- ))} -
- ))} -
-
- ) -} - -// const testDiff = `--- combined_before.txt 2025-06-24 16:38:08 -// +++ combined_after.txt 2025-06-24 16:38:12 -// @@ -1,21 +1,25 @@ -// unchanged line -// -deleted line -// -old content -// +added line -// +new content -// -// -removed empty line below -// +added empty line above -// -// - tab indented -// -trailing spaces -// -very long line that will definitely wrap in most editors and cause potential alignment issues when displayed in a two column diff view -// -unicode content: 🚀 ✨ 中文 -// -mixed content with tabs and spaces -// + space indented -// +no trailing spaces -// +short line -// +very long replacement line that will also wrap and test how the diff viewer handles long line additions after short line removals -// +different unicode: 🎉 💻 日本語 -// +normalized content with consistent spacing -// +newline to content -// -// -content to remove -// -whitespace only: -// -multiple -// -consecutive -// -deletions -// -single deletion -// + -// +single addition -// +first addition -// +second addition -// +third addition -// line before addition -// +first added line -// + -// +third added line -// line after addition -// final unchanged line` diff --git a/frontend/docs/src/components/share/content-error.module.css b/frontend/docs/src/components/share/content-error.module.css deleted file mode 100644 index 9ed051a..0000000 --- a/frontend/docs/src/components/share/content-error.module.css +++ /dev/null @@ -1,64 +0,0 @@ -.root { - background-color: var(--sl-color-bg-surface); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - align-self: flex-start; - - [data-section="content"] { - pre { - margin-bottom: 0.5rem; - line-height: 1.5; - font-size: 0.75rem; - white-space: pre-wrap; - word-break: break-word; - - &:last-child { - margin-bottom: 0; - } - - span { - margin-right: 0.25rem; - &:last-child { - margin-right: 0; - } - } - span[data-color="red"] { - color: var(--sl-color-red); - } - span[data-color="dimmed"] { - color: var(--sl-color-text-dimmed); - } - span[data-marker="label"] { - text-transform: uppercase; - letter-spacing: -0.5px; - } - span[data-separator] { - margin-right: 0.375rem; - } - } - } - - &[data-expanded="true"] { - [data-section="content"] { - display: block; - } - } - &[data-expanded="false"] { - [data-section="content"] { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 7; - overflow: hidden; - } - } - - button { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } -} diff --git a/frontend/docs/src/components/share/content-error.tsx b/frontend/docs/src/components/share/content-error.tsx deleted file mode 100644 index 1e8cbea..0000000 --- a/frontend/docs/src/components/share/content-error.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import style from "./content-error.module.css" -import { type JSX, createSignal } from "solid-js" -import { createOverflow } from "./common" - -interface Props extends JSX.HTMLAttributes { - expand?: boolean -} -export function ContentError(props: Props) { - const [expanded, setExpanded] = createSignal(false) - const overflow = createOverflow() - - return ( -
-
- {props.children} -
- {((!props.expand && overflow.status) || expanded()) && ( - - )} -
- ) -} diff --git a/frontend/docs/src/components/share/content-markdown.module.css b/frontend/docs/src/components/share/content-markdown.module.css deleted file mode 100644 index 858a8ad..0000000 --- a/frontend/docs/src/components/share/content-markdown.module.css +++ /dev/null @@ -1,154 +0,0 @@ -.root { - position: relative; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - - [data-slot="expand-button"] { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.857em; - } - - [data-slot="markdown"] { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - - [data-expanded] & { - display: block; - } - - font-size: 1em; - line-height: 1.5; - - p, - blockquote, - ul, - ol, - dl, - table, - pre { - margin-bottom: 1rem; - } - - ul, - ol { - margin-bottom: 0.5rem; - } - - /* Add spacing between top-level list items */ - ol > li { - margin-bottom: 0.5rem; - } - - strong { - font-weight: 600; - } - - ol { - list-style-position: outside; - padding-left: 1.5rem; - } - - ul { - padding-left: 1.5rem; - } - - /* Nested list spacing */ - li ul, - li ol { - margin-top: 0.25rem; - margin-bottom: 0; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - font-size: 1em; - font-weight: 600; - margin-bottom: 0.5rem; - } - - & > *:last-child { - margin-bottom: 0; - } - - pre { - --shiki-dark-bg: var(--sl-color-bg-surface) !important; - background-color: var(--sl-color-bg-surface) !important; - padding: 0.5rem 0.75rem; - line-height: 1.6; - font-size: 0.857em; - white-space: pre-wrap; - word-break: break-word; - - span { - white-space: break-spaces; - } - } - - code { - font-weight: 500; - - &:not(pre code) { - &::before { - content: "`"; - font-weight: 700; - } - - &::after { - content: "`"; - font-weight: 700; - } - } - } - - table { - border-collapse: collapse; - width: 100%; - } - - th, - td { - border: 1px solid var(--sl-color-border); - padding: 0.5rem 0.75rem; - text-align: left; - } - - th { - border-bottom: 1px solid var(--sl-color-border); - } - - /* Remove outer borders */ - table tr:first-child th, - table tr:first-child td { - border-top: none; - } - - table tr:last-child td { - border-bottom: none; - } - - table th:first-child, - table td:first-child { - border-left: none; - } - - table th:last-child, - table td:last-child { - border-right: none; - } - } - - [data-component="copy-button"] { - top: 0; - right: 0; - } -} diff --git a/frontend/docs/src/components/share/content-markdown.tsx b/frontend/docs/src/components/share/content-markdown.tsx deleted file mode 100644 index b9b1d5d..0000000 --- a/frontend/docs/src/components/share/content-markdown.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { marked } from "marked" -import { codeToHtml } from "shiki" -import markedShiki from "marked-shiki" -import { createOverflow } from "./common" -import { CopyButton } from "./copy-button" -import { createResource, createSignal } from "solid-js" -import { transformerNotationDiff } from "@shikijs/transformers" -import style from "./content-markdown.module.css" - -const markedWithShiki = marked.use( - { - renderer: { - link({ href, title, text }) { - const titleAttr = title ? ` title="${title}"` : "" - return `${text}` - }, - }, - }, - markedShiki({ - highlight(code, lang) { - return codeToHtml(code, { - lang: lang || "text", - themes: { - light: "github-light", - dark: "github-dark", - }, - transformers: [transformerNotationDiff()], - }) - }, - }), -) - -interface Props { - text: string - expand?: boolean - highlight?: boolean -} -export function ContentMarkdown(props: Props) { - const [html] = createResource( - () => strip(props.text), - async (markdown) => { - return markedWithShiki.parse(markdown) - }, - ) - const [expanded, setExpanded] = createSignal(false) - const overflow = createOverflow() - - return ( -
-
- - {!props.expand && overflow.status && ( - - )} - -
- ) -} - -function strip(text: string): string { - const wrappedRe = /^\s*<([A-Za-z]\w*)>\s*([\s\S]*?)\s*<\/\1>\s*$/ - const match = text.match(wrappedRe) - return match ? match[2] : text -} diff --git a/frontend/docs/src/components/share/content-text.module.css b/frontend/docs/src/components/share/content-text.module.css deleted file mode 100644 index 139aa3f..0000000 --- a/frontend/docs/src/components/share/content-text.module.css +++ /dev/null @@ -1,63 +0,0 @@ -.root { - position: relative; - color: var(--sl-color-text); - background-color: var(--sl-color-bg-surface); - padding: 0.5rem calc(0.5rem + 3px); - padding-right: calc(1rem + 18px); - border-radius: 0.25rem; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 1rem; - align-self: flex-start; - font-size: 0.875rem; - - &[data-compact] { - font-size: 0.75rem; - color: var(--sl-color-text-dimmed); - } - - [data-slot="text"] { - line-height: 1.5; - white-space: pre-wrap; - overflow-wrap: anywhere; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - - [data-expanded] & { - display: block; - } - } - - [data-slot="expand-button"] { - flex: 0 0 auto; - padding: 2px 0; - font-size: 0.75rem; - } - - &[data-theme="invert"] { - background-color: var(--sl-color-blue-high); - color: var(--sl-color-text-invert); - - [data-slot="expand-button"] { - opacity: 0.85; - color: var(--sl-color-text-invert); - - &:hover { - opacity: 1; - } - } - } - - &[data-theme="blue"] { - background-color: var(--sl-color-blue-low); - } - - [data-component="copy-button"] { - top: 0.5rem; - right: calc(0.5rem - 1px); - } -} diff --git a/frontend/docs/src/components/share/content-text.tsx b/frontend/docs/src/components/share/content-text.tsx deleted file mode 100644 index 5db12a5..0000000 --- a/frontend/docs/src/components/share/content-text.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import style from "./content-text.module.css" -import { createSignal } from "solid-js" -import { createOverflow } from "./common" -import { CopyButton } from "./copy-button" - -interface Props { - text: string - expand?: boolean - compact?: boolean -} -export function ContentText(props: Props) { - const [expanded, setExpanded] = createSignal(false) - const overflow = createOverflow() - - return ( -
-
-        {props.text}
-      
- {((!props.expand && overflow.status) || expanded()) && ( - - )} - -
- ) -} diff --git a/frontend/docs/src/components/share/copy-button.module.css b/frontend/docs/src/components/share/copy-button.module.css deleted file mode 100644 index 31013fc..0000000 --- a/frontend/docs/src/components/share/copy-button.module.css +++ /dev/null @@ -1,30 +0,0 @@ -.root { - position: absolute; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease; - - button { - cursor: pointer; - background: none; - border: none; - padding: 0.125rem; - color: var(--sl-color-text-secondary); - - svg { - display: block; - width: 1rem; - height: 1rem; - } - - &[data-copied="true"] { - color: var(--sl-color-green-high); - } - } -} - -/* Show copy button when parent is hovered */ -*:hover > .root { - opacity: 1; - visibility: visible; -} diff --git a/frontend/docs/src/components/share/copy-button.tsx b/frontend/docs/src/components/share/copy-button.tsx deleted file mode 100644 index 892d555..0000000 --- a/frontend/docs/src/components/share/copy-button.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { createSignal } from "solid-js" -import { IconClipboard, IconCheckCircle } from "../icons" -import styles from "./copy-button.module.css" - -interface CopyButtonProps { - text: string -} - -export function CopyButton(props: CopyButtonProps) { - const [copied, setCopied] = createSignal(false) - - function handleCopyClick() { - if (props.text) { - navigator.clipboard.writeText(props.text).catch((err) => console.error("Copy failed", err)) - - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } - } - - return ( -
- -
- ) -} diff --git a/frontend/docs/src/components/share/part.module.css b/frontend/docs/src/components/share/part.module.css deleted file mode 100644 index b126944..0000000 --- a/frontend/docs/src/components/share/part.module.css +++ /dev/null @@ -1,428 +0,0 @@ -.root { - display: flex; - gap: 0.625rem; - - [data-component="decoration"] { - flex: 0 0 auto; - display: flex; - flex-direction: column; - gap: 0.625rem; - align-items: center; - justify-content: flex-start; - - [data-slot="anchor"] { - position: relative; - - a:first-child { - display: block; - flex: 0 0 auto; - width: 18px; - opacity: 0.65; - - svg { - color: var(--sl-color-text-secondary); - display: block; - - &:nth-child(3) { - color: var(--sl-color-green-high); - } - } - - svg:nth-child(2), - svg:nth-child(3) { - display: none; - } - - &:hover { - svg:nth-child(1) { - display: none; - } - - svg:nth-child(2) { - display: block; - } - } - } - - [data-copied] & { - a, - a:hover { - svg:nth-child(1), - svg:nth-child(2) { - display: none; - } - - svg:nth-child(3) { - display: block; - } - } - } - } - - [data-slot="bar"] { - width: 3px; - height: 100%; - border-radius: 1px; - background-color: var(--sl-color-hairline); - } - - [data-slot="tooltip"] { - position: absolute; - top: 50%; - left: calc(100% + 12px); - transform: translate(0, -50%); - line-height: 1.1; - padding: 0.375em 0.5em calc(0.375em + 2px); - background: var(--sl-color-white); - color: var(--sl-color-text-invert); - font-size: 0.6875rem; - border-radius: 7px; - white-space: nowrap; - - z-index: 1; - opacity: 0; - visibility: hidden; - - &::after { - content: ""; - position: absolute; - top: 50%; - left: -15px; - transform: translateY(-50%); - border: 8px solid transparent; - border-right-color: var(--sl-color-white); - } - - [data-copied] & { - opacity: 1; - visibility: visible; - } - } - } - - [data-component="content"] { - flex: 1 1 auto; - min-width: 0; - padding: 0 0 1rem; - display: flex; - flex-direction: column; - gap: 1rem; - } - - [data-component="spacer"] { - height: 0rem; - } - - [data-component="content-footer"] { - align-self: flex-start; - font-size: 0.75rem; - color: var(--sl-color-text-dimmed); - } - - [data-component="user-text"] { - min-width: 0; - display: flex; - flex-direction: column; - gap: 1rem; - flex-grow: 1; - max-width: var(--md-tool-width); - position: relative; - } - - [data-component="assistant-reasoning"] { - min-width: 0; - display: flex; - flex-direction: column; - gap: 0.5rem; - flex-grow: 1; - max-width: var(--md-tool-width); - - [data-component="assistant-reasoning-markdown"] { - align-self: flex-start; - font-size: 0.75rem; - border: 1px solid var(--sl-color-blue-high); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - position: relative; - } - } - - [data-component="assistant-text"] { - min-width: 0; - display: flex; - flex-direction: column; - gap: 1rem; - flex-grow: 1; - max-width: var(--md-tool-width); - - & > [data-component="assistant-text-markdown"] { - align-self: flex-start; - font-size: 0.875rem; - border: 1px solid var(--sl-color-blue-high); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - position: relative; - } - } - - [data-component="step-start"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.375rem; - - [data-slot="provider"] { - line-height: 18px; - font-size: 0.875rem; - text-transform: uppercase; - letter-spacing: -0.5px; - color: var(--sl-color-text-secondary); - } - - [data-slot="model"] { - line-height: 1.5; - } - } - - [data-component="attachment"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.375rem; - padding-bottom: 1rem; - - [data-slot="copy"] { - line-height: 18px; - font-size: 0.875rem; - text-transform: uppercase; - letter-spacing: -0.5px; - color: var(--sl-color-text-secondary); - } - - [data-slot="filename"] { - line-height: 1.5; - font-size: 0.875rem; - font-weight: 500; - max-width: var(--md-tool-width); - } - } - - [data-component="button-text"] { - cursor: pointer; - appearance: none; - background-color: transparent; - border: none; - padding: 0; - color: var(--sl-color-text-secondary); - font-size: 0.75rem; - - &:hover { - color: var(--sl-color-text); - } - - &[data-more] { - display: flex; - align-items: center; - gap: 0.125rem; - - span[data-slot="icon"] { - line-height: 1; - opacity: 0.85; - - svg { - display: block; - } - } - } - } - - [data-component="tool"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.375rem; - - &[data-tool="bash"] { - max-width: var(--sm-tool-width); - } - - &[data-tool="error"] { - max-width: var(--md-tool-width); - } - - &[data-tool="read"], - &[data-tool="edit"], - &[data-tool="list"], - &[data-tool="glob"], - &[data-tool="grep"], - &[data-tool="write"], - &[data-tool="webfetch"] { - [data-component="tool-result"] { - max-width: var(--sm-tool-width); - } - } - &[data-tool="edit"] { - [data-component="tool-result"] { - max-width: var(--lg-tool-width); - align-items: stretch; - width: 100%; - } - } - &[data-tool="task"] { - [data-component="tool-input"] { - font-size: 0.75rem; - line-height: 1.5; - max-width: var(--md-tool-width); - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; - } - [data-component="tool-output"] { - max-width: var(--sm-tool-width); - font-size: 0.75rem; - border: 1px solid var(--sl-color-divider); - padding: 0.5rem calc(0.5rem + 3px); - border-radius: 0.25rem; - position: relative; - } - } - } - - [data-component="tool-title"] { - line-height: 18px; - font-size: 0.875rem; - color: var(--sl-color-text-secondary); - max-width: var(--md-tool-width); - display: flex; - align-items: flex-start; - gap: 0.375rem; - - [data-slot="name"] { - text-transform: uppercase; - letter-spacing: -0.5px; - } - - [data-slot="target"] { - color: var(--sl-color-text); - word-break: break-all; - font-weight: 500; - } - } - - [data-component="tool-result"] { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.5rem; - } - - [data-component="todos"] { - list-style-type: none; - padding: 0; - margin: 0; - width: 100%; - max-width: var(--sm-tool-width); - border: 1px solid var(--sl-color-divider); - border-radius: 0.25rem; - - [data-slot="item"] { - margin: 0; - position: relative; - padding-left: 1.5rem; - font-size: 0.75rem; - padding: 0.375rem 0.625rem 0.375rem 1.75rem; - border-bottom: 1px solid var(--sl-color-divider); - line-height: 1.5; - word-break: break-word; - - &:last-child { - border-bottom: none; - } - - & > span { - position: absolute; - display: inline-block; - left: 0.5rem; - top: calc(0.5rem + 1px); - width: 0.75rem; - height: 0.75rem; - border: 1px solid var(--sl-color-divider); - border-radius: 0.15rem; - - &::before { - } - } - - &[data-status="pending"] { - color: var(--sl-color-text); - } - - &[data-status="in_progress"] { - color: var(--sl-color-text); - - & > span { - border-color: var(--sl-color-orange); - } - - & > span::before { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: calc(0.75rem - 2px - 4px); - height: calc(0.75rem - 2px - 4px); - box-shadow: inset 1rem 1rem var(--sl-color-orange-low); - } - } - - &[data-status="completed"] { - color: var(--sl-color-text-secondary); - - & > span { - border-color: var(--sl-color-green-low); - } - - & > span::before { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: calc(0.75rem - 2px - 4px); - height: calc(0.75rem - 2px - 4px); - box-shadow: inset 1rem 1rem var(--sl-color-green); - - transform-origin: bottom left; - clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); - } - } - } - } - - [data-component="tool-args"] { - display: inline-grid; - align-items: center; - grid-template-columns: max-content max-content minmax(0, 1fr); - max-width: var(--md-tool-width); - gap: 0.25rem 0.375rem; - - & > div:nth-child(3n + 1) { - width: 8px; - height: 2px; - border-radius: 1px; - background: var(--sl-color-divider); - } - - & > div:nth-child(3n + 2), - & > div:nth-child(3n + 3) { - font-size: 0.75rem; - line-height: 1.5; - } - - & > div:nth-child(3n + 3) { - padding-left: 0.125rem; - word-break: break-word; - color: var(--sl-color-text-secondary); - } - } -} diff --git a/frontend/docs/src/components/share/part.tsx b/frontend/docs/src/components/share/part.tsx deleted file mode 100644 index ad2ba60..0000000 --- a/frontend/docs/src/components/share/part.tsx +++ /dev/null @@ -1,780 +0,0 @@ -import map from "lang-map" -import { DateTime } from "luxon" -import { For, Show, Match, Switch, type JSX, createMemo, createSignal, type ParentProps } from "solid-js" -import { - IconHashtag, - IconSparkles, - IconGlobeAlt, - IconDocument, - IconPaperClip, - IconQueueList, - IconUserCircle, - IconCommandLine, - IconCheckCircle, - IconChevronDown, - IconChevronRight, - IconDocumentPlus, - IconPencilSquare, - IconRectangleStack, - IconMagnifyingGlass, - IconDocumentMagnifyingGlass, -} from "../icons" -import { IconMeta, IconRobot, IconOpenAI, IconGemini, IconAnthropic, IconBrain } from "../icons/custom" -import { ContentCode } from "./content-code" -import { ContentDiff } from "./content-diff" -import { ContentText } from "./content-text" -import { ContentBash } from "./content-bash" -import { ContentError } from "./content-error" -import { formatDuration } from "../share/common" -import { ContentMarkdown } from "./content-markdown" -import type { MessageV2 } from "@synsci/openscience/session/message-v2" -import type { Diagnostic } from "vscode-languageserver-types" - -import styles from "./part.module.css" - -const MIN_DURATION = 2000 - -export interface PartProps { - index: number - message: MessageV2.Info - part: MessageV2.Part - last: boolean -} - -export function Part(props: PartProps) { - const [copied, setCopied] = createSignal(false) - const id = createMemo(() => props.message.id + "-" + props.index) - - return ( -
- -
- {props.message.role === "user" && props.part.type === "text" && ( -
- -
- )} - {props.message.role === "assistant" && props.part.type === "text" && ( -
-
- -
- {props.last && props.message.role === "assistant" && props.message.time.completed && ( -
- {DateTime.fromMillis(props.message.time.completed).toLocaleString(DateTime.DATETIME_MED)} -
- )} -
- )} - {props.message.role === "assistant" && props.part.type === "reasoning" && ( -
-
- Thinking -
- -
- -
- -
-
-
-
-
- )} - {props.message.role === "user" && props.part.type === "file" && ( -
-
Attachment
-
{props.part.filename}
-
- )} - {props.message.role === "user" && props.part.type === "file" && ( -
-
Attachment
-
{props.part.filename}
-
- )} - {props.part.type === "step-start" && props.message.role === "assistant" && ( -
-
{props.message.providerID}
-
{props.message.modelID}
-
- )} - {props.part.type === "tool" && props.part.state.status === "error" && ( -
- {formatErrorString(props.part.state.error)} - -
- )} - {props.part.type === "tool" && - props.part.state.status === "completed" && - props.message.role === "assistant" && ( - <> -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - )} -
-
- ) -} - -type ToolProps = { - id: MessageV2.ToolPart["id"] - tool: MessageV2.ToolPart["tool"] - state: MessageV2.ToolStateCompleted - message: MessageV2.Assistant - isLastPart?: boolean -} - -interface Todo { - id: string - content: string - status: "pending" | "in_progress" | "completed" - priority: "low" | "medium" | "high" -} - -function stripWorkingDirectory(filePath?: string, workingDir?: string) { - if (filePath === undefined || workingDir === undefined) return filePath - - const prefix = workingDir.endsWith("/") ? workingDir : workingDir + "/" - - if (filePath === workingDir) { - return "" - } - - if (filePath.startsWith(prefix)) { - return filePath.slice(prefix.length) - } - - return filePath -} - -function getShikiLang(filename: string) { - const ext = filename.split(".").pop()?.toLowerCase() ?? "" - const langs = map.languages(ext) - const type = langs?.[0]?.toLowerCase() - - const overrides: Record = { - conf: "shellscript", - } - - return type ? (overrides[type] ?? type) : "plaintext" -} - -function getDiagnostics(diagnosticsByFile: Record, currentFile: string): JSX.Element[] { - const result: JSX.Element[] = [] - - if (diagnosticsByFile === undefined || diagnosticsByFile[currentFile] === undefined) return result - - for (const diags of Object.values(diagnosticsByFile)) { - for (const d of diags) { - if (d.severity !== 1) continue - - const line = d.range.start.line + 1 - const column = d.range.start.character + 1 - - result.push( -
-          
-            Error
-          
-          
-            [{line}:{column}]
-          
-          {d.message}
-        
, - ) - } - } - - return result -} - -function formatErrorString(error: string): JSX.Element { - const errorMarker = "Error: " - const startsWithError = error.startsWith(errorMarker) - - return startsWithError ? ( -
-      
-        Error
-      
-      {error.slice(errorMarker.length)}
-    
- ) : ( -
-      {error}
-    
- ) -} - -export function TodoWriteTool(props: ToolProps) { - const priority: Record = { - in_progress: 0, - pending: 1, - completed: 2, - } - const todos = createMemo(() => - ((props.state.input?.todos ?? []) as Todo[]).slice().sort((a, b) => priority[a.status] - priority[b.status]), - ) - const starting = () => todos().every((t: Todo) => t.status === "pending") - const finished = () => todos().every((t: Todo) => t.status === "completed") - - return ( - <> -
- - - Creating plan - Completing plan - - -
- 0}> -
    - - {(todo) => ( -
  • - - {todo.content} -
  • - )} -
    -
-
- - ) -} - -export function GrepTool(props: ToolProps) { - return ( - <> -
- Grep - “{props.state.input.pattern}” -
-
- - 0}> - - - - - - - - -
- - ) -} - -export function ListTool(props: ToolProps) { - const path = createMemo(() => - props.state.input?.path !== props.message.path.cwd - ? stripWorkingDirectory(props.state.input?.path, props.message.path.cwd) - : props.state.input?.path, - ) - - return ( - <> -
- LS - - {path()} - -
-
- - - - - - - -
- - ) -} - -export function WebFetchTool(props: ToolProps) { - return ( - <> -
- Fetch - {props.state.input.url} -
-
- - - {formatErrorString(props.state.output)} - - - - - - - -
- - ) -} - -export function ReadTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd)) - - return ( - <> -
- Read - - {filePath()} - -
-
- - - {formatErrorString(props.state.output)} - - - - - - - - - - - - -
- - ) -} - -export function WriteTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd)) - const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath)) - - return ( - <> -
- Write - - {filePath()} - -
- 0}> - {diagnostics()} - -
- - - {formatErrorString(props.state.output)} - - - - - - - -
- - ) -} - -export function EditTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input.filePath, props.message.path.cwd)) - const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath)) - - return ( - <> -
- Edit - - {filePath()} - -
-
- - - {formatErrorString(props.state.metadata?.message || "")} - - -
- -
-
-
-
- 0}> - {diagnostics()} - - - ) -} - -export function BashTool(props: ToolProps) { - return ( - - ) -} - -export function GlobTool(props: ToolProps) { - return ( - <> -
- Glob - “{props.state.input.pattern}” -
- - 0}> -
- - - -
-
- - - -
- - ) -} - -interface ResultsButtonProps extends ParentProps { - showCopy?: string - hideCopy?: string -} -function ResultsButton(props: ResultsButtonProps) { - const [show, setShow] = createSignal(false) - - return ( - <> - - {props.children} - - ) -} - -export function Spacer() { - return
-} - -function Footer(props: ParentProps<{ title: string }>) { - return ( -
- {props.children} -
- ) -} - -function ToolFooter(props: { time: number }) { - return props.time > MIN_DURATION &&
{formatDuration(props.time)}
-} - -function TaskTool(props: ToolProps) { - return ( - <> -
- Task - {props.state.input.description} -
-
“{props.state.input.prompt}”
- -
- -
-
- - ) -} - -export function FallbackTool(props: ToolProps) { - return ( - <> -
- {props.tool} -
-
- - {(arg) => ( - <> -
-
{arg[0]}
-
{arg[1]}
- - )} -
-
- - -
- - - -
-
-
- - ) -} - -// Converts nested objects/arrays into [path, value] pairs. -// E.g. {a:{b:{c:1}}, d:[{e:2}, 3]} => [["a.b.c",1], ["d[0].e",2], ["d[1]",3]] -function flattenToolArgs(obj: any, prefix: string = ""): Array<[string, any]> { - const entries: Array<[string, any]> = [] - - for (const [key, value] of Object.entries(obj)) { - const path = prefix ? `${prefix}.${key}` : key - - if (value !== null && typeof value === "object") { - if (Array.isArray(value)) { - value.forEach((item, index) => { - const arrayPath = `${path}[${index}]` - if (item !== null && typeof item === "object") { - entries.push(...flattenToolArgs(item, arrayPath)) - } else { - entries.push([arrayPath, item]) - } - }) - } else { - entries.push(...flattenToolArgs(value, path)) - } - } else { - entries.push([path, value]) - } - } - - return entries -} - -function getProvider(model: string) { - const lowerModel = model.toLowerCase() - - if (/claude|anthropic/.test(lowerModel)) return "anthropic" - if (/gpt|o[1-4]|codex|openai/.test(lowerModel)) return "openai" - if (/gemini|palm|bard|google/.test(lowerModel)) return "gemini" - if (/llama|meta/.test(lowerModel)) return "meta" - - return "any" -} - -export function ProviderIcon(props: { model: string; size?: number }) { - const provider = getProvider(props.model) - const size = props.size || 16 - return ( - }> - - - - - - - - - - - - - - ) -} diff --git a/frontend/docs/src/content.config.ts b/frontend/docs/src/content.config.ts deleted file mode 100644 index d614714..0000000 --- a/frontend/docs/src/content.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineCollection } from "astro:content" -import { docsLoader } from "@astrojs/starlight/loaders" -import { docsSchema } from "@astrojs/starlight/schema" - -export const collections = { - docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), -} diff --git a/frontend/docs/src/content/docs/1-0.mdx b/frontend/docs/src/content/docs/1-0.mdx deleted file mode 100644 index 926e7f3..0000000 --- a/frontend/docs/src/content/docs/1-0.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Migrating to 1.0 -description: What's new in OpenScience 1.0. ---- - -OpenScience 1.0 introduces the browser workspace. Running `openscience` opens a workspace in your browser, and `openscience web` does the same. It connects to the same OpenScience server, so your existing sessions and projects carry over. - ---- - -## Upgrading - -You should not be auto-upgraded to 1.0 if you are currently using a previous version. Some older versions of OpenScience always grab the latest release. - -To upgrade manually, run: - -```bash -$ openscience upgrade 1.0.0 -``` - -To downgrade back to 0.x, run: - -```bash -$ openscience upgrade 0.15.31 -``` - ---- - -## What's new - -The session history is more compact, showing full details only for the edit and bash tools. - -There is a command bar that almost everything flows through. Press ctrl+p to bring it up in any context and see everything you can do. - -There is a session sidebar you can toggle, with useful information about the current session. - -We removed some functionality we weren't sure anyone used. If something important is missing, open an issue and we'll add it back quickly. - ---- - -## Breaking changes - -Actions that used to be keyboard shortcuts now live in the command bar. Open it with ctrl+p and search for the one you need. diff --git a/frontend/docs/src/content/docs/acp.mdx b/frontend/docs/src/content/docs/acp.mdx deleted file mode 100644 index e589505..0000000 --- a/frontend/docs/src/content/docs/acp.mdx +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: ACP Support -description: Use OpenScience in any ACP-compatible editor. ---- - -OpenScience supports the [Agent Client Protocol](https://agentclientprotocol.com) or (ACP), allowing you to use it directly in compatible editors and IDEs. - -:::tip -For a list of editors and tools that support ACP, check out the [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now). -::: - -ACP is an open protocol that standardizes communication between code editors and AI coding agents. - ---- - -## Configure - -To use OpenScience via ACP, configure your editor to run the `openscience acp` command. - -The command starts OpenScience as an ACP-compatible subprocess that communicates with your editor over JSON-RPC via stdio. - -Below are examples for popular editors that support ACP. - ---- - -### Zed - -Add to your [Zed](https://zed.dev) configuration (`~/.config/zed/settings.json`): - -```json title="~/.config/zed/settings.json" -{ - "agent_servers": { - "OpenScience": { - "command": "openscience", - "args": ["acp"] - } - } -} -``` - -To open it, use the `agent: new thread` action in the **Command Palette**. - -You can also bind a keyboard shortcut by editing your `keymap.json`: - -```json title="keymap.json" -[ - { - "bindings": { - "cmd-alt-o": [ - "agent::NewExternalAgentThread", - { - "agent": { - "custom": { - "name": "OpenScience", - "command": { - "command": "openscience", - "args": ["acp"] - } - } - } - } - ] - } - } -] -``` - ---- - -### JetBrains IDEs - -Add to your [JetBrains IDE](https://www.jetbrains.com/) acp.json according to the [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html): - -```json title="acp.json" -{ - "agent_servers": { - "OpenScience": { - "command": "/absolute/path/bin/openscience", - "args": ["acp"] - } - } -} -``` - -To open it, use the new 'OpenScience' agent in the AI Chat agent selector. - ---- - -### Avante.nvim - -Add to your [Avante.nvim](https://github.com/yetone/avante.nvim) configuration: - -```lua -{ - acp_providers = { - ["openscience"] = { - command = "openscience", - args = { "acp" } - } - } -} -``` - -If you need to pass environment variables: - -```lua {6-8} -{ - acp_providers = { - ["openscience"] = { - command = "openscience", - args = { "acp" }, - env = { - SYNSCI_API_KEY = os.getenv("SYNSCI_API_KEY") - } - } - } -} -``` - ---- - -### CodeCompanion.nvim - -To use OpenScience as an ACP agent in [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), add the following to your Neovim config: - -```lua -require("codecompanion").setup({ - interactions = { - chat = { - adapter = { - name = "openscience", - model = "claude-sonnet-4", - }, - }, - }, -}) -``` - -This config sets up CodeCompanion to use OpenScience as the ACP agent for chat. - -If you need to pass environment variables (like `SYNSCI_API_KEY`), refer to [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) in the CodeCompanion.nvim documentation for full details. - -## Support - -OpenScience works the same over ACP as it does in the workspace. All features are supported: - -:::note -Some built-in slash commands like `/undo` and `/redo` are currently unsupported. -::: - -- Built-in tools (file operations, shell commands, etc.) -- Custom tools and slash commands -- MCP servers configured in your OpenScience config -- Project-specific rules from `AGENTS.md` -- Custom formatters and linters -- Agents and permissions system diff --git a/frontend/docs/src/content/docs/agents.mdx b/frontend/docs/src/content/docs/agents.mdx deleted file mode 100644 index 5d52ccb..0000000 --- a/frontend/docs/src/content/docs/agents.mdx +++ /dev/null @@ -1,687 +0,0 @@ ---- -title: Agents -description: Configure and use specialized agents. ---- - -Agents are specialized AI assistants that can be configured for specific tasks and workflows. They allow you to create focused tools with custom prompts, models, and tool access. - -:::tip -Use the plan agent to analyze code and review suggestions without making any code changes. -::: - -You can switch between agents during a session or invoke them with the `@` mention. - ---- - -## Types - -There are two types of agents in OpenScience; primary agents and subagents. - ---- - -### Primary agents - -Primary agents are the main assistants you interact with directly. You can cycle through them using the **Tab** key, or your configured `switch_agent` keybind. These agents handle your main conversation. Tool access is configured via permissions. For example, Research has all tools enabled while Plan is restricted. - -:::tip -You can use the **Tab** key to switch between primary agents during a session. -::: - -OpenScience comes with two built-in primary agents, **Research** (the default) and -**Plan**, plus the domain specialists **Biology**, **Physics**, and **ML** that can -run as either primary agents or subagents. We'll look at these below. - ---- - -### Subagents - -Subagents are specialized assistants that primary agents can invoke for specific tasks. You can also manually invoke them by **@ mentioning** them in your messages. - -OpenScience ships with a set of built-in subagents that primary agents invoke automatically for specialized work: task (general-purpose), explore, literature-review, critique, reviewer, physics-critique, and write. We'll look at the main ones below. - ---- - -## Built-in - -Let's look at the main built-in agents. - ---- - -### Research - -_Mode_: `primary` - -Research is the **default** primary agent with all tools enabled. It's the standard harness for scientific research work such as literature review, data analysis, GPU compute, and synthesis, with full access to file operations and system commands. - ---- - -### Biology, Physics, and ML - -_Mode_: `all` - -Domain specialists for computational biology, computational physics, and machine learning. Each ships with a task-specific workflow prompt and can be used as your primary agent or invoked as a subagent. - ---- - -### Plan - -_Mode_: `primary` - -A restricted agent designed for planning and analysis. We use a permission system to give you more control and prevent unintended changes. -By default, all of the following are set to `ask`: - -- `file edits`: All writes, patches, and edits -- `bash`: All bash commands - -This agent is useful when you want the LLM to analyze code, suggest changes, or create plans without making any actual modifications to your codebase. - ---- - -### Task - -_Mode_: `subagent` - -A general-purpose agent for researching complex questions and executing multi-step tasks. Has full tool access (except todo), so it can make file changes when needed. Use this to run multiple units of work in parallel. - ---- - -### Explore - -_Mode_: `subagent` - -A fast, read-only agent for exploring codebases. Cannot modify files. Use this when you need to quickly find files by patterns, search code for keywords, or answer questions about the codebase. - ---- - -## Usage - -1. For primary agents, use the **Tab** key to cycle through them during a session. You can also use your configured `switch_agent` keybind. - -2. Subagents can be invoked: - - **Automatically** by primary agents for specialized tasks based on their descriptions. - - Manually by **@ mentioning** a subagent in your message. For example. - - ```txt frame="none" - @explore help me search for this function - ``` - -3. **Navigation between sessions**: When subagents create their own child sessions, you can move between the parent session and all of its child sessions in the workspace. Cycle forward with the `session_child_cycle` keybind and backward with `session_child_cycle_reverse`. - - This lets you switch between the main conversation and specialized subagent work. - ---- - -## Configure - -You can customize the built-in agents or create your own through configuration. Agents can be configured in two ways: - ---- - -### JSON - -Configure agents in your `openscience.json` config file: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "research": { - "mode": "primary", - "model": "anthropic/claude-sonnet-4-20250514", - "prompt": "{file:./prompts/research.txt}", - "tools": { - "write": true, - "edit": true, - "bash": true - } - }, - "plan": { - "mode": "primary", - "model": "anthropic/claude-haiku-4-20250514", - "tools": { - "write": false, - "edit": false, - "bash": false - } - }, - "code-reviewer": { - "description": "Reviews code for best practices and potential issues", - "mode": "subagent", - "model": "anthropic/claude-sonnet-4-20250514", - "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", - "tools": { - "write": false, - "edit": false - } - } - } -} -``` - ---- - -### Markdown - -You can also define agents using markdown files. Place them in: - -- Global: `~/.config/openscience/agents/` -- Per-project: `.openscience/agents/` - -```markdown title="~/.config/openscience/agents/review.md" ---- -description: Reviews code for quality and best practices -mode: subagent -model: anthropic/claude-sonnet-4-20250514 -temperature: 0.1 -tools: - write: false - edit: false - bash: false ---- - -You are in code review mode. Focus on: - -- Code quality and best practices -- Potential bugs and edge cases -- Performance implications -- Security considerations - -Provide constructive feedback without making direct changes. -``` - -The markdown file name becomes the agent name. For example, `review.md` creates a `review` agent. - ---- - -## Options - -Let's look at these configuration options in detail. - ---- - -### Description - -Use the `description` option to provide a brief description of what the agent does and when to use it. - -```json title="openscience.json" -{ - "agent": { - "review": { - "description": "Reviews code for best practices and potential issues" - } - } -} -``` - -This is a **required** config option. - ---- - -### Temperature - -Control the randomness and creativity of the LLM's responses with the `temperature` config. - -Lower values make responses more focused and deterministic, while higher values increase creativity and variability. - -```json title="openscience.json" -{ - "agent": { - "plan": { - "temperature": 0.1 - }, - "creative": { - "temperature": 0.8 - } - } -} -``` - -Temperature values typically range from 0.0 to 1.0: - -- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning -- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks -- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration - -```json title="openscience.json" -{ - "agent": { - "analyze": { - "temperature": 0.1, - "prompt": "{file:./prompts/analysis.txt}" - }, - "research": { - "temperature": 0.3 - }, - "brainstorm": { - "temperature": 0.7, - "prompt": "{file:./prompts/creative.txt}" - } - } -} -``` - -If no temperature is specified, OpenScience uses model-specific defaults; typically 0 for most models, 0.55 for Qwen models. - ---- - -### Max steps - -Control the maximum number of agentic iterations an agent can perform before being forced to respond with text only. This allows users who wish to control costs to set a limit on agentic actions. - -If this is not set, the agent will continue to iterate until the model chooses to stop or the user interrupts the session. - -```json title="openscience.json" -{ - "agent": { - "quick-thinker": { - "description": "Fast reasoning with limited iterations", - "prompt": "You are a quick thinker. Solve problems with minimal steps.", - "maxSteps": 5 - } - } -} -``` - -When the limit is reached, the agent receives a special system prompt instructing it to respond with a summarization of its work and recommended remaining tasks. - ---- - -### Disable - -Set to `true` to disable the agent. - -```json title="openscience.json" -{ - "agent": { - "review": { - "disable": true - } - } -} -``` - ---- - -### Prompt - -Specify a custom system prompt file for this agent with the `prompt` config. The prompt file should contain instructions specific to the agent's purpose. - -```json title="openscience.json" -{ - "agent": { - "review": { - "prompt": "{file:./prompts/code-review.txt}" - } - } -} -``` - -This path is relative to where the config file is located. So this works for both the global OpenScience config and the project specific config. - ---- - -### Model - -Use the `model` config to override the model for this agent. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation. - -:::tip -If you don't specify a model, primary agents use the [model globally configured](/docs/config#models) while subagents will use the model of the primary agent that invoked the subagent. -::: - -```json title="openscience.json" -{ - "agent": { - "plan": { - "model": "anthropic/claude-haiku-4-20250514" - } - } -} -``` - -The model ID in your OpenScience config uses the format `provider/model-id`. For example, if you're using [Atlas](/docs/atlas), you would use `synsci/gpt-5-nano` for GPT 5 Nano. - ---- - -### Tools - -Control which tools are available in this agent with the `tools` config. You can enable or disable specific tools by setting them to `true` or `false`. - -```json title="openscience.json" {3-6,9-12} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "tools": { - "write": true, - "bash": true - }, - "agent": { - "plan": { - "tools": { - "write": false, - "bash": false - } - } - } -} -``` - -:::note -The agent-specific config overrides the global config. -::: - -You can also use wildcards to control multiple tools at once. For example, to disable all tools from an MCP server: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "readonly": { - "tools": { - "mymcp_*": false, - "write": false, - "edit": false - } - } - } -} -``` - -[Learn more about tools](/docs/tools). - ---- - -### Permissions - -You can configure permissions to manage what actions an agent can take. Currently, the permissions for the `edit`, `bash`, and `webfetch` tools can be configured to: - -- `"ask"`: Prompt for approval before running the tool -- `"allow"`: Allow all operations without approval -- `"deny"`: Disable the tool - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "deny" - } -} -``` - -You can override these permissions per agent. - -```json title="openscience.json" {3-5,8-10} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "deny" - }, - "agent": { - "research": { - "permission": { - "edit": "ask" - } - } - } -} -``` - -You can also set permissions in Markdown agents. - -```markdown title="~/.config/openscience/agents/review.md" ---- -description: Code review without edits -mode: subagent -permission: - edit: deny - bash: - "*": ask - "git diff": allow - "git log*": allow - "grep *": allow - webfetch: deny ---- - -Only analyze code and suggest changes. -``` - -You can set permissions for specific bash commands. - -```json title="openscience.json" {7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "research": { - "permission": { - "bash": { - "git push": "ask", - "grep *": "allow" - } - } - } - } -} -``` - -This can take a glob pattern. - -```json title="openscience.json" {7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "research": { - "permission": { - "bash": { - "git *": "ask" - } - } - } - } -} -``` - -And you can also use the `*` wildcard to manage permissions for all commands. -Since the last matching rule takes precedence, put the `*` wildcard first and specific rules after. - -```json title="openscience.json" {8} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "research": { - "permission": { - "bash": { - "*": "ask", - "git status *": "allow" - } - } - } - } -} -``` - -[Learn more about permissions](/docs/permissions). - ---- - -### Mode - -Control the agent's mode with the `mode` config. The `mode` option is used to determine how the agent can be used. - -```json title="openscience.json" -{ - "agent": { - "review": { - "mode": "subagent" - } - } -} -``` - -The `mode` option can be set to `primary`, `subagent`, or `all`. If no `mode` is specified, it defaults to `all`. - ---- - -### Hidden - -Hide a subagent from the `@` autocomplete menu with `hidden: true`. Useful for internal subagents that should only be invoked programmatically by other agents via the Task tool. - -```json title="openscience.json" -{ - "agent": { - "internal-helper": { - "mode": "subagent", - "hidden": true - } - } -} -``` - -This only affects user visibility in the autocomplete menu. Hidden agents can still be invoked by the model via the Task tool if permissions allow. - -:::note -Only applies to `mode: subagent` agents. -::: - ---- - -### Task permissions - -Control which subagents an agent can invoke via the Task tool with `permission.task`. Uses glob patterns for flexible matching. - -```json title="openscience.json" -{ - "agent": { - "orchestrator": { - "mode": "primary", - "permission": { - "task": { - "*": "deny", - "orchestrator-*": "allow", - "code-reviewer": "ask" - } - } - } - } -} -``` - -When set to `deny`, the subagent is removed from the Task tool description entirely, so the model won't attempt to invoke it. - -:::tip -Rules are evaluated in order, and the **last matching rule wins**. In the example above, `orchestrator-planner` matches both `*` (deny) and `orchestrator-*` (allow), but since `orchestrator-*` comes after `*`, the result is `allow`. -::: - -:::tip -Users can always invoke any subagent directly via the `@` autocomplete menu, even if the agent's task permissions would deny it. -::: - ---- - -### Additional - -Any other options you specify in your agent configuration will be **passed through directly** to the provider as model options. This allows you to use provider-specific features and parameters. - -For example, with OpenAI's reasoning models, you can control the reasoning effort: - -```json title="openscience.json" {6,7} -{ - "agent": { - "deep-thinker": { - "description": "Agent that uses high reasoning effort for complex problems", - "model": "openai/gpt-5", - "reasoningEffort": "high", - "textVerbosity": "low" - } - } -} -``` - -These additional options are model and provider-specific. Check your provider's documentation for available parameters. - -:::tip -Run `openscience models` to see a list of the available models. -::: - ---- - -## Create agents - -You can create new agents using the following command: - -```bash -openscience agent create -``` - -This interactive command will: - -1. Ask where to save the agent; global or project-specific. -2. Description of what the agent should do. -3. Generate an appropriate system prompt and identifier. -4. Let you select which tools the agent can access. -5. Finally, create a markdown file with the agent configuration. - ---- - -## Use cases - -Here are some common use cases for different agents. - -- **Research agent**: Full research and development work with all tools enabled -- **Plan agent**: Analysis and planning without making changes -- **Review agent**: Code review with read-only access plus documentation tools -- **Debug agent**: Focused on investigation with bash and read tools enabled -- **Docs agent**: Documentation writing with file operations but no system commands - ---- - -## Examples - -Here are some example agents you might find useful. - -:::tip -Do you have an agent you'd like to share? [Submit a PR](https://github.com/synthetic-sciences/OpenScience). -::: - ---- - -### Documentation agent - -```markdown title="~/.config/openscience/agents/docs-writer.md" ---- -description: Writes and maintains project documentation -mode: subagent -tools: - bash: false ---- - -You are a technical writer. Create clear, comprehensive documentation. - -Focus on: - -- Clear explanations -- Proper structure -- Code examples -- User-friendly language -``` - ---- - -### Security auditor - -```markdown title="~/.config/openscience/agents/security-auditor.md" ---- -description: Performs security audits and identifies vulnerabilities -mode: subagent -tools: - write: false - edit: false ---- - -You are a security expert. Focus on identifying potential security issues. - -Look for: - -- Input validation vulnerabilities -- Authentication and authorization flaws -- Data exposure risks -- Dependency vulnerabilities -- Configuration security issues -``` diff --git a/frontend/docs/src/content/docs/atlas.mdx b/frontend/docs/src/content/docs/atlas.mdx deleted file mode 100644 index 110d332..0000000 --- a/frontend/docs/src/content/docs/atlas.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Atlas -description: Synthetic Sciences' managed platform for OpenScience. ---- - -import config from "../../../config.mjs" -export const email = `mailto:${config.email}` - -Atlas is Synthetic Sciences' managed platform for OpenScience. It gives you: - -- **Curated models**: a tested set of frontier models, served through the managed `synsci` provider and billed from a prepaid wallet. -- **Research graph**: your sessions, runs, and findings organized into a durable research map. -- **Cloud compute**: managed GPU compute for training jobs and experiment runs. - -:::note -Atlas is **completely optional**. Bring-your-own-key (BYOK) is free, first-class, and needs no account. Configure your own provider API keys and OpenScience works fully without Atlas. -::: - ---- - -## Sign in - -Authenticate the CLI with: - -```bash -openscience connect login -``` - -This opens your browser to approve the device; the CLI then stores a long-lived API key. On headless or CI machines, create a key in the dashboard and pass it directly: - -```bash -openscience connect login --key thk_... -``` - -Manage your devices, API keys, and billing at [app.syntheticsciences.ai](https://app.syntheticsciences.ai/cli). - -You can check the connection at any time: - -```bash -openscience connect status -``` - ---- - -## Models - -Managed models are served through the `synsci` provider. The [model ID](/docs/models) in your OpenScience config uses the format `synsci/`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "model": "synsci/gpt-5-nano" -} -``` - -Run `/models` in the workspace to see the curated list. - ---- - -## Billing - -Atlas is billed from a prepaid wallet. Only **managed** calls, meaning requests running on Atlas-issued credentials, draw from the wallet. Calls made with your own API keys (BYOK) or a first-party OAuth subscription (Claude Pro/Max, ChatGPT, GitHub Copilot) cost the wallet nothing and are never blocked by it. - -If your balance can't cover a managed call, the session halts with an insufficient-credits message. Top up in the dashboard's Plan tab, or switch back to your own keys. - -You can also pin the spend mode explicitly in your config: - -```json title="openscience.json" -{ - "billing": { - "llm": "byok", - "compute": "byok" - } -} -``` - -- `llm`: `"managed"` bills LLM calls to your wallet; `"byok"` always runs them on your own keys or subscriptions. -- `compute`: the same toggle for cloud compute. Defaults to `"byok"`. - ---- - -## BYOK - -You don't need an Atlas account to use OpenScience. Configure any [provider](/docs/providers) with your own API key and all usage is billed by that provider directly, never by Synthetic Sciences. - -Contact us if you have any questions. diff --git a/frontend/docs/src/content/docs/cli.mdx b/frontend/docs/src/content/docs/cli.mdx deleted file mode 100644 index 75792c5..0000000 --- a/frontend/docs/src/content/docs/cli.mdx +++ /dev/null @@ -1,570 +0,0 @@ ---- -title: CLI -description: OpenScience CLI options and commands. ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components" - -The OpenScience CLI opens the [workspace](/docs/web) in your browser when run without any arguments. - -```bash -openscience -``` - -It also accepts commands as documented on this page. This lets you interact with OpenScience programmatically. - -```bash -openscience run "Explain how closures work in JavaScript" -``` - ---- - -### workspace - -Open the OpenScience workspace in your browser. - -```bash -openscience [project] -``` - -#### Flags - -| Flag | Short | Description | -| ------------ | ----- | ------------------------------------------ | -| `--continue` | `-c` | Continue the last session | -| `--session` | `-s` | Session ID to continue | -| `--prompt` | | Prompt to use | -| `--model` | `-m` | Model to use in the form of provider/model | -| `--agent` | | Agent to use | -| `--port` | | Port to listen on | -| `--hostname` | | Hostname to listen on | - ---- - -## Commands - -The OpenScience CLI also has the following commands. - ---- - -### agent - -Manage agents for OpenScience. - -```bash -openscience agent [command] -``` - ---- - -#### create - -Create a new agent with custom configuration. - -```bash -openscience agent create -``` - -This command will guide you through creating a new agent with a custom system prompt and tool configuration. - ---- - -#### list - -List all available agents. - -```bash -openscience agent list -``` - ---- - -### auth - -Command to manage credentials and login for providers. - -```bash -openscience auth [command] -``` - ---- - -#### login - -OpenScience is powered by the provider list at [Models.dev](https://models.dev), so you can use `openscience auth login` to configure API keys for any provider you'd like to use. This is stored in `~/.local/share/openscience/auth.json`. - -```bash -openscience auth login -``` - -When OpenScience starts up it loads the providers from the credentials file. And if there are any keys defined in your environments or a `.env` file in your project. - ---- - -#### list - -Lists all the authenticated providers as stored in the credentials file. - -```bash -openscience auth list -``` - -Or the short version. - -```bash -openscience auth ls -``` - ---- - -#### logout - -Logs you out of a provider by clearing it from the credentials file. - -```bash -openscience auth logout -``` - ---- - -### github - -Manage the GitHub agent for repository automation. - -```bash -openscience github [command] -``` - ---- - -#### install - -Install the GitHub agent in your repository. - -```bash -openscience github install -``` - -This sets up the necessary GitHub Actions workflow and guides you through the configuration process. [Learn more](/docs/github). - ---- - -#### run - -Run the GitHub agent. This is typically used in GitHub Actions. - -```bash -openscience github run -``` - -##### Flags - -| Flag | Description | -| --------- | -------------------------------------- | -| `--event` | GitHub mock event to run the agent for | -| `--token` | GitHub personal access token | - ---- - -### mcp - -Manage Model Context Protocol servers. - -```bash -openscience mcp [command] -``` - ---- - -#### add - -Add an MCP server to your configuration. - -```bash -openscience mcp add -``` - -This command will guide you through adding either a local or remote MCP server. - ---- - -#### list - -List all configured MCP servers and their connection status. - -```bash -openscience mcp list -``` - -Or use the short version. - -```bash -openscience mcp ls -``` - ---- - -#### auth - -Authenticate with an OAuth-enabled MCP server. - -```bash -openscience mcp auth [name] -``` - -If you don't provide a server name, you'll be prompted to select from available OAuth-capable servers. - -You can also list OAuth-capable servers and their authentication status. - -```bash -openscience mcp auth list -``` - -Or use the short version. - -```bash -openscience mcp auth ls -``` - ---- - -#### logout - -Remove OAuth credentials for an MCP server. - -```bash -openscience mcp logout [name] -``` - ---- - -#### debug - -Debug OAuth connection issues for an MCP server. - -```bash -openscience mcp debug -``` - ---- - -### models - -List all available models from configured providers. - -```bash -openscience models [provider] -``` - -This command displays all models available across your configured providers in the format `provider/model`. - -This is useful for figuring out the exact model name to use in [your config](/docs/config/). - -You can optionally pass a provider ID to filter models by that provider. - -```bash -openscience models anthropic -``` - -#### Flags - -| Flag | Description | -| ----------- | ------------------------------------------------------------ | -| `--refresh` | Refresh the models cache from models.dev | -| `--verbose` | Use more verbose model output (includes metadata like costs) | - -Use the `--refresh` flag to update the cached model list. This is useful when new models have been added to a provider and you want to see them in OpenScience. - -```bash -openscience models --refresh -``` - ---- - -### run - -Run openscience in non-interactive mode by passing a prompt directly. - -```bash -openscience run [message..] -``` - -This is useful for scripting, automation, or when you want a quick answer without opening the workspace. For example. - -```bash "openscience run" -openscience run Explain the use of context in Go -``` - -You can also attach to a running `openscience serve` instance to avoid MCP server cold boot times on every run: - -```bash -# Start a headless server in one terminal -openscience serve - -# In another terminal, run commands that attach to it -openscience run --attach http://localhost:4096 "Explain async/await in JavaScript" -``` - -#### Flags - -| Flag | Short | Description | -| ------------ | ----- | ------------------------------------------------------------------ | -| `--command` | | The command to run, use message for args | -| `--continue` | `-c` | Continue the last session | -| `--session` | `-s` | Session ID to continue | -| `--share` | | Share the session | -| `--model` | `-m` | Model to use in the form of provider/model | -| `--agent` | | Agent to use | -| `--file` | `-f` | File(s) to attach to message | -| `--format` | | Format: default (formatted) or json (raw JSON events) | -| `--title` | | Title for the session (uses truncated prompt if no value provided) | -| `--attach` | | Attach to a running openscience server (e.g., http://localhost:4096) | -| `--port` | | Port for the local server (defaults to random port) | - ---- - -### serve - -Start a headless OpenScience server for API access. Check out the [server docs](/docs/server) for the full HTTP interface. - -```bash -openscience serve -``` - -This starts an HTTP server that provides API access to openscience functionality without a browser interface. Set `OPENSCIENCE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `openscience`). - -#### Flags - -| Flag | Description | -| ------------ | ------------------------------------------ | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | -| `--mdns` | Enable mDNS discovery | -| `--cors` | Additional browser origin(s) to allow CORS | - ---- - -### session - -Manage OpenScience sessions. - -```bash -openscience session [command] -``` - ---- - -#### list - -List all OpenScience sessions. - -```bash -openscience session list -``` - -##### Flags - -| Flag | Short | Description | -| ------------- | ----- | ------------------------------------ | -| `--max-count` | `-n` | Limit to N most recent sessions | -| `--format` | | Output format: table or json (table) | - ---- - -### stats - -Show token usage and cost statistics for your OpenScience sessions. - -```bash -openscience stats -``` - -#### Flags - -| Flag | Description | -| ----------- | --------------------------------------------------------------------------- | -| `--days` | Show stats for the last N days (all time) | -| `--tools` | Number of tools to show (all) | -| `--models` | Show model usage breakdown (hidden by default). Pass a number to show top N | -| `--project` | Filter by project (all projects, empty string: current project) | - ---- - -### export - -Export session data as JSON. - -```bash -openscience export [sessionID] -``` - -If you don't provide a session ID, you'll be prompted to select from available sessions. - ---- - -### import - -Import session data from a JSON file or OpenScience share URL. - -```bash -openscience import -``` - -You can import from a local file or an OpenScience share URL. - -```bash -openscience import session.json -openscience import https://syntheticsciences.ai/s/abc123 -``` - ---- - -### web - -Start a headless OpenScience server with a web interface. - -```bash -openscience web -``` - -This starts an HTTP server and opens a web browser to access OpenScience through a web interface. Set `OPENSCIENCE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `openscience`). - -#### Flags - -| Flag | Description | -| ------------ | ------------------------------------------ | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | -| `--mdns` | Enable mDNS discovery | -| `--cors` | Additional browser origin(s) to allow CORS | - ---- - -### acp - -Start an ACP (Agent Client Protocol) server. - -```bash -openscience acp -``` - -This command starts an ACP server that communicates via stdin/stdout using nd-JSON. - -#### Flags - -| Flag | Description | -| ------------ | --------------------- | -| `--cwd` | Working directory | -| `--port` | Port to listen on | -| `--hostname` | Hostname to listen on | - ---- - -### uninstall - -Uninstall OpenScience and remove all related files. - -```bash -openscience uninstall -``` - -#### Flags - -| Flag | Short | Description | -| --------------- | ----- | ------------------------------------------- | -| `--keep-config` | `-c` | Keep configuration files | -| `--keep-data` | `-d` | Keep session data and snapshots | -| `--dry-run` | | Show what would be removed without removing | -| `--force` | `-f` | Skip confirmation prompts | - ---- - -### upgrade - -Updates openscience to the latest version or a specific version. - -```bash -openscience upgrade [target] -``` - -To upgrade to the latest version. - -```bash -openscience upgrade -``` - -To upgrade to a specific version. - -```bash -openscience upgrade v0.1.48 -``` - -#### Flags - -| Flag | Short | Description | -| ---------- | ----- | ----------------------------------------------------------------- | -| `--method` | `-m` | The installation method that was used; curl, npm, pnpm, bun, brew | - ---- - -## Global flags - -The openscience CLI takes the following global flags. - -| Flag | Short | Description | -| -------------- | ----- | ------------------------------------ | -| `--help` | `-h` | Display help | -| `--version` | `-v` | Print version number | -| `--print-logs` | | Print logs to stderr | -| `--log-level` | | Log level (DEBUG, INFO, WARN, ERROR) | - ---- - -## Environment variables - -OpenScience can be configured using environment variables. - -| Variable | Type | Description | -| ------------------------------------- | ------- | ------------------------------------------------- | -| `OPENSCIENCE_AUTO_SHARE` | boolean | Automatically share sessions | -| `OPENSCIENCE_GIT_BASH_PATH` | string | Path to Git Bash executable on Windows | -| `OPENSCIENCE_CONFIG` | string | Path to config file | -| `OPENSCIENCE_CONFIG_DIR` | string | Path to config directory | -| `OPENSCIENCE_CONFIG_CONTENT` | string | Inline json config content | -| `OPENSCIENCE_DISABLE_AUTOUPDATE` | boolean | Disable automatic update checks | -| `OPENSCIENCE_DISABLE_PRUNE` | boolean | Disable pruning of old data | -| `OPENSCIENCE_DISABLE_TERMINAL_TITLE` | boolean | Disable automatic terminal title updates | -| `OPENSCIENCE_PERMISSION` | string | Inlined json permissions config | -| `OPENSCIENCE_DISABLE_DEFAULT_PLUGINS` | boolean | Disable default plugins | -| `OPENSCIENCE_DISABLE_LSP_DOWNLOAD` | boolean | Disable automatic LSP server downloads | -| `OPENSCIENCE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models | -| `OPENSCIENCE_DISABLE_AUTOCOMPACT` | boolean | Disable automatic context compaction | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE` | boolean | Disable reading from `.claude` (prompt + skills) | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Disable reading `~/.claude/CLAUDE.md` | -| `OPENSCIENCE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Disable loading `.claude/skills` | -| `OPENSCIENCE_CLIENT` | string | Client identifier (defaults to `cli`) | -| `OPENSCIENCE_ENABLE_EXA` | boolean | Enable Exa web search tools | -| `OPENSCIENCE_SERVER_PASSWORD` | string | Enable basic auth for `serve`/`web` | -| `OPENSCIENCE_SERVER_USERNAME` | string | Override basic auth username (default `openscience`) | - ---- - -### Experimental - -These environment variables enable experimental features that may change or be removed. - -| Variable | Type | Description | -| ----------------------------------------------- | ------- | --------------------------------------- | -| `OPENSCIENCE_EXPERIMENTAL` | boolean | Enable all experimental features | -| `OPENSCIENCE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Enable icon discovery | -| `OPENSCIENCE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Disable copy on select | -| `OPENSCIENCE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Default timeout for bash commands in ms | -| `OPENSCIENCE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Max output tokens for LLM responses | -| `OPENSCIENCE_EXPERIMENTAL_FILEWATCHER` | boolean | Enable file watcher for entire dir | -| `OPENSCIENCE_EXPERIMENTAL_OXFMT` | boolean | Enable oxfmt formatter | -| `OPENSCIENCE_EXPERIMENTAL_LSP_TOOL` | boolean | Enable experimental LSP tool | -| `OPENSCIENCE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Disable file watcher | -| `OPENSCIENCE_EXPERIMENTAL_EXA` | boolean | Enable experimental Exa features | -| `OPENSCIENCE_EXPERIMENTAL_LSP_TY` | boolean | Enable experimental LSP type checking | -| `OPENSCIENCE_EXPERIMENTAL_MARKDOWN` | boolean | Enable experimental markdown features | -| `OPENSCIENCE_EXPERIMENTAL_PLAN_MODE` | boolean | Enable plan mode | diff --git a/frontend/docs/src/content/docs/commands.mdx b/frontend/docs/src/content/docs/commands.mdx deleted file mode 100644 index efc1091..0000000 --- a/frontend/docs/src/content/docs/commands.mdx +++ /dev/null @@ -1,323 +0,0 @@ ---- -title: Commands -description: Create custom commands for repetitive tasks. ---- - -Custom commands let you specify a prompt you want to run when that command is executed in the workspace. - -```bash frame="none" -/my-command -``` - -Custom commands are in addition to the built-in commands like `/init`, `/undo`, `/redo`, `/share`, `/help`. [Learn more](/docs/web). - ---- - -## Create command files - -Create markdown files in the `commands/` directory to define custom commands. - -Create `.openscience/commands/test.md`: - -```md title=".openscience/commands/test.md" ---- -description: Run tests with coverage -agent: research -model: anthropic/claude-3-5-sonnet-20241022 ---- - -Run the full test suite with coverage report and show any failures. -Focus on the failing tests and suggest fixes. -``` - -The frontmatter defines command properties. The content becomes the template. - -Use the command by typing `/` followed by the command name. - -```bash frame="none" -"/test" -``` - ---- - -## Configure - -You can add custom commands through the OpenScience config or by creating markdown files in the `commands/` directory. - ---- - -### JSON - -Use the `command` option in your OpenScience [config](/docs/config): - -```json title="openscience.jsonc" {4-12} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "command": { - // This becomes the name of the command - "test": { - // This is the prompt that will be sent to the LLM - "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", - // This is shown as the description in the workspace - "description": "Run tests with coverage", - "agent": "research", - "model": "anthropic/claude-3-5-sonnet-20241022" - } - } -} -``` - -Now you can run this command in the workspace: - -```bash frame="none" -/test -``` - ---- - -### Markdown - -You can also define commands using markdown files. Place them in: - -- Global: `~/.config/openscience/commands/` -- Per-project: `.openscience/commands/` - -```markdown title="~/.config/openscience/commands/test.md" ---- -description: Run tests with coverage -agent: research -model: anthropic/claude-3-5-sonnet-20241022 ---- - -Run the full test suite with coverage report and show any failures. -Focus on the failing tests and suggest fixes. -``` - -The markdown file name becomes the command name. For example, `test.md` lets -you run: - -```bash frame="none" -/test -``` - ---- - -## Prompt config - -The prompts for the custom commands support several special placeholders and syntax. - ---- - -### Arguments - -Pass arguments to commands using the `$ARGUMENTS` placeholder. - -```md title=".openscience/commands/component.md" ---- -description: Create a new component ---- - -Create a new React component named $ARGUMENTS with TypeScript support. -Include proper typing and basic structure. -``` - -Run the command with arguments: - -```bash frame="none" -/component Button -``` - -And `$ARGUMENTS` will be replaced with `Button`. - -You can also access individual arguments using positional parameters: - -- `$1`: First argument -- `$2`: Second argument -- `$3`: Third argument -- And so on... - -For example: - -```md title=".openscience/commands/create-file.md" ---- -description: Create a new file with content ---- - -Create a file named $1 in the directory $2 -with the following content: $3 -``` - -Run the command: - -```bash frame="none" -/create-file config.json src "{ \"key\": \"value\" }" -``` - -This replaces: - -- `$1` with `config.json` -- `$2` with `src` -- `$3` with `{ "key": "value" }` - ---- - -### Shell output - -Use _!`command`_ to inject bash command output into your prompt. - -For example, to create a custom command that analyzes test coverage: - -```md title=".openscience/commands/analyze-coverage.md" ---- -description: Analyze test coverage ---- - -Here are the current test results: -!`npm test` - -Based on these results, suggest improvements to increase coverage. -``` - -Or to review recent changes: - -```md title=".openscience/commands/review-changes.md" ---- -description: Review recent changes ---- - -Recent git commits: -!`git log --oneline -10` - -Review these changes and suggest any improvements. -``` - -Commands run in your project's root directory and their output becomes part of the prompt. - ---- - -### File references - -Include files in your command using `@` followed by the filename. - -```md title=".openscience/commands/review-component.md" ---- -description: Review component ---- - -Review the component in @src/components/Button.tsx. -Check for performance issues and suggest improvements. -``` - -The file content gets included in the prompt automatically. - ---- - -## Options - -Let's look at the configuration options in detail. - ---- - -### Template - -The `template` option defines the prompt that will be sent to the LLM when the command is executed. - -```json title="openscience.json" -{ - "command": { - "test": { - "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes." - } - } -} -``` - -This is a **required** config option. - ---- - -### Description - -Use the `description` option to provide a brief description of what the command does. - -```json title="openscience.json" -{ - "command": { - "test": { - "description": "Run tests with coverage" - } - } -} -``` - -This is shown as the description in the workspace when you type in the command. - ---- - -### Agent - -Use the `agent` config to optionally specify which [agent](/docs/agents) should execute this command. -If this is a [subagent](/docs/agents/#subagents) the command will trigger a subagent invocation by default. -To disable this behavior, set `subtask` to `false`. - -```json title="openscience.json" -{ - "command": { - "review": { - "agent": "plan" - } - } -} -``` - -This is an **optional** config option. If not specified, defaults to your current agent. - ---- - -### Subtask - -Use the `subtask` boolean to force the command to trigger a [subagent](/docs/agents/#subagents) invocation. -This is useful if you want the command to not pollute your primary context and will **force** the agent to act as a subagent, -even if `mode` is set to `primary` on the [agent](/docs/agents) configuration. - -```json title="openscience.json" -{ - "command": { - "analyze": { - "subtask": true - } - } -} -``` - -This is an **optional** config option. - ---- - -### Model - -Use the `model` config to override the default model for this command. - -```json title="openscience.json" -{ - "command": { - "analyze": { - "model": "anthropic/claude-3-5-sonnet-20241022" - } - } -} -``` - -This is an **optional** config option. - ---- - -## Built-in - -OpenScience includes several built-in commands like `/init`, `/undo`, `/redo`, `/share`, `/help`; [learn more](/docs/web). - -:::note -Custom commands can override built-in commands. -::: - -If you define a custom command with the same name, it will override the built-in command. diff --git a/frontend/docs/src/content/docs/config.mdx b/frontend/docs/src/content/docs/config.mdx deleted file mode 100644 index b378dc2..0000000 --- a/frontend/docs/src/content/docs/config.mdx +++ /dev/null @@ -1,641 +0,0 @@ ---- -title: Config -description: Using the OpenScience JSON config. ---- - -You can configure OpenScience using a JSON config file. - ---- - -## Format - -OpenScience supports both **JSON** and **JSONC** (JSON with Comments) formats. - -```jsonc title="openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - // Theme configuration - "theme": "openscience", - "model": "anthropic/claude-sonnet-4-5", - "autoupdate": true, -} -``` - ---- - -## Locations - -You can place your config in a couple of different locations and they have a -different order of precedence. - -:::note -Configuration files are **merged together**, not replaced. -::: - -Settings from the following config locations are combined. Later configs override earlier ones only for conflicting keys. Non-conflicting settings from all configs are preserved. - -For example, if your global config sets `theme: "openscience"` and `autoupdate: true`, and your project config sets `model: "anthropic/claude-sonnet-4-5"`, the final configuration will include all three settings. - ---- - -### Precedence order - -Config sources are loaded in this order (later sources override earlier ones): - -1. Remote config (from `.well-known/openscience`): organizational defaults -2. Global config (`~/.config/openscience/openscience.json`): user preferences -3. Custom config (`OPENSCIENCE_CONFIG` env var): custom overrides -4. Project config (`openscience.json` in project): project-specific settings -5. `.openscience` directories: agents, commands, plugins -6. Inline config (`OPENSCIENCE_CONFIG_CONTENT` env var): runtime overrides - -This means project configs can override global defaults, and global configs can override remote organizational defaults. - -:::note -The `.openscience` and `~/.config/openscience` directories use **plural names** for subdirectories: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, and `themes/`. Singular names (e.g., `agent/`) are also supported for backwards compatibility. -::: - ---- - -### Remote - -Organizations can provide default configuration via the `.well-known/openscience` endpoint. This is fetched automatically when you authenticate with a provider that supports it. - -Remote config is loaded first, serving as the base layer. All other config sources (global, project) can override these defaults. - -For example, if your organization provides MCP servers that are disabled by default: - -```json title="Remote config from .well-known/openscience" -{ - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": false - } - } -} -``` - -You can enable specific servers in your local config: - -```json title="openscience.json" -{ - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - ---- - -### Global - -Place your global OpenScience config in `~/.config/openscience/openscience.json`. Use global config for user-wide preferences like themes, providers, or your default model. - -Global config overrides remote organizational defaults. - ---- - -### Per project - -Add `openscience.json` in your project root. Project config has the highest precedence among standard config files. It overrides both global and remote configs. - -:::tip -Place project specific config in the root of your project. -::: - -When OpenScience starts up, it looks for a config file in the current directory or traverse up to the nearest Git directory. - -This is also safe to be checked into Git and uses the same schema as the global one. - ---- - -### Custom path - -Specify a custom config file path using the `OPENSCIENCE_CONFIG` environment variable. - -```bash -export OPENSCIENCE_CONFIG=/path/to/my/custom-config.json -openscience run "Hello world" -``` - -Custom config is loaded between global and project configs in the precedence order. - ---- - -### Custom directory - -Specify a custom config directory using the `OPENSCIENCE_CONFIG_DIR` -environment variable. This directory will be searched for agents, commands, -modes, and plugins just like the standard `.openscience` directory, and should -follow the same structure. - -```bash -export OPENSCIENCE_CONFIG_DIR=/path/to/my/config-directory -openscience run "Hello world" -``` - -The custom directory is loaded after the global config and `.openscience` directories, so it **can override** their settings. - ---- - -## Schema - -The config file has a schema that's defined in [**`syntheticsciences.ai/config.json`**](https://syntheticsciences.ai/config.json). - -Your editor should be able to validate and autocomplete based on the schema. - ---- - -### Server - -You can configure server settings for the `openscience serve` and `openscience web` commands through the `server` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "server": { - "port": 4096, - "hostname": "0.0.0.0", - "mdns": true, - "cors": ["http://localhost:5173"] - } -} -``` - -Available options: - -- `port`: Port to listen on. -- `hostname`: Hostname to listen on. When `mdns` is enabled and no hostname is set, defaults to `0.0.0.0`. -- `mdns`: Enable mDNS service discovery. This lets other devices on the network discover your OpenScience server. -- `cors`: Additional origins to allow for CORS when using the HTTP server from a browser-based client. Values must be full origins (scheme + host + optional port), eg `https://app.example.com`. - -[Learn more about the server here](/docs/server). - ---- - -### Tools - -You can manage the tools an LLM can use through the `tools` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "tools": { - "write": false, - "bash": false - } -} -``` - -[Learn more about tools here](/docs/tools). - ---- - -### Models - -You can configure the providers and models you want to use in your OpenScience config through the `provider`, `model` and `small_model` options. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": {}, - "model": "anthropic/claude-sonnet-4-5", - "small_model": "anthropic/claude-haiku-4-5" -} -``` - -The `small_model` option configures a separate model for lightweight tasks like title generation. By default, OpenScience tries to use a cheaper model if one is available from your provider, otherwise it falls back to your main model. - -Provider options can include `timeout` and `setCacheKey`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "anthropic": { - "options": { - "timeout": 600000, - "setCacheKey": true - } - } - } -} -``` - -- `timeout`: Request timeout in milliseconds (default: 300000). Set to `false` to disable. -- `setCacheKey`: Ensure a cache key is always set for the designated provider. - -You can also configure [local models](/docs/models#local). [Learn more](/docs/models). - ---- - -#### Provider-specific options - -Some providers support additional configuration options beyond the generic `timeout` and `apiKey` settings. - -##### Amazon Bedrock - -Amazon Bedrock supports AWS-specific configuration: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "my-aws-profile", - "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" - } - } - } -} -``` - -- `region`: AWS region for Bedrock (defaults to `AWS_REGION` env var or `us-east-1`) -- `profile`: AWS named profile from `~/.aws/credentials` (defaults to `AWS_PROFILE` env var) -- `endpoint`: Custom endpoint URL for VPC endpoints. This is an alias for the generic `baseURL` option using AWS-specific terminology. If both are specified, `endpoint` takes precedence. - -:::note -Bearer tokens (`AWS_BEARER_TOKEN_BEDROCK` or `/connect`) take precedence over profile-based authentication. See [authentication precedence](/docs/providers#authentication-precedence) for details. -::: - -[Learn more about Amazon Bedrock configuration](/docs/providers#amazon-bedrock). - ---- - -### Themes - -You can configure the theme you want to use in your OpenScience config through the `theme` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "theme": "" -} -``` - -[Learn more here](/docs/themes). - ---- - -### Agents - -You can configure specialized agents for specific tasks through the `agent` option. - -```jsonc title="openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "agent": { - "code-reviewer": { - "description": "Reviews code for best practices and potential issues", - "model": "anthropic/claude-sonnet-4-5", - "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", - "tools": { - // Disable file modification tools for review-only agent - "write": false, - "edit": false, - }, - }, - }, -} -``` - -You can also define agents using markdown files in `~/.config/openscience/agents/` or `.openscience/agents/`. [Learn more here](/docs/agents). - ---- - -### Default agent - -You can set the default agent using the `default_agent` option. This determines which agent is used when none is explicitly specified. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "default_agent": "plan" -} -``` - -The default agent must be a primary agent (not a subagent). This can be a built-in agent like `"research"`, `"biology"`, `"physics"`, `"ml"`, or `"plan"`, or a [custom agent](/docs/agents) you've defined. If the specified agent doesn't exist or is a subagent, OpenScience will fall back to `"research"` with a warning. - -This setting applies across all interfaces: the browser workspace, the CLI (`openscience run`), and the GitHub Action. - ---- - -### Sharing - -You can configure the [share](/docs/share) feature through the `share` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "share": "manual" -} -``` - -This takes: - -- `"manual"`: Allow manual sharing via commands (default) -- `"auto"`: Automatically share new conversations -- `"disabled"`: Disable sharing entirely - -By default, sharing is set to manual mode where you need to explicitly share conversations using the `/share` command. - ---- - -### Commands - -You can configure custom commands for repetitive tasks through the `command` option. - -```jsonc title="openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "command": { - "test": { - "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", - "description": "Run tests with coverage", - "agent": "research", - "model": "anthropic/claude-haiku-4-5", - }, - "component": { - "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", - "description": "Create a new component", - }, - }, -} -``` - -You can also define commands using markdown files in `~/.config/openscience/commands/` or `.openscience/commands/`. [Learn more here](/docs/commands). - ---- - -### Autoupdate - -OpenScience will automatically download any new updates when it starts up. You can disable this with the `autoupdate` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "autoupdate": false -} -``` - -If you don't want updates but want to be notified when a new version is available, set `autoupdate` to `"notify"`. -Notice that this only works if it was not installed using a package manager such as Homebrew. - ---- - -### Formatters - -You can configure code formatters through the `formatter` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "formatter": { - "prettier": { - "disabled": true - }, - "custom-prettier": { - "command": ["npx", "prettier", "--write", "$FILE"], - "environment": { - "NODE_ENV": "development" - }, - "extensions": [".js", ".ts", ".jsx", ".tsx"] - } - } -} -``` - -[Learn more about formatters here](/docs/formatters). - ---- - -### Permissions - -By default, openscience **allows all operations** without requiring explicit approval. You can change this using the `permission` option. - -For example, to ensure that the `edit` and `bash` tools require user approval: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "ask", - "bash": "ask" - } -} -``` - -[Learn more about permissions here](/docs/permissions). - ---- - -### Compaction - -You can control context compaction behavior through the `compaction` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "compaction": { - "auto": true, - "prune": true - } -} -``` - -- `auto`: Automatically compact the session when context is full (default: `true`). -- `prune`: Remove old tool outputs to save tokens (default: `true`). - ---- - -### Watcher - -You can configure file watcher ignore patterns through the `watcher` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "watcher": { - "ignore": ["node_modules/**", "dist/**", ".git/**"] - } -} -``` - -Patterns follow glob syntax. Use this to exclude noisy directories from file watching. - ---- - -### MCP servers - -You can configure MCP servers you want to use through the `mcp` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": {} -} -``` - -[Learn more here](/docs/mcp-servers). - ---- - -### Plugins - -[Plugins](/docs/plugins) extend OpenScience with custom tools, hooks, and integrations. - -Place plugin files in `.openscience/plugins/` or `~/.config/openscience/plugins/`. You can also load plugins from npm through the `plugin` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "plugin": ["openscience-helicone-session", "@my-org/custom-plugin"] -} -``` - -[Learn more here](/docs/plugins). - ---- - -### Instructions - -You can configure the instructions for the model you're using through the `instructions` option. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] -} -``` - -This takes an array of paths and glob patterns to instruction files. [Learn more -about rules here](/docs/rules). - ---- - -### Disabled providers - -You can disable providers that are loaded automatically through the `disabled_providers` option. This is useful when you want to prevent certain providers from being loaded even if their credentials are available. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "disabled_providers": ["openai", "gemini"] -} -``` - -:::note -The `disabled_providers` takes priority over `enabled_providers`. -::: - -The `disabled_providers` option accepts an array of provider IDs. When a provider is disabled: - -- It won't be loaded even if environment variables are set. -- It won't be loaded even if API keys are configured through the `/connect` command. -- The provider's models won't appear in the model selection list. - ---- - -### Enabled providers - -You can specify an allowlist of providers through the `enabled_providers` option. When set, only the specified providers will be enabled and all others will be ignored. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "enabled_providers": ["anthropic", "openai"] -} -``` - -This is useful when you want to restrict OpenScience to only use specific providers rather than disabling them one by one. - -:::note -The `disabled_providers` takes priority over `enabled_providers`. -::: - -If a provider appears in both `enabled_providers` and `disabled_providers`, the `disabled_providers` takes priority for backwards compatibility. - ---- - -### Experimental - -The `experimental` key contains options that are under active development. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "experimental": {} -} -``` - -:::caution -Experimental options are not stable. They may change or be removed without notice. -::: - ---- - -## Variables - -You can use variable substitution in your config files to reference environment variables and file contents. - ---- - -### Env vars - -Use `{env:VARIABLE_NAME}` to substitute environment variables: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "model": "{env:OPENSCIENCE_MODEL}", - "provider": { - "anthropic": { - "models": {}, - "options": { - "apiKey": "{env:ANTHROPIC_API_KEY}" - } - } - } -} -``` - -If the environment variable is not set, it will be replaced with an empty string. - ---- - -### Files - -Use `{file:path/to/file}` to substitute the contents of a file: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "instructions": ["./custom-instructions.md"], - "provider": { - "openai": { - "options": { - "apiKey": "{file:~/.secrets/openai-key}" - } - } - } -} -``` - -File paths can be: - -- Relative to the config file directory -- Or absolute paths starting with `/` or `~` - -These are useful for: - -- Keeping sensitive data like API keys in separate files. -- Including large instruction files without cluttering your config. -- Sharing common configuration snippets across multiple config files. diff --git a/frontend/docs/src/content/docs/custom-tools.mdx b/frontend/docs/src/content/docs/custom-tools.mdx deleted file mode 100644 index 17b4496..0000000 --- a/frontend/docs/src/content/docs/custom-tools.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Custom Tools -description: Create tools the LLM can call in OpenScience. ---- - -Custom tools are functions you create that the LLM can call during conversations. They work alongside OpenScience's [built-in tools](/docs/tools) like `read`, `write`, and `bash`. - ---- - -## Creating a tool - -Tools are defined as TypeScript or JavaScript files. The definition can invoke scripts written in any language, so TypeScript or JavaScript is only used for the tool definition itself. - ---- - -### Location - -They can be defined: - -- Locally by placing them in the `.openscience/tools/` directory of your project. -- Or globally, by placing them in `~/.config/openscience/tools/`. - ---- - -### Structure - -The easiest way to create tools is using the `tool()` helper which provides type-safety and validation. - -```ts title=".openscience/tools/database.ts" {1} -import { tool } from "@synsci/plugin" - -export default tool({ - description: "Query the project database", - args: { - query: tool.schema.string().describe("SQL query to execute"), - }, - async execute(args) { - // Your database logic here - return `Executed query: ${args.query}` - }, -}) -``` - -The filename becomes the tool name. The above creates a `database` tool. - ---- - -#### Multiple tools per file - -You can also export multiple tools from a single file. Each export becomes a separate tool named `_`: - -```ts title=".openscience/tools/math.ts" -import { tool } from "@synsci/plugin" - -export const add = tool({ - description: "Add two numbers", - args: { - a: tool.schema.number().describe("First number"), - b: tool.schema.number().describe("Second number"), - }, - async execute(args) { - return args.a + args.b - }, -}) - -export const multiply = tool({ - description: "Multiply two numbers", - args: { - a: tool.schema.number().describe("First number"), - b: tool.schema.number().describe("Second number"), - }, - async execute(args) { - return args.a * args.b - }, -}) -``` - -This creates two tools: `math_add` and `math_multiply`. - ---- - -### Arguments - -You can use `tool.schema`, which is just [Zod](https://zod.dev), to define argument types. - -```ts "tool.schema" -args: { - query: tool.schema.string().describe("SQL query to execute") -} -``` - -You can also import [Zod](https://zod.dev) directly and return a plain object: - -```ts {6} -import { z } from "zod" - -export default { - description: "Tool description", - args: { - param: z.string().describe("Parameter description"), - }, - async execute(args, context) { - // Tool implementation - return "result" - }, -} -``` - ---- - -### Context - -Tools receive context about the current session: - -```ts title=".openscience/tools/project.ts" {8} -import { tool } from "@synsci/plugin" - -export default tool({ - description: "Get project information", - args: {}, - async execute(args, context) { - // Access context information - const { agent, sessionID, messageID, directory, worktree } = context - return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` - }, -}) -``` - -Use `context.directory` for the session working directory. -Use `context.worktree` for the git worktree root. - ---- - -## Examples - -### Write a tool in Python - -You can write your tools in any language you want. Here's an example that adds two numbers using Python. - -First, create the tool as a Python script: - -```python title=".openscience/tools/add.py" -import sys - -a = int(sys.argv[1]) -b = int(sys.argv[2]) -print(a + b) -``` - -Then create the tool definition that invokes it: - -```ts title=".openscience/tools/python-add.ts" {10} -import { tool } from "@synsci/plugin" -import path from "path" - -export default tool({ - description: "Add two numbers using Python", - args: { - a: tool.schema.number().describe("First number"), - b: tool.schema.number().describe("Second number"), - }, - async execute(args, context) { - const script = path.join(context.worktree, ".openscience/tools/add.py") - const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text() - return result.trim() - }, -}) -``` - -Here we are using the [`Bun.$`](https://bun.com/docs/runtime/shell) utility to run the Python script. diff --git a/frontend/docs/src/content/docs/ecosystem.mdx b/frontend/docs/src/content/docs/ecosystem.mdx deleted file mode 100644 index 89f403f..0000000 --- a/frontend/docs/src/content/docs/ecosystem.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Ecosystem -description: Projects and integrations built with OpenScience. ---- - -A collection of community projects built on OpenScience. - -:::note -Want to add your OpenScience related project to this list? Submit a PR. -::: - -You can also check out [awesome-openscience](https://github.com/awesome-openscience/awesome-openscience) and [openscience.cafe](https://openscience.cafe), a community that aggregates the ecosystem and community. - ---- - -## Plugins - -| Name | Description | -| -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -| [openscience-daytona](https://github.com/jamesmurdza/daytona/tree/main/libs/openscience-plugin) | Automatically run OpenScience sessions in isolated Daytona sandboxes with git sync and live previews | -| [openscience-helicone-session](https://github.com/H2Shami/openscience-helicone-session) | Automatically inject Helicone session headers for request grouping | -| [openscience-type-inject](https://github.com/nick-vi/openscience-type-inject) | Auto-inject TypeScript/Svelte types into file reads with lookup tools | -| [openscience-openai-codex-auth](https://github.com/numman-ali/openscience-openai-codex-auth) | Use your ChatGPT Plus/Pro subscription instead of API credits | -| [openscience-gemini-auth](https://github.com/jenslys/openscience-gemini-auth) | Use your existing Gemini plan instead of API billing | -| [openscience-antigravity-auth](https://github.com/NoeFabris/openscience-antigravity-auth) | Use Antigravity's free models instead of API billing | -| [openscience-devcontainers](https://github.com/athal7/openscience-devcontainers) | Multi-branch devcontainer isolation with shallow clones and auto-assigned ports | -| [openscience-google-antigravity-auth](https://github.com/shekohex/openscience-google-antigravity-auth) | Google Antigravity OAuth plugin, with support for Google Search, and more reliable API handling | -| [openscience-dynamic-context-pruning](https://github.com/Tarquinen/openscience-dynamic-context-pruning) | Optimize token usage by pruning obsolete tool outputs | -| [openscience-websearch-cited](https://github.com/ghoulr/openscience-websearch-cited.git) | Add native websearch support for supported providers with Google grounded style | -| [openscience-pty](https://github.com/shekohex/openscience-pty.git) | Enables AI agents to run background processes in a PTY, send interactive input to them. | -| [openscience-shell-strategy](https://github.com/JRedeker/openscience-shell-strategy) | Instructions for non-interactive shell commands, prevents hangs from TTY-dependent operations | -| [openscience-wakatime](https://github.com/angristan/openscience-wakatime) | Track OpenScience usage with Wakatime | -| [openscience-md-table-formatter](https://github.com/franlol/openscience-md-table-formatter/tree/main) | Clean up markdown tables produced by LLMs | -| [openscience-morph-fast-apply](https://github.com/JRedeker/openscience-morph-fast-apply) | 10x faster code editing with Morph Fast Apply API and lazy edit markers | -| [oh-my-openscience](https://github.com/code-yeongyu/oh-my-openscience) | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible | -| [openscience-notificator](https://github.com/panta82/openscience-notificator) | Desktop notifications and sound alerts for OpenScience sessions | -| [openscience-notifier](https://github.com/mohak34/openscience-notifier) | Desktop notifications and sound alerts for permission, completion, and error events | -| [openscience-zellij-namer](https://github.com/24601/openscience-zellij-namer) | AI-powered automatic Zellij session naming based on OpenScience context | -| [openscience-skillful](https://github.com/zenobi-us/openscience-skillful) | Allow OpenScience agents to lazy load prompts on demand with skill discovery and injection | -| [openscience-supermemory](https://github.com/supermemoryai/openscience-supermemory) | Persistent memory across sessions using Supermemory | -| [@plannotator/openscience](https://github.com/backnotprop/plannotator/tree/main/apps/openscience-plugin) | Interactive plan review with visual annotation and private/offline sharing | -| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Extend OpenScience /commands into an orchestration system with granular flow control | -| [openscience-scheduler](https://github.com/different-ai/openscience-scheduler) | Schedule recurring jobs using launchd (Mac) or systemd (Linux) with cron syntax | -| [micode](https://github.com/vtemian/micode) | Structured Brainstorm → Plan → Implement workflow with session continuity | -| [octto](https://github.com/vtemian/octto) | Interactive browser UI for AI brainstorming with multi-question forms | -| [openscience-background-agents](https://github.com/kdcokenny/openscience-background-agents) | Claude Code-style background agents with async delegation and context persistence | -| [openscience-notify](https://github.com/kdcokenny/openscience-notify) | Native OS notifications for OpenScience, know when tasks complete | -| [openscience-workspace](https://github.com/kdcokenny/openscience-workspace) | Bundled multi-agent orchestration harness with 16 components, one install | -| [openscience-worktree](https://github.com/kdcokenny/openscience-worktree) | Zero-friction git worktrees for OpenScience | - ---- - -## Projects - -| Name | Description | -| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | -| [kimaki](https://github.com/remorses/kimaki) | Discord bot to control OpenScience sessions, built on the SDK | -| [openscience.nvim](https://github.com/NickvanDyke/openscience.nvim) | Neovim plugin for editor-aware prompts, built on the API | -| [portal](https://github.com/hosenur/portal) | Mobile-first web UI for OpenScience over Tailscale/VPN | -| [openscience plugin template](https://github.com/zenobi-us/openscience-plugin-template/) | Template for building OpenScience plugins | -| [openscience.nvim](https://github.com/sudo-tee/openscience.nvim) | Neovim frontend for OpenScience | -| [ai-sdk-provider-openscience-sdk](https://github.com/ben-vargas/ai-sdk-provider-openscience-sdk) | Vercel AI SDK provider for using OpenScience via @synsci/sdk | -| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web / Desktop App and VS Code Extension for OpenScience | -| [OpenScience-Obsidian](https://github.com/mtymek/openscience-obsidian) | Obsidian plugin that embedds OpenScience in Obsidian's UI | -| [OpenWork](https://github.com/different-ai/openwork) | An open-source alternative to Claude Cowork, powered by OpenScience | -| [ocx](https://github.com/kdcokenny/ocx) | OpenScience extension manager with portable, isolated profiles. | -| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop, Web, Mobile and Remote Client App for OpenScience | - ---- - -## Agents - -| Name | Description | -| ----------------------------------------------------------------- | ------------------------------------------------------------ | -| [Agentic](https://github.com/Cluster444/agentic) | Modular AI agents and commands for structured development | -| [openscience-agents](https://github.com/darrenhinde/openscience-agents) | Configs, prompts, agents, and plugins for enhanced workflows | diff --git a/frontend/docs/src/content/docs/enterprise.mdx b/frontend/docs/src/content/docs/enterprise.mdx deleted file mode 100644 index 2eb0eae..0000000 --- a/frontend/docs/src/content/docs/enterprise.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Enterprise -description: Using OpenScience securely in your organization. ---- - -import config from "../../../config.mjs" -export const email = `mailto:${config.email}` - -OpenScience Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway. - -:::note -OpenScience does not store any of your code or context data. -::: - -To get started with OpenScience Enterprise: - -1. Do a trial internally with your team. -2. **Contact us** to discuss pricing and implementation options. - ---- - -## Trial - -OpenScience is open source and does not store any of your code or context data, so your developers can simply [get started](/docs/) and carry out a trial. - ---- - -### Data handling - -**OpenScience does not store your code or context data.** All processing happens locally or through direct API calls to your AI provider. - -This means that as long as you are using a provider you trust, or an internal -AI gateway, you can use OpenScience securely. - -The only caveat here is the optional `/share` feature. - ---- - -#### Sharing conversations - -If a user enables the `/share` feature, the conversation and the data associated with it are sent to the service we use to host these share pages at syntheticsciences.ai. - -The data is currently served through our CDN's edge network, and is cached on the edge near your users. - -We recommend you disable this for your trial. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "share": "disabled" -} -``` - -[Learn more about sharing](/docs/share). - ---- - -### Code ownership - -**You own all code produced by OpenScience.** There are no licensing restrictions or ownership claims. - ---- - -## Pricing - -We use a per-seat model for OpenScience Enterprise. If you have your own LLM gateway, we do not charge for tokens used. For further details about pricing and implementation options, **contact us**. - ---- - -## Deployment - -Once you have completed your trial and you are ready to use OpenScience at -your organization, you can **contact us** to discuss -pricing and implementation options. - ---- - -### Central config - -We can set up OpenScience to use a single central config for your entire organization. - -This centralized config can integrate with your SSO provider and ensures all users access only your internal AI gateway. - ---- - -### SSO integration - -Through the central config, OpenScience can integrate with your organization's SSO provider for authentication. - -This allows OpenScience to obtain credentials for your internal AI gateway through your existing identity management system. - ---- - -### Internal AI gateway - -With the central config, OpenScience can also be configured to use only your internal AI gateway. - -You can also disable all other AI providers, ensuring all requests go through your organization's approved infrastructure. - ---- - -### Self-hosting - -While we recommend disabling the share pages to ensure your data never leaves -your organization, we can also help you self-host them on your infrastructure. - -This is currently on our roadmap. If you're interested, **let us know**. - ---- - -## FAQ - -
-What is OpenScience Enterprise? - -OpenScience Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway. - -
- -
-How do I get started with OpenScience Enterprise? - -Simply start with an internal trial with your team. OpenScience by default does not store your code or context data, making it easy to get started. - -Then **contact us** to discuss pricing and implementation options. - -
- -
-How does enterprise pricing work? - -We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not charge for tokens used. For further details, **contact us** for a custom quote based on your organization's needs. - -
- -
-Is my data secure with OpenScience Enterprise? - -Yes. OpenScience does not store your code or context data. All processing happens locally or through direct API calls to your AI provider. With central config and SSO integration, your data remains secure within your organization's infrastructure. - -
- -
-Can we use our own private NPM registry? - -OpenScience supports private npm registries through Bun's native `.npmrc` file support. If your organization uses a private registry, such as JFrog Artifactory, Nexus, or similar, ensure developers are authenticated before running OpenScience. - -To set up authentication with your private registry: - -```bash -npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/ -``` - -This creates `~/.npmrc` with authentication details. OpenScience will automatically -pick this up. - -:::caution -You must be logged into the private registry before running OpenScience. -::: - -Alternatively, you can manually configure a `.npmrc` file: - -```bash title="~/.npmrc" -registry=https://your-company.jfrog.io/api/npm/npm-virtual/ -//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN} -``` - -Developers must be logged into the private registry before running OpenScience to ensure packages can be installed from your enterprise registry. - -
diff --git a/frontend/docs/src/content/docs/formatters.mdx b/frontend/docs/src/content/docs/formatters.mdx deleted file mode 100644 index 664ec1a..0000000 --- a/frontend/docs/src/content/docs/formatters.mdx +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Formatters -description: OpenScience uses language specific formatters. ---- - -OpenScience automatically formats files after they are written or edited using language-specific formatters. This ensures that the code that is generated follows the code styles of your project. - ---- - -## Built-in - -OpenScience comes with several built-in formatters for popular languages and frameworks. Below is a list of the formatters, supported file extensions, and commands or config options it needs. - -| Formatter | Extensions | Requirements | -| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| gofmt | .go | `gofmt` command available | -| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` command available | -| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json` | -| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | `biome.json(c)` config file | -| zig | .zig, .zon | `zig` command available | -| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` config file | -| ktlint | .kt, .kts | `ktlint` command available | -| ruff | .py, .pyi | `ruff` command available with config | -| rustfmt | .rs | `rustfmt` command available | -| cargofmt | .rs | `cargo fmt` command available | -| uv | .py, .pyi | `uv` command available | -| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` command available | -| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` command available | -| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` command available | -| air | .R | `air` command available | -| dart | .dart | `dart` command available | -| ocamlformat | .ml, .mli | `ocamlformat` command available and `.ocamlformat` config file | -| terraform | .tf, .tfvars | `terraform` command available | -| gleam | .gleam | `gleam` command available | -| nixfmt | .nix | `nixfmt` command available | -| shfmt | .sh, .bash | `shfmt` command available | -| pint | .php | `laravel/pint` dependency in `composer.json` | -| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) | - -So if your project has `prettier` in your `package.json`, OpenScience will automatically use it. - ---- - -## How it works - -When OpenScience writes or edits a file, it: - -1. Checks the file extension against all enabled formatters. -2. Runs the appropriate formatter command on the file. -3. Applies the formatting changes automatically. - -This process happens in the background, ensuring your code styles are maintained without any manual steps. - ---- - -## Configure - -You can customize formatters through the `formatter` section in your OpenScience config. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "formatter": {} -} -``` - -Each formatter configuration supports the following: - -| Property | Type | Description | -| ------------- | -------- | ------------------------------------------------------- | -| `disabled` | boolean | Set this to `true` to disable the formatter | -| `command` | string[] | The command to run for formatting | -| `environment` | object | Environment variables to set when running the formatter | -| `extensions` | string[] | File extensions this formatter should handle | - -Let's look at some examples. - ---- - -### Disabling formatters - -To disable **all** formatters globally, set `formatter` to `false`: - -```json title="openscience.json" {3} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "formatter": false -} -``` - -To disable a **specific** formatter, set `disabled` to `true`: - -```json title="openscience.json" {5} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "formatter": { - "prettier": { - "disabled": true - } - } -} -``` - ---- - -### Custom formatters - -You can override the built-in formatters or add new ones by specifying the command, environment variables, and file extensions: - -```json title="openscience.json" {4-14} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "formatter": { - "prettier": { - "command": ["npx", "prettier", "--write", "$FILE"], - "environment": { - "NODE_ENV": "development" - }, - "extensions": [".js", ".ts", ".jsx", ".tsx"] - }, - "custom-markdown-formatter": { - "command": ["deno", "fmt", "$FILE"], - "extensions": [".md"] - } - } -} -``` - -The **`$FILE` placeholder** in the command will be replaced with the path to the file being formatted. diff --git a/frontend/docs/src/content/docs/github.mdx b/frontend/docs/src/content/docs/github.mdx deleted file mode 100644 index bc4bdc6..0000000 --- a/frontend/docs/src/content/docs/github.mdx +++ /dev/null @@ -1,321 +0,0 @@ ---- -title: GitHub -description: Use OpenScience in GitHub issues and pull-requests. ---- - -OpenScience integrates with your GitHub workflow. Mention `/openscience` or `/oc` in your comment, and OpenScience will execute tasks within your GitHub Actions runner. - ---- - -## Features - -- **Triage issues**: Ask OpenScience to look into an issue and explain it to you. -- **Fix and implement**: Ask OpenScience to fix an issue or implement a feature. It works in a new branch and opens a PR with all the changes. -- **Secure**: OpenScience runs inside your GitHub's runners. - ---- - -## Installation - -Run the following command in a project that is in a GitHub repo: - -```bash -openscience github install -``` - -This will walk you through installing the GitHub app, creating the workflow, and setting up secrets. - ---- - -### Manual setup - -Or you can set it up manually. - -1. **Install the GitHub app** - - Head over to [**github.com/apps/openscience-agent**](https://github.com/apps/openscience-agent). Make sure it's installed on the target repository. - -2. **Add the workflow** - - Add the following workflow file to `.github/workflows/openscience.yml` in your repo. Make sure to set the appropriate `model` and required API keys in `env`. - - ```yml title=".github/workflows/openscience.yml" {24,26} - name: openscience - - on: - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - - jobs: - openscience: - if: | - contains(github.event.comment.body, '/oc') || - contains(github.event.comment.body, '/openscience') - runs-on: ubuntu-latest - permissions: - id-token: write - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 1 - persist-credentials: false - - - name: Run OpenScience - uses: synthetic-sciences/OpenScience/github@latest - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - with: - model: anthropic/claude-sonnet-4-20250514 - # share: true - # github_token: xxxx - ``` - -3. **Store the API keys in secrets** - - In your organization or project **settings**, expand **Secrets and variables** on the left and select **Actions**. And add the required API keys. - ---- - -## Configuration - -- `model`: The model to use with OpenScience. Takes the format of `provider/model`. This is **required**. -- `agent`: The agent to use. Must be a primary agent. Falls back to `default_agent` from config or `"research"` if not found. -- `share`: Whether to share the OpenScience session. Defaults to **true** for public repositories. -- `prompt`: Optional custom prompt to override the default behavior. Use this to customize how OpenScience processes requests. -- `token`: Optional GitHub access token for performing operations such as creating comments, committing changes, and opening pull requests. By default, OpenScience uses the installation access token from the OpenScience GitHub App, so commits, comments, and pull requests appear as coming from the app. - - Alternatively, you can use the GitHub Action runner's [built-in `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) without installing the OpenScience GitHub App. Just make sure to grant the required permissions in your workflow: - - ```yaml - permissions: - id-token: write - contents: write - pull-requests: write - issues: write - ``` - - You can also use a [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) if preferred. - ---- - -## Supported events - -OpenScience can be triggered by the following GitHub events: - -| Event Type | Triggered By | Details | -| ----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| `issue_comment` | Comment on an issue or PR | Mention `/openscience` or `/oc` in your comment. OpenScience reads context and can create branches, open PRs, or reply. | -| `pull_request_review_comment` | Comment on specific code lines in a PR | Mention `/openscience` or `/oc` while reviewing code. OpenScience receives file path, line numbers, and diff context. | -| `issues` | Issue opened or edited | Automatically trigger OpenScience when issues are created or modified. Requires `prompt` input. | -| `pull_request` | PR opened or updated | Automatically trigger OpenScience when PRs are opened, synchronized, or reopened. Useful for automated reviews. | -| `schedule` | Cron-based schedule | Run OpenScience on a schedule. Requires `prompt` input. Output goes to logs and PRs (no issue to comment on). | -| `workflow_dispatch` | Manual trigger from GitHub UI | Trigger OpenScience on demand via Actions tab. Requires `prompt` input. Output goes to logs and PRs. | - -### Schedule example - -Run OpenScience on a schedule to perform automated tasks: - -```yaml title=".github/workflows/openscience-scheduled.yml" -name: Scheduled OpenScience Task - -on: - schedule: - - cron: "0 9 * * 1" # Every Monday at 9am UTC - -jobs: - openscience: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - persist-credentials: false - - - name: Run OpenScience - uses: synthetic-sciences/OpenScience/github@latest - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - with: - model: anthropic/claude-sonnet-4-20250514 - prompt: | - Review the codebase for any TODO comments and create a summary. - If you find issues worth addressing, open an issue to track them. -``` - -For scheduled events, the `prompt` input is **required** since there's no comment to extract instructions from. Scheduled workflows run without a user context to permission-check, so the workflow must grant `contents: write` and `pull-requests: write` if you expect OpenScience to create branches or PRs. - ---- - -### Pull request example - -Automatically review PRs when they are opened or updated: - -```yaml title=".github/workflows/openscience-review.yml" -name: openscience-review - -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - -jobs: - review: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - pull-requests: read - issues: read - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: synthetic-sciences/OpenScience/github@latest - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - model: anthropic/claude-sonnet-4-20250514 - use_github_token: true - prompt: | - Review this pull request: - - Check for code quality issues - - Look for potential bugs - - Suggest improvements -``` - -For `pull_request` events, if no `prompt` is provided, OpenScience defaults to reviewing the pull request. - ---- - -### Issues triage example - -Automatically triage new issues. This example filters to accounts older than 30 days to reduce spam: - -```yaml title=".github/workflows/openscience-triage.yml" -name: Issue Triage - -on: - issues: - types: [opened] - -jobs: - triage: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - pull-requests: write - issues: write - steps: - - name: Check account age - id: check - uses: actions/github-script@v7 - with: - script: | - const user = await github.rest.users.getByUsername({ - username: context.payload.issue.user.login - }); - const created = new Date(user.data.created_at); - const days = (Date.now() - created) / (1000 * 60 * 60 * 24); - return days >= 30; - result-encoding: string - - - uses: actions/checkout@v6 - if: steps.check.outputs.result == 'true' - with: - persist-credentials: false - - - uses: synthetic-sciences/OpenScience/github@latest - if: steps.check.outputs.result == 'true' - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - with: - model: anthropic/claude-sonnet-4-20250514 - prompt: | - Review this issue. If there's a clear fix or relevant docs: - - Provide documentation links - - Add error handling guidance for code examples - Otherwise, do not comment. -``` - -For `issues` events, the `prompt` input is **required** since there's no comment to extract instructions from. - ---- - -## Custom prompts - -Override the default prompt to customize OpenScience's behavior for your workflow. - -```yaml title=".github/workflows/openscience.yml" -- uses: synthetic-sciences/OpenScience/github@latest - with: - model: anthropic/claude-sonnet-4-5 - prompt: | - Review this pull request: - - Check for code quality issues - - Look for potential bugs - - Suggest improvements -``` - -This is useful for enforcing specific review criteria, coding standards, or focus areas relevant to your project. - ---- - -## Examples - -Here are some examples of how you can use OpenScience in GitHub. - -- **Explain an issue** - - Add this comment in a GitHub issue. - - ``` - /openscience explain this issue - ``` - - OpenScience will read the entire thread, including all comments, and reply with a clear explanation. - -- **Fix an issue** - - In a GitHub issue, say: - - ``` - /openscience fix this - ``` - - And OpenScience will create a new branch, implement the changes, and open a PR with the changes. - -- **Review PRs and make changes** - - Leave the following comment on a GitHub PR. - - ``` - Delete the attachment from S3 when the note is removed /oc - ``` - - OpenScience will implement the requested change and commit it to the same PR. - -- **Review specific code lines** - - Leave a comment directly on code lines in the PR's "Files" tab. OpenScience automatically detects the file, line numbers, and diff context to provide precise responses. - - ``` - [Comment on specific lines in Files tab] - /oc add error handling here - ``` - - When commenting on specific lines, OpenScience receives: - - The exact file being reviewed - - The specific lines of code - - The surrounding diff context - - Line number information - - This allows for more targeted requests without needing to specify file paths or line numbers manually. diff --git a/frontend/docs/src/content/docs/gitlab.mdx b/frontend/docs/src/content/docs/gitlab.mdx deleted file mode 100644 index 57f0902..0000000 --- a/frontend/docs/src/content/docs/gitlab.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: GitLab -description: Use OpenScience in GitLab issues and merge requests. ---- - -OpenScience integrates with your GitLab workflow through your GitLab CI/CD pipeline or with GitLab Duo. - -In both cases, OpenScience will run on your GitLab runners. - ---- - -## GitLab CI - -OpenScience works in a regular GitLab pipeline. You can build it into a pipeline as a [CI component](https://docs.gitlab.com/ee/ci/components/) - -Here we are using a community-created CI/CD component for OpenScience, [nagyv/gitlab-openscience](https://gitlab.com/nagyv/gitlab-openscience). - ---- - -### Features - -- **Use custom configuration per job**: Configure OpenScience with a custom configuration directory, for example `./config/#custom-directory` to enable or disable functionality per OpenScience invocation. -- **Minimal setup**: The CI component sets up OpenScience in the background, you only need to create the OpenScience configuration and the initial prompt. -- **Flexible**: The CI component supports several inputs for customizing its behavior - ---- - -### Setup - -1. Store your OpenScience authentication JSON as a File type CI environment variables under **Settings** > **CI/CD** > **Variables**. Make sure to mark them as "Masked and hidden". -2. Add the following to your `.gitlab-ci.yml` file. - - ```yaml title=".gitlab-ci.yml" - include: - - component: $CI_SERVER_FQDN/nagyv/gitlab-openscience/openscience@2 - inputs: - config_dir: ${CI_PROJECT_DIR}/openscience-config - auth_json: $OPENSCIENCE_AUTH_JSON # The variable name for your OpenScience authentication JSON - command: optional-custom-command - message: "Your prompt here" - ``` - -For more inputs and use cases [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-openscience) for this component. - ---- - -## GitLab Duo - -OpenScience integrates with your GitLab workflow. -Mention `@openscience` in a comment, and OpenScience will execute tasks within your GitLab CI pipeline. - ---- - -### Features - -- **Triage issues**: Ask OpenScience to look into an issue and explain it to you. -- **Fix and implement**: Ask OpenScience to fix an issue or implement a feature. - It will create a new branch and raise a merge request with the changes. -- **Secure**: OpenScience runs on your GitLab runners. - ---- - -### Setup - -OpenScience runs in your GitLab CI/CD pipeline, here's what you'll need to set it up: - -:::tip -Check out the [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for up to date instructions. -::: - -1. Configure your GitLab environment -2. Set up CI/CD -3. Get an AI model provider API key -4. Create a service account -5. Configure CI/CD variables -6. Create a flow config file, here's an example: - -
- - Flow configuration - - ```yaml - image: node:22-slim - commands: - - echo "Installing openscience" - - npm install --global openscience - - echo "Installing glab" - - export GITLAB_TOKEN=$GITLAB_TOKEN_OPENSCIENCE - - apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/* - - curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash - - apt-get install --yes glab - - echo "Configuring glab" - - echo $GITLAB_HOST - - echo "Creating OpenScience auth configuration" - - mkdir --parents ~/.local/share/openscience - - | - cat > ~/.local/share/openscience/auth.json << EOF - { - "anthropic": { - "type": "api", - "key": "$ANTHROPIC_API_KEY" - } - } - EOF - - echo "Configuring git" - - git config --global user.email "openscience@gitlab.com" - - git config --global user.name "OpenScience" - - echo "Testing glab" - - glab issue list - - echo "Running OpenScience" - - | - openscience run " - You are an AI assistant helping with GitLab operations. - - Context: $AI_FLOW_CONTEXT - Task: $AI_FLOW_INPUT - Event: $AI_FLOW_EVENT - - Please execute the requested task using the available GitLab tools. - Be thorough in your analysis and provide clear explanations. - - - Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands. - - If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it. - You don't need to commit or push up changes, those will be done automatically based on the file changes you make. - - " - - git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF - - echo "Checking for git changes and pushing if any exist" - - | - if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then - echo "Git changes detected, adding and pushing..." - git add . - if git diff --cached --quiet; then - echo "No staged changes to commit" - else - echo "Committing changes to branch: $CI_WORKLOAD_REF" - git commit --message "Codex changes" - echo "Pushing changes up to $CI_WORKLOAD_REF" - git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF - echo "Changes successfully pushed" - fi - else - echo "No git changes detected, skipping push" - fi - variables: - - ANTHROPIC_API_KEY - - GITLAB_TOKEN_OPENSCIENCE - - GITLAB_HOST - ``` - -
- -You can refer to the [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for detailed instructions. - ---- - -### Examples - -Here are some examples of how you can use OpenScience in GitLab. - -:::tip -You can configure to use a different trigger phrase than `@openscience`. -::: - -- **Explain an issue** - - Add this comment in a GitLab issue. - - ``` - @openscience explain this issue - ``` - - OpenScience will read the issue and reply with a clear explanation. - -- **Fix an issue** - - In a GitLab issue, say: - - ``` - @openscience fix this - ``` - - OpenScience will create a new branch, implement the changes, and open a merge request with the changes. - -- **Review merge requests** - - Leave the following comment on a GitLab merge request. - - ``` - @openscience review this merge request - ``` - - OpenScience will review the merge request and provide feedback. diff --git a/frontend/docs/src/content/docs/index.mdx b/frontend/docs/src/content/docs/index.mdx deleted file mode 100644 index 5b7bc63..0000000 --- a/frontend/docs/src/content/docs/index.mdx +++ /dev/null @@ -1,317 +0,0 @@ ---- -title: Intro -description: Get started with OpenScience. ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components" - -[**OpenScience**](/) is an open-source AI co-scientist. You give it a goal, and it reads the relevant literature, writes and runs code, runs the experiments, and writes up the result. Running `openscience` opens a workspace in your browser. It also has a CLI for scripting. - -![The OpenScience workspace](../../assets/lander/screenshot.png) - -Let's get started. - ---- - -#### Prerequisites - -To use OpenScience, you'll need: - -1. A modern web browser. -2. API keys for the LLM providers you want to use. - ---- - -## Install - -The easiest way to install OpenScience is with npm. It installs the `openscience` command: - -```bash -npm i -g @synsci/openscience -``` - -To install and open the workspace in a single step, run the setup wizard instead: - -```bash -npx synsci -``` - -You can also install it with one of the following package managers: - -- **Using Node.js** - - - - - ```bash - npm i -g @synsci/openscience - ``` - - - - - ```bash - bun install -g @synsci/openscience - ``` - - - - - ```bash - pnpm install -g @synsci/openscience - ``` - - - - - ```bash - yarn global add @synsci/openscience - ``` - - - - - -#### Windows - -- **Using NPM** - - ```bash - npm i -g @synsci/openscience - ``` - -- **Using Mise** - - ```bash - mise use -g github:synthetic-sciences/OpenScience - ``` - -- **Using Docker** - - ```bash - docker run -it --rm ghcr.io/synthetic-sciences/openscience - ``` - -Support for installing OpenScience on Windows using Bun is currently in progress. - -You can also grab the binary from the [Releases](https://github.com/synthetic-sciences/OpenScience/releases). - ---- - -## Configure - -With OpenScience you can use any LLM provider by configuring their API keys. - -If you are new to using LLM providers, we recommend using [Atlas](/docs/atlas), -Synthetic Sciences' managed platform. It includes a curated set of models that -have been tested and verified by the OpenScience team. - -1. Sign in from the CLI. - - ```bash - openscience connect login - ``` - -2. Approve the sign-in from your browser and add credits to your wallet. - -3. Run `/models` in the workspace and pick one of the curated `synsci/...` models. - - ```txt - /models - ``` - -Alternatively, BYOK is free and needs no account. You can connect any of the other providers with your own API keys. [Learn more](/docs/providers#directory). - ---- - -## Initialize - -Now that you've configured a provider, you can navigate to a project that -you want to work on. - -```bash -cd /path/to/project -``` - -And run OpenScience. - -```bash -openscience -``` - -Next, initialize OpenScience for the project by running the following command. - -```bash frame="none" -/init -``` - -This will get OpenScience to analyze your project and create an `AGENTS.md` file in -the project root. - -:::tip -You should commit your project's `AGENTS.md` file to Git. -::: - -This helps OpenScience understand the project structure and the coding patterns -used. - ---- - -## Usage - -You are now ready to use OpenScience to work on your project. Feel free to ask it -anything! - -If you are new to using an AI coding agent, here are some examples that might -help. - ---- - -### Ask questions - -You can ask OpenScience to explain the codebase to you. - -:::tip -Use the `@` key to fuzzy search for files in the project. -::: - -```txt frame="none" "@packages/functions/src/api/index.ts" -How is authentication handled in @packages/functions/src/api/index.ts -``` - -This is helpful if there's a part of the codebase that you didn't work on. - ---- - -### Add features - -You can ask OpenScience to add new features to your project. Though we first recommend asking it to create a plan. - -1. **Create a plan** - - OpenScience has a _plan mode_ that turns off its ability to make changes and - instead suggests _how_ it'll implement the feature. - - Switch to it with the mode selector in the workspace. - - Now let's describe what we want it to do. - - ```txt frame="none" - When a user deletes a note, we'd like to flag it as deleted in the database. - Then create a screen that shows all the recently deleted notes. - From this screen, the user can undelete a note or permanently delete it. - ``` - - You want to give OpenScience enough details to understand what you want. It helps - to talk to it like you are talking to a junior developer on your team. - - :::tip - Give OpenScience plenty of context and examples to help it understand what you - want. - ::: - -2. **Iterate on the plan** - - Once it gives you a plan, you can give it feedback or add more details. - - ```txt frame="none" - We'd like to design this new screen using a design I've used before. - [Image #1] Take a look at this image and use it as a reference. - ``` - - :::tip - Drag and drop images into the workspace to add them to the prompt. - ::: - - OpenScience can scan any images you give it and add them to the prompt. You can - do this by dragging and dropping an image into the workspace. - -3. **Build the feature** - - Once you feel comfortable with the plan, switch back to the _research_ - agent with the mode selector. - - And ask it to make the changes. - - ```bash frame="none" - Sounds good! Go ahead and make the changes. - ``` - ---- - -### Make changes - -For more straightforward changes, you can ask OpenScience to directly build it -without having to review the plan first. - -```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts" -We need to add authentication to the /settings route. Take a look at how this is -handled in the /notes route in @packages/functions/src/notes.ts and implement -the same logic in @packages/functions/src/settings.ts -``` - -You want to make sure you provide a good amount of detail so OpenScience makes the right -changes. - ---- - -### Undo changes - -Let's say you ask OpenScience to make some changes. - -```txt frame="none" "@packages/functions/src/api/index.ts" -Can you refactor the function in @packages/functions/src/api/index.ts? -``` - -But you realize that it is not what you wanted. You **can undo** the changes -using the `/undo` command. - -```bash frame="none" -/undo -``` - -OpenScience will now revert the changes you made and show your original message -again. - -```txt frame="none" "@packages/functions/src/api/index.ts" -Can you refactor the function in @packages/functions/src/api/index.ts? -``` - -From here you can tweak the prompt and ask OpenScience to try again. - -:::tip -You can run `/undo` multiple times to undo multiple changes. -::: - -Or you **can redo** the changes using the `/redo` command. - -```bash frame="none" -/redo -``` - ---- - -## Share - -The conversations that you have with OpenScience can be [shared with your -team](/docs/share). - -```bash frame="none" -/share -``` - -This will create a link to the current conversation and copy it to your clipboard. - -:::note -Conversations are not shared by default. -::: - -Here's an [example conversation](https://syntheticsciences.ai/s/4XP1fce5) with OpenScience. - ---- - -## Customize - -And that's it. You now know your way around OpenScience. - -To make it your own, you can [pick a theme](/docs/themes), [configure code formatters](/docs/formatters), [create custom commands](/docs/commands), or adjust the [OpenScience config](/docs/config). diff --git a/frontend/docs/src/content/docs/lsp.mdx b/frontend/docs/src/content/docs/lsp.mdx deleted file mode 100644 index a4535a2..0000000 --- a/frontend/docs/src/content/docs/lsp.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: LSP Servers -description: OpenScience integrates with your LSP servers. ---- - -OpenScience integrates with your Language Server Protocol (LSP) to help the LLM interact with your codebase. It uses diagnostics to provide feedback to the LLM. - ---- - -## Built-in - -OpenScience comes with several built-in LSP servers for popular languages: - -| LSP Server | Extensions | Requirements | -| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ | -| astro | .astro | Auto-installs for Astro projects | -| bash | .sh, .bash, .zsh, .ksh | Auto-installs bash-language-server | -| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Auto-installs for C/C++ projects | -| csharp | .cs | `.NET SDK` installed | -| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` command available | -| dart | .dart | `dart` command available | -| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` command available (auto-detects deno.json/deno.jsonc) | -| elixir-ls | .ex, .exs | `elixir` command available | -| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` dependency in project | -| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed | -| gleam | .gleam | `gleam` command available | -| gopls | .go | `go` command available | -| jdtls | .java | `Java SDK (version 21+)` installed | -| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects | -| lua-ls | .lua | Auto-installs for Lua projects | -| nixd | .nix | `nixd` command available | -| ocaml-lsp | .ml, .mli | `ocamllsp` command available | -| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependency in project | -| php intelephense | .php | Auto-installs for PHP projects | -| prisma | .prisma | `prisma` command available | -| pyright | .py, .pyi | `pyright` dependency installed | -| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` and `gem` commands available | -| rust | .rs | `rust-analyzer` command available | -| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installed (`xcode` on macOS) | -| svelte | .svelte | Auto-installs for Svelte projects | -| terraform | .tf, .tfvars | Auto-installs from GitHub releases | -| tinymist | .typ, .typc | Auto-installs from GitHub releases | -| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project | -| vue | .vue | Auto-installs for Vue projects | -| yaml-ls | .yaml, .yml | Auto-installs Red Hat yaml-language-server | -| zls | .zig, .zon | `zig` command available | - -LSP servers are automatically enabled when one of the above file extensions are detected and the requirements are met. - -:::note -You can disable automatic LSP server downloads by setting the `OPENSCIENCE_DISABLE_LSP_DOWNLOAD` environment variable to `true`. -::: - ---- - -## How it works - -When OpenScience opens a file, it: - -1. Checks the file extension against all enabled LSP servers. -2. Starts the appropriate LSP server if not already running. - ---- - -## Configure - -You can customize LSP servers through the `lsp` section in your OpenScience config. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "lsp": {} -} -``` - -Each LSP server supports the following: - -| Property | Type | Description | -| ---------------- | -------- | ------------------------------------------------- | -| `disabled` | boolean | Set this to `true` to disable the LSP server | -| `command` | string[] | The command to start the LSP server | -| `extensions` | string[] | File extensions this LSP server should handle | -| `env` | object | Environment variables to set when starting server | -| `initialization` | object | Initialization options to send to the LSP server | - -Let's look at some examples. - ---- - -### Disabling LSP servers - -To disable **all** LSP servers globally, set `lsp` to `false`: - -```json title="openscience.json" {3} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "lsp": false -} -``` - -To disable a **specific** LSP server, set `disabled` to `true`: - -```json title="openscience.json" {5} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "lsp": { - "typescript": { - "disabled": true - } - } -} -``` - ---- - -### Custom LSP servers - -You can add custom LSP servers by specifying the command and file extensions: - -```json title="openscience.json" {4-7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "lsp": { - "custom-lsp": { - "command": ["custom-lsp-server", "--stdio"], - "extensions": [".custom"] - } - } -} -``` - ---- - -## Additional information - -### PHP Intelephense - -PHP Intelephense offers premium features through a license key. You can provide a license key by placing (only) the key in a text file at: - -- On macOS/Linux: `$HOME/intelephense/licence.txt` -- On Windows: `%USERPROFILE%/intelephense/licence.txt` - -The file should contain only the license key with no additional content. diff --git a/frontend/docs/src/content/docs/mcp-servers.mdx b/frontend/docs/src/content/docs/mcp-servers.mdx deleted file mode 100644 index 5cb58e0..0000000 --- a/frontend/docs/src/content/docs/mcp-servers.mdx +++ /dev/null @@ -1,511 +0,0 @@ ---- -title: MCP servers -description: Add local and remote MCP tools. ---- - -You can add external tools to OpenScience using the _Model Context Protocol_, or MCP. OpenScience supports both local and remote servers. - -Once added, MCP tools are automatically available to the LLM alongside built-in tools. - ---- - -#### Caveats - -When you use an MCP server, it adds to the context. This can quickly add up if you have a lot of tools. So we recommend being careful with which MCP servers you use. - -:::tip -MCP servers add to your context, so you want to be careful with which ones you enable. -::: - -Certain MCP servers, like the GitHub MCP server, tend to add a lot of tokens and can easily exceed the context limit. - ---- - -## Enable - -You can define MCP servers in your [OpenScience config](https://syntheticsciences.ai/docs/config/) under `mcp`. Add each MCP with a unique name. You can refer to that MCP by name when prompting the LLM. - -```jsonc title="openscience.jsonc" {6} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "name-of-mcp-server": { - // ... - "enabled": true, - }, - "name-of-other-mcp-server": { - // ... - }, - }, -} -``` - -You can also disable a server by setting `enabled` to `false`. This is useful if you want to temporarily disable a server without removing it from your config. - ---- - -### Overriding remote defaults - -Organizations can provide default MCP servers via their `.well-known/openscience` endpoint. These servers may be disabled by default, allowing users to opt-in to the ones they need. - -To enable a specific server from your organization's remote config, add it to your local config with `enabled: true`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - -Your local config values override the remote defaults. See [config precedence](/docs/config#precedence-order) for more details. - ---- - -## Local - -Add local MCP servers using `type` to `"local"` within the MCP object. - -```jsonc title="openscience.jsonc" {15} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-local-mcp-server": { - "type": "local", - // Or ["bun", "x", "my-mcp-command"] - "command": ["npx", "-y", "my-mcp-command"], - "enabled": true, - "environment": { - "MY_ENV_VAR": "my_env_var_value", - }, - }, - }, -} -``` - -The command is how the local MCP server is started. You can also pass in a list of environment variables as well. - -For example, here's how you can add the test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP server. - -```jsonc title="openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "mcp_everything": { - "type": "local", - "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], - }, - }, -} -``` - -And to use it I can add `use the mcp_everything tool` to my prompts. - -```txt "mcp_everything" -use the mcp_everything tool to add the number 3 and 4 -``` - ---- - -#### Options - -Here are all the options for configuring a local MCP server. - -| Option | Type | Required | Description | -| ------------- | ------- | -------- | ----------------------------------------------------------------------------------- | -| `type` | String | Y | Type of MCP server connection, must be `"local"`. | -| `command` | Array | Y | Command and arguments to run the MCP server. | -| `environment` | Object | | Environment variables to set when running the server. | -| `enabled` | Boolean | | Enable or disable the MCP server on startup. | -| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). | - ---- - -## Remote - -Add remote MCP servers by setting `type` to `"remote"`. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-remote-mcp": { - "type": "remote", - "url": "https://my-mcp-server.com", - "enabled": true, - "headers": { - "Authorization": "Bearer MY_API_KEY" - } - } - } -} -``` - -The `url` is the URL of the remote MCP server and with the `headers` option you can pass in a list of headers. - ---- - -#### Options - -| Option | Type | Required | Description | -| --------- | ------- | -------- | ----------------------------------------------------------------------------------- | -| `type` | String | Y | Type of MCP server connection, must be `"remote"`. | -| `url` | String | Y | URL of the remote MCP server. | -| `enabled` | Boolean | | Enable or disable the MCP server on startup. | -| `headers` | Object | | Headers to send with the request. | -| `oauth` | Object | | OAuth authentication configuration. See [OAuth](#oauth) section below. | -| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). | - ---- - -## OAuth - -OpenScience automatically handles OAuth authentication for remote MCP servers. When a server requires authentication, OpenScience will: - -1. Detect the 401 response and initiate the OAuth flow -2. Use **Dynamic Client Registration (RFC 7591)** if supported by the server -3. Store tokens securely for future requests - ---- - -### Automatic - -For most OAuth-enabled MCP servers, no special configuration is needed. Just configure the remote server: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp" - } - } -} -``` - -If the server requires authentication, OpenScience will prompt you to authenticate when you first try to use it. If not, you can [manually trigger the flow](#authenticating) with `openscience mcp auth `. - ---- - -### Pre-registered - -If you have client credentials from the MCP server provider, you can configure them: - -```json title="openscience.json" {7-11} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": { - "clientId": "{env:MY_MCP_CLIENT_ID}", - "clientSecret": "{env:MY_MCP_CLIENT_SECRET}", - "scope": "tools:read tools:execute" - } - } - } -} -``` - ---- - -### Authenticating - -You can manually trigger authentication or manage credentials. - -Authenticate with a specific MCP server: - -```bash -openscience mcp auth my-oauth-server -``` - -List all MCP servers and their auth status: - -```bash -openscience mcp list -``` - -Remove stored credentials: - -```bash -openscience mcp logout my-oauth-server -``` - -The `mcp auth` command will open your browser for authorization. After you authorize, OpenScience will store the tokens securely in `~/.local/share/openscience/mcp-auth.json`. - ---- - -#### Disabling OAuth - -If you want to disable automatic OAuth for a server (e.g., for servers that use API keys instead), set `oauth` to `false`: - -```json title="openscience.json" {7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-api-key-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": false, - "headers": { - "Authorization": "Bearer {env:MY_API_KEY}" - } - } - } -} -``` - ---- - -#### OAuth options - -| Option | Type | Description | -| -------------- | --------------- | -------------------------------------------------------------------------------- | -| `oauth` | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection. | -| `clientId` | String | OAuth client ID. If not provided, dynamic client registration will be attempted. | -| `clientSecret` | String | OAuth client secret, if required by the authorization server. | -| `scope` | String | OAuth scopes to request during authorization. | - -#### Debugging - -If a remote MCP server is failing to authenticate, you can diagnose issues with: - -```bash -# View auth status for all OAuth-capable servers -openscience mcp auth list - -# Debug connection and OAuth flow for a specific server -openscience mcp debug my-oauth-server -``` - -The `mcp debug` command shows the current auth status, tests HTTP connectivity, and attempts the OAuth discovery flow. - ---- - -## Manage - -Your MCPs are available as tools in OpenScience, alongside built-in tools. So you can manage them through the OpenScience config like any other tool. - ---- - -### Global - -This means that you can enable or disable them globally. - -```json title="openscience.json" {14} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp-foo": false - } -} -``` - -We can also use a glob pattern to disable all matching MCPs. - -```json title="openscience.json" {14} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp*": false - } -} -``` - -Here we are using the glob pattern `my-mcp*` to disable all MCPs. - ---- - -### Per agent - -If you have a large number of MCP servers you may want to only enable them per agent and disable them globally. To do this: - -1. Disable it as a tool globally. -2. In your [agent config](/docs/agents#tools), enable the MCP server as a tool. - -```json title="openscience.json" {11, 14-18} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "my-mcp": { - "type": "local", - "command": ["bun", "x", "my-mcp-command"], - "enabled": true - } - }, - "tools": { - "my-mcp*": false - }, - "agent": { - "my-agent": { - "tools": { - "my-mcp*": true - } - } - } -} -``` - ---- - -#### Glob patterns - -The glob pattern uses simple regex globbing patterns: - -- `*` matches zero or more of any character (e.g., `"my-mcp*"` matches `my-mcp_search`, `my-mcp_list`, etc.) -- `?` matches exactly one character -- All other characters match literally - -:::note -MCP server tools are registered with server name as prefix, so to disable all tools for a server simply use: - -``` -"mymcpservername_*": false -``` - -::: - ---- - -## Examples - -Below are examples of some common MCP servers. You can submit a PR if you want to document other servers. - ---- - -### Sentry - -Add the [Sentry MCP server](https://mcp.sentry.dev) to interact with your Sentry projects and issues. - -```json title="openscience.json" {4-8} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "sentry": { - "type": "remote", - "url": "https://mcp.sentry.dev/mcp", - "oauth": {} - } - } -} -``` - -After adding the configuration, authenticate with Sentry: - -```bash -openscience mcp auth sentry -``` - -This will open a browser window to complete the OAuth flow and connect OpenScience to your Sentry account. - -Once authenticated, you can use Sentry tools in your prompts to query issues, projects, and error data. - -```txt "use sentry" -Show me the latest unresolved issues in my project. use sentry -``` - ---- - -### Context7 - -Add the [Context7 MCP server](https://github.com/upstash/context7) to search through docs. - -```json title="openscience.json" {4-7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp" - } - } -} -``` - -If you have signed up for a free account, you can use your API key and get higher rate-limits. - -```json title="openscience.json" {7-9} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp", - "headers": { - "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}" - } - } - } -} -``` - -Here we are assuming that you have the `CONTEXT7_API_KEY` environment variable set. - -Add `use context7` to your prompts to use Context7 MCP server. - -```txt "use context7" -Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 -``` - -Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -When you need to search docs, use `context7` tools. -``` - ---- - -### Grep by Vercel - -Add the [Grep by Vercel](https://grep.app) MCP server to search through code snippets on GitHub. - -```json title="openscience.json" {4-7} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "mcp": { - "gh_grep": { - "type": "remote", - "url": "https://mcp.grep.app" - } - } -} -``` - -Since we named our MCP server `gh_grep`, you can add `use the gh_grep tool` to your prompts to get the agent to use it. - -```txt "use the gh_grep tool" -What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool -``` - -Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. -``` diff --git a/frontend/docs/src/content/docs/models.mdx b/frontend/docs/src/content/docs/models.mdx deleted file mode 100644 index bc20121..0000000 --- a/frontend/docs/src/content/docs/models.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Models -description: Configuring an LLM provider and model. ---- - -OpenScience uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support **75+ LLM providers** and it supports running local models. - ---- - -## Providers - -Most popular providers are preloaded by default. If you've added the credentials for a provider through the `/connect` command, they'll be available when you start OpenScience. - -Learn more about [providers](/docs/providers). - ---- - -## Select a model - -Once you've configured your provider you can select the model you want by typing in: - -```bash frame="none" -/models -``` - ---- - -## Recommended models - -There are a lot of models out there, with new models coming out every week. - -:::tip -Consider using one of the models we recommend. -::: - -However, there are only a few of them that are good at both generating code and tool calling. - -Here are several models that work well with OpenScience, in no particular order. (This is not an exhaustive list nor is it necessarily up to date): - -- GPT 5.2 -- GPT 5.1 Codex -- Claude Opus 4.5 -- Claude Sonnet 4.5 -- Minimax M2.1 -- Gemini 3 Pro - ---- - -## Set a default - -To set one of these as the default model, you can set the `model` key in your -OpenScience config. - -```json title="openscience.json" {3} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "model": "lmstudio/google/gemma-3n-e4b" -} -``` - -Here the full ID is `provider_id/model_id`. For example, if you're using [Atlas](/docs/atlas), you would use `synsci/gpt-5-nano` for GPT 5 Nano (the managed provider's ID is `synsci`). - -If you've configured a [custom provider](/docs/providers#custom), the `provider_id` is key from the `provider` part of your config, and the `model_id` is the key from `provider.models`. - ---- - -## Configure models - -You can globally configure a model's options through the config. - -```jsonc title="openscience.jsonc" {7-12,19-24} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "openai": { - "models": { - "gpt-5": { - "options": { - "reasoningEffort": "high", - "textVerbosity": "low", - "reasoningSummary": "auto", - "include": ["reasoning.encrypted_content"], - }, - }, - }, - }, - "anthropic": { - "models": { - "claude-sonnet-4-5-20250929": { - "options": { - "thinking": { - "type": "enabled", - "budgetTokens": 16000, - }, - }, - }, - }, - }, - }, -} -``` - -Here we're configuring global settings for two built-in models: `gpt-5` when accessed via the `openai` provider, and `claude-sonnet-4-20250514` when accessed via the `anthropic` provider. -The built-in provider and model names can be found on [Models.dev](https://models.dev). - -You can also configure these options for any agents that you are using. The agent config overrides any global options here. [Learn more](/docs/agents/#additional). - -You can also define custom variants that extend built-in ones. Variants let you configure different settings for the same model without creating duplicate entries: - -```jsonc title="openscience.jsonc" {6-21} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "synsci": { - "models": { - "gpt-5": { - "variants": { - "high": { - "reasoningEffort": "high", - "textVerbosity": "low", - "reasoningSummary": "auto", - }, - "low": { - "reasoningEffort": "low", - "textVerbosity": "low", - "reasoningSummary": "auto", - }, - }, - }, - }, - }, - }, -} -``` - ---- - -## Variants - -Many models support multiple variants with different configurations. OpenScience ships with built-in default variants for popular providers. - -### Built-in variants - -OpenScience ships with default variants for many providers: - -**Anthropic**: - -- `high`: High thinking budget (default) -- `max`: Maximum thinking budget - -**OpenAI**: - -Varies by model but roughly: - -- `none`: No reasoning -- `minimal`: Minimal reasoning effort -- `low`: Low reasoning effort -- `medium`: Medium reasoning effort -- `high`: High reasoning effort -- `xhigh`: Extra high reasoning effort - -**Google**: - -- `low`: Lower effort/token budget -- `high`: Higher effort/token budget - -:::tip -This list is not comprehensive. Many other providers have built-in defaults too. -::: - -### Custom variants - -You can override existing variants or add your own: - -```jsonc title="openscience.jsonc" {7-18} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "openai": { - "models": { - "gpt-5": { - "variants": { - "thinking": { - "reasoningEffort": "high", - "textVerbosity": "low", - }, - "fast": { - "disabled": true, - }, - }, - }, - }, - }, - }, -} -``` - -### Cycle variants - -Use the `variant_cycle` keybind to switch between variants. - ---- - -## Loading models - -When OpenScience starts up, it checks for models in the following priority order: - -1. The `--model` or `-m` command line flag. The format is the same as in the config file: `provider_id/model_id`. - -2. The model list in the OpenScience config. - - ```json title="openscience.json" - { - "$schema": "https://syntheticsciences.ai/config.json", - "model": "anthropic/claude-sonnet-4-20250514" - } - ``` - - The format here is `provider/model`. - -3. The last used model. - -4. The first model using an internal priority. diff --git a/frontend/docs/src/content/docs/network.mdx b/frontend/docs/src/content/docs/network.mdx deleted file mode 100644 index a86b478..0000000 --- a/frontend/docs/src/content/docs/network.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Network -description: Configure proxies and custom certificates. ---- - -OpenScience supports standard proxy environment variables and custom certificates for enterprise network environments. - ---- - -## Proxy - -OpenScience respects standard proxy environment variables. - -```bash -# HTTPS proxy (recommended) -export HTTPS_PROXY=https://proxy.example.com:8080 - -# HTTP proxy (if HTTPS not available) -export HTTP_PROXY=http://proxy.example.com:8080 - -# Bypass proxy for local server (required) -export NO_PROXY=localhost,127.0.0.1 -``` - -:::caution -The browser workspace communicates with a local HTTP server. You must bypass the proxy for this connection to prevent routing loops. -::: - -You can configure the server's port and hostname using [CLI flags](/docs/cli#run). - ---- - -### Authenticate - -If your proxy requires basic authentication, include credentials in the URL. - -```bash -export HTTPS_PROXY=http://username:password@proxy.example.com:8080 -``` - -:::caution -Avoid hardcoding passwords. Use environment variables or secure credential storage. -::: - -For proxies requiring advanced authentication like NTLM or Kerberos, consider using an LLM Gateway that supports your authentication method. - ---- - -## Custom certificates - -If your enterprise uses custom CAs for HTTPS connections, configure OpenScience to trust them. - -```bash -export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem -``` - -This works for both proxy connections and direct API access. diff --git a/frontend/docs/src/content/docs/permissions.mdx b/frontend/docs/src/content/docs/permissions.mdx deleted file mode 100644 index 50f507f..0000000 --- a/frontend/docs/src/content/docs/permissions.mdx +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Permissions -description: Control which actions require approval to run. ---- - -OpenScience uses the `permission` config to decide whether a given action should run automatically, prompt you, or be blocked. - -As of `v1.1.1`, the legacy `tools` boolean config is deprecated and has been merged into `permission`. The old `tools` config is still supported for backwards compatibility. - ---- - -## Actions - -Each permission rule resolves to one of: - -- `"allow"`: run without approval -- `"ask"`: prompt for approval -- `"deny"`: block the action - ---- - -## Configuration - -You can set permissions globally (with `*`), and override specific tools. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "*": "ask", - "bash": "allow", - "edit": "deny" - } -} -``` - -You can also set all permissions at once: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": "allow" -} -``` - ---- - -## Granular rules (object syntax) - -For most permissions, you can use an object to apply different actions based on the tool input. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "npm *": "allow", - "rm *": "deny", - "grep *": "allow" - }, - "edit": { - "*": "deny", - "frontend/docs/src/content/docs/*.mdx": "allow" - } - } -} -``` - -Rules are evaluated by pattern match, with the **last matching rule winning**. A common pattern is to put the catch-all `"*"` rule first, and more specific rules after it. - -### Wildcards - -Permission patterns use simple wildcard matching: - -- `*` matches zero or more of any character -- `?` matches exactly one character -- All other characters match literally - -### Home directory expansion - -You can use `~` or `$HOME` at the start of a pattern to reference your home directory. This is particularly useful for [`external_directory`](#external-directories) rules. - -- `~/projects/*` -> `/Users/username/projects/*` -- `$HOME/projects/*` -> `/Users/username/projects/*` -- `~` -> `/Users/username` - -### External directories - -Use `external_directory` to allow tool calls that touch paths outside the working directory where OpenScience was started. This applies to any tool that takes a path as input (for example `read`, `edit`, `list`, `glob`, `grep`, and many `bash` commands). - -Home expansion (like `~/...`) only affects how a pattern is written. It does not make an external path part of the current workspace, so paths outside the working directory must still be allowed via `external_directory`. - -For example, this allows access to everything under `~/projects/personal/`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "external_directory": { - "~/projects/personal/**": "allow" - } - } -} -``` - -Any directory allowed here inherits the same defaults as the current workspace. Since [`read` defaults to `allow`](#defaults), reads are also allowed for entries under `external_directory` unless overridden. Add explicit rules when a tool should be restricted in these paths, such as blocking edits while keeping reads: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "external_directory": { - "~/projects/personal/**": "allow" - }, - "edit": { - "~/projects/personal/**": "deny" - } - } -} -``` - -Keep the list focused on trusted paths, and layer extra allow or deny rules as needed for other tools (for example `bash`). - ---- - -## Available permissions - -OpenScience permissions are keyed by tool name, plus a couple of safety guards: - -- `read`: reading a file (matches the file path) -- `edit`: all file modifications (covers `edit`, `write`, `patch`, `multiedit`) -- `glob`: file globbing (matches the glob pattern) -- `grep`: content search (matches the regex pattern) -- `list`: listing files in a directory (matches the directory path) -- `bash`: running shell commands (matches parsed commands like `git status --porcelain`) -- `task`: launching subagents (matches the subagent type) -- `skill`: loading a skill (matches the skill name) -- `lsp`: running LSP queries (currently non-granular) -- `todoread`, `todowrite`: reading/updating the todo list -- `webfetch`: fetching a URL (matches the URL) -- `websearch`, `codesearch`: web/code search (matches the query) -- `external_directory`: triggered when a tool touches paths outside the project working directory -- `doom_loop`: triggered when the same tool call repeats 3 times with identical input - ---- - -## Defaults - -If you don't specify anything, OpenScience starts from permissive defaults: - -- Most permissions default to `"allow"`. -- `doom_loop` and `external_directory` default to `"ask"`. -- `read` is `"allow"`, but `.env` files are denied by default: - -```json title="openscience.json" -{ - "permission": { - "read": { - "*": "allow", - "*.env": "deny", - "*.env.*": "deny", - "*.env.example": "allow" - } - } -} -``` - ---- - -## What "Ask" does - -When OpenScience prompts for approval, the UI offers three outcomes: - -- `once`: approve just this request -- `always`: approve future requests matching the suggested patterns (for the rest of the current OpenScience session) -- `reject`: deny the request - -The set of patterns that `always` would approve is provided by the tool (for example, bash approvals typically whitelist a safe command prefix like `git status*`). - ---- - -## Agents - -You can override permissions per agent. Agent permissions are merged with the global config, and agent rules take precedence. [Learn more](/docs/agents#permissions) about agent permissions. - -:::note -Refer to the [Granular rules (object syntax)](#granular-rules-object-syntax) section above for more detailed pattern matching examples. -::: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "git commit *": "deny", - "git push *": "deny", - "grep *": "allow" - } - }, - "agent": { - "research": { - "permission": { - "bash": { - "*": "ask", - "git *": "allow", - "git commit *": "ask", - "git push *": "deny", - "grep *": "allow" - } - } - } - } -} -``` - -You can also configure agent permissions in Markdown: - -```markdown title="~/.config/openscience/agents/review.md" ---- -description: Code review without edits -mode: subagent -permission: - edit: deny - bash: ask - webfetch: deny ---- - -Only analyze code and suggest changes. -``` - -:::tip -Use pattern matching for commands with arguments. `"grep *"` allows `grep pattern file.txt`, while `"grep"` alone would block it. Commands like `git status` work for default behavior but require explicit permission (like `"git status *"`) when arguments are passed. -::: diff --git a/frontend/docs/src/content/docs/plugins.mdx b/frontend/docs/src/content/docs/plugins.mdx deleted file mode 100644 index 735ee74..0000000 --- a/frontend/docs/src/content/docs/plugins.mdx +++ /dev/null @@ -1,356 +0,0 @@ ---- -title: Plugins -description: Write your own plugins to extend OpenScience. ---- - -Plugins allow you to extend OpenScience by hooking into various events and customizing behavior. You can create plugins to add new features, integrate with external services, or modify OpenScience's default behavior. - -For examples, check out the [plugins](/docs/ecosystem#plugins) created by the community. - ---- - -## Use a plugin - -There are two ways to load plugins. - ---- - -### From local files - -Place JavaScript or TypeScript files in the plugin directory. - -- `.openscience/plugins/` - Project-level plugins -- `~/.config/openscience/plugins/` - Global plugins - -Files in these directories are automatically loaded at startup. - ---- - -### From npm - -Specify npm packages in your config file. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "plugin": ["openscience-helicone-session", "openscience-wakatime", "@my-org/custom-plugin"] -} -``` - -Both regular and scoped npm packages are supported. - -Browse available plugins in the [ecosystem](/docs/ecosystem#plugins). - ---- - -### How plugins are installed - -**npm plugins** are installed automatically using Bun at startup. Packages and their dependencies are cached in `~/.cache/openscience/node_modules/`. - -**Local plugins** are loaded directly from the plugin directory. To use external packages, you must create a `package.json` within your config directory (see [Dependencies](#dependencies)), or publish the plugin to npm and [add it to your config](/docs/config#plugins). - ---- - -### Load order - -Plugins are loaded from all sources and all hooks run in sequence. The load order is: - -1. Global config (`~/.config/openscience/openscience.json`) -2. Project config (`openscience.json`) -3. Global plugin directory (`~/.config/openscience/plugins/`) -4. Project plugin directory (`.openscience/plugins/`) - -Duplicate npm packages with the same name and version are loaded once. However, a local plugin and an npm plugin with similar names are both loaded separately. - ---- - -## Create a plugin - -A plugin is a **JavaScript/TypeScript module** that exports one or more plugin -functions. Each function receives a context object and returns a hooks object. - ---- - -### Dependencies - -Local plugins and custom tools can use external npm packages. Add a `package.json` to your config directory with the dependencies you need. - -```json title=".openscience/package.json" -{ - "dependencies": { - "shescape": "^2.1.0" - } -} -``` - -OpenScience runs `bun install` at startup to install these. Your plugins and tools can then import them. - -```ts title=".openscience/plugins/my-plugin.ts" -import { escape } from "shescape" - -export const MyPlugin = async (ctx) => { - return { - "tool.execute.before": async (input, output) => { - if (input.tool === "bash") { - output.args.command = escape(output.args.command) - } - }, - } -} -``` - ---- - -### Basic structure - -```js title=".openscience/plugins/example.js" -export const MyPlugin = async ({ project, client, $, directory, worktree }) => { - console.log("Plugin initialized!") - - return { - // Hook implementations go here - } -} -``` - -The plugin function receives: - -- `project`: The current project information. -- `directory`: The current working directory. -- `worktree`: The git worktree path. -- `client`: An OpenScience SDK client for interacting with the AI. -- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) for executing commands. - ---- - -### TypeScript support - -For TypeScript plugins, you can import types from the plugin package: - -```ts title="my-plugin.ts" {1} -import type { Plugin } from "@synsci/plugin" - -export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { - return { - // Type-safe hook implementations - } -} -``` - ---- - -### Events - -Plugins can subscribe to events as seen below in the Examples section. Here is a list of the different events available. - -#### Command Events - -- `command.executed` - -#### File Events - -- `file.edited` -- `file.watcher.updated` - -#### Installation Events - -- `installation.updated` - -#### LSP Events - -- `lsp.client.diagnostics` -- `lsp.updated` - -#### Message Events - -- `message.part.removed` -- `message.part.updated` -- `message.removed` -- `message.updated` - -#### Permission Events - -- `permission.asked` -- `permission.replied` - -#### Server Events - -- `server.connected` - -#### Session Events - -- `session.created` -- `session.compacted` -- `session.deleted` -- `session.diff` -- `session.error` -- `session.idle` -- `session.status` -- `session.updated` - -#### Todo Events - -- `todo.updated` - -#### Tool Events - -- `tool.execute.after` -- `tool.execute.before` - ---- - -## Examples - -Here are some examples of plugins you can use to extend OpenScience. - ---- - -### Send notifications - -Send notifications when certain events occur: - -```js title=".openscience/plugins/notification.js" -export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { - return { - event: async ({ event }) => { - // Send notification on session completion - if (event.type === "session.idle") { - await $`osascript -e 'display notification "Session completed!" with title "OpenScience"'` - } - }, - } -} -``` - -We are using `osascript` to run AppleScript on macOS. Here we are using it to send notifications. - -:::note -If you're using the OpenScience desktop app, it can send system notifications automatically when a response is ready or when a session errors. -::: - ---- - -### .env protection - -Prevent OpenScience from reading `.env` files: - -```javascript title=".openscience/plugins/env-protection.js" -export const EnvProtection = async ({ project, client, $, directory, worktree }) => { - return { - "tool.execute.before": async (input, output) => { - if (input.tool === "read" && output.args.filePath.includes(".env")) { - throw new Error("Do not read .env files") - } - }, - } -} -``` - ---- - -### Custom tools - -Plugins can also add custom tools to OpenScience: - -```ts title=".openscience/plugins/custom-tools.ts" -import { type Plugin, tool } from "@synsci/plugin" - -export const CustomToolsPlugin: Plugin = async (ctx) => { - return { - tool: { - mytool: tool({ - description: "This is a custom tool", - args: { - foo: tool.schema.string(), - }, - async execute(args, context) { - const { directory, worktree } = context - return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` - }, - }), - }, - } -} -``` - -The `tool` helper creates a custom tool that OpenScience can call. It takes a Zod schema function and returns a tool definition with: - -- `description`: What the tool does -- `args`: Zod schema for the tool's arguments -- `execute`: Function that runs when the tool is called - -Your custom tools will be available to OpenScience alongside built-in tools. - ---- - -### Logging - -Use `client.app.log()` instead of `console.log` for structured logging: - -```ts title=".openscience/plugins/my-plugin.ts" -export const MyPlugin = async ({ client }) => { - await client.app.log({ - service: "my-plugin", - level: "info", - message: "Plugin initialized", - extra: { foo: "bar" }, - }) -} -``` - -Levels: `debug`, `info`, `warn`, `error`. See [SDK documentation](https://syntheticsciences.ai/docs/sdk) for details. - ---- - -### Compaction hooks - -Customize the context included when a session is compacted: - -```ts title=".openscience/plugins/compaction.ts" -import type { Plugin } from "@synsci/plugin" - -export const CompactionPlugin: Plugin = async (ctx) => { - return { - "experimental.session.compacting": async (input, output) => { - // Inject additional context into the compaction prompt - output.context.push(` -## Custom Context - -Include any state that should persist across compaction: -- Current task status -- Important decisions made -- Files being actively worked on -`) - }, - } -} -``` - -The `experimental.session.compacting` hook fires before the LLM generates a continuation summary. Use it to inject domain-specific context that the default compaction prompt would miss. - -You can also replace the compaction prompt entirely by setting `output.prompt`: - -```ts title=".openscience/plugins/custom-compaction.ts" -import type { Plugin } from "@synsci/plugin" - -export const CustomCompactionPlugin: Plugin = async (ctx) => { - return { - "experimental.session.compacting": async (input, output) => { - // Replace the entire compaction prompt - output.prompt = ` -You are generating a continuation prompt for a multi-agent swarm session. - -Summarize: -1. The current task and its status -2. Which files are being modified and by whom -3. Any blockers or dependencies between agents -4. The next steps to complete the work - -Format as a structured prompt that a new agent can use to resume work. -` - }, - } -} -``` - -When `output.prompt` is set, it completely replaces the default compaction prompt. The `output.context` array is ignored in this case. diff --git a/frontend/docs/src/content/docs/providers.mdx b/frontend/docs/src/content/docs/providers.mdx deleted file mode 100644 index 793e52c..0000000 --- a/frontend/docs/src/content/docs/providers.mdx +++ /dev/null @@ -1,1870 +0,0 @@ ---- -title: Providers -description: Using any LLM provider in OpenScience. ---- - - -OpenScience uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support **75+ LLM providers** and it supports running local models. - -To add a provider you need to: - -1. Add the API keys for the provider using the `/connect` command. -2. Configure the provider in your OpenScience config. - ---- - -### Credentials - -When you add a provider's API keys with the `/connect` command, they are stored -in `~/.local/share/openscience/auth.json`. - ---- - -### Config - -You can customize the providers through the `provider` section in your OpenScience -config. - ---- - -#### Base URL - -You can customize the base URL for any provider by setting the `baseURL` option. This is useful when using proxy services or custom endpoints. - -```json title="openscience.json" {6} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "anthropic": { - "options": { - "baseURL": "https://api.anthropic.com/v1" - } - } - } -} -``` - ---- - -## Atlas - -[Atlas](/docs/atlas) is Synthetic Sciences' managed platform. It includes a curated -set of models that have been tested and verified to work well with OpenScience, -served through the managed `synsci` provider and billed from a prepaid wallet. - -:::tip -If you are new, we recommend starting with Atlas. BYOK is free and needs no account. -::: - -1. Sign in from the CLI. - - ```bash - openscience connect login - ``` - -2. Approve the sign-in from your browser. Keys and billing live at [app.syntheticsciences.ai](https://app.syntheticsciences.ai/cli). - -3. Run `/models` to see the list of models we recommend. - - ```txt - /models - ``` - -It works like any other provider in OpenScience and is completely optional to use. - ---- - -## Directory - -Let's look at some of the providers in detail. If you'd like to add a provider to the -list, feel free to open a PR. - -:::note -Don't see a provider here? Submit a PR. -::: - ---- - -### 302.AI - -1. Head over to the [302.AI console](https://302.ai/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **302.AI**. - - ```txt - /connect - ``` - -3. Enter your 302.AI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - ---- - -### Amazon Bedrock - -To use Amazon Bedrock with OpenScience: - -1. Head over to the **Model catalog** in the Amazon Bedrock console and request - access to the models you want. - - :::tip - You need to have access to the model you want in Amazon Bedrock. - ::: - -2. **Configure authentication** using one of the following methods: - - #### Environment variables (quick start) - - Set one of these environment variables while running openscience: - - ```bash - # Option 1: Using AWS access keys - AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY openscience - - # Option 2: Using named AWS profile - AWS_PROFILE=my-profile openscience - - # Option 3: Using Bedrock bearer token - AWS_BEARER_TOKEN_BEDROCK=XXX openscience - ``` - - Or add them to your bash profile: - - ```bash title="~/.bash_profile" - export AWS_PROFILE=my-dev-profile - export AWS_REGION=us-east-1 - ``` - - #### Configuration file (recommended) - - For project-specific or persistent configuration, use `openscience.json`: - - ```json title="openscience.json" - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "my-aws-profile" - } - } - } - } - ``` - - **Available options:** - - `region`: AWS region (e.g., `us-east-1`, `eu-west-1`) - - `profile`: AWS named profile from `~/.aws/credentials` - - `endpoint`: Custom endpoint URL for VPC endpoints (alias for generic `baseURL` option) - - :::tip - Configuration file options take precedence over environment variables. - ::: - - #### Advanced: VPC endpoints - - If you're using VPC endpoints for Bedrock: - - ```json title="openscience.json" - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "production", - "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" - } - } - } - } - ``` - - :::note - The `endpoint` option is an alias for the generic `baseURL` option, using AWS-specific terminology. If both `endpoint` and `baseURL` are specified, `endpoint` takes precedence. - ::: - - #### Authentication methods - - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Create an IAM user and generate access keys in the AWS Console - - **`AWS_PROFILE`**: Use named profiles from `~/.aws/credentials`. First configure with `aws configure --profile my-profile` or `aws sso login` - - **`AWS_BEARER_TOKEN_BEDROCK`**: Generate long-term API keys from the Amazon Bedrock console - - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: For EKS IRSA (IAM Roles for Service Accounts) or other Kubernetes environments with OIDC federation. These environment variables are automatically injected by Kubernetes when using service account annotations. - - #### Authentication precedence - - Amazon Bedrock uses the following authentication priority: - 1. **Bearer Token**: `AWS_BEARER_TOKEN_BEDROCK` environment variable or token from `/connect` command - 2. **AWS Credential Chain**: Profile, access keys, shared credentials, IAM roles, Web Identity Tokens (EKS IRSA), instance metadata - - :::note - When a bearer token is set (via `/connect` or `AWS_BEARER_TOKEN_BEDROCK`), it takes precedence over all AWS credential methods including configured profiles. - ::: - -3. Run the `/models` command to select the model you want. - - ```txt - /models - ``` - -:::note -For custom inference profiles, use the model and provider name in the key and set the `id` property to the arn. This ensures correct caching: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "amazon-bedrock": { - // ... - "models": { - "anthropic-claude-sonnet-4.5": { - "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy" - } - } - } - } -} -``` - -::: - ---- - -### Anthropic - -1. Once you've signed up, run the `/connect` command and select Anthropic. - - ```txt - /connect - ``` - -2. Here you can select the **Claude Pro/Max** option and it'll open your browser - and ask you to authenticate. - - ```txt - ┌ Select auth method - │ - │ Claude Pro/Max - │ Create an API Key - │ Manually enter API Key - └ - ``` - -3. Now all the Anthropic models should be available when you use the `/models` command. - - ```txt - /models - ``` - -:::info -Using your Claude Pro/Max subscription in OpenScience is not officially supported by [Anthropic](https://anthropic.com). -::: - -##### Using API keys - -You can also select **Create an API Key** if you don't have a Pro/Max subscription. It'll also open your browser and ask you to login to Anthropic and give you a code you can paste into the workspace. - -Or if you already have an API key, you can select **Manually enter API Key** and paste it into the workspace. - ---- - -### Azure OpenAI - -:::note -If you encounter "I'm sorry, but I cannot assist with that request" errors, try changing the content filter from **DefaultV2** to **Default** in your Azure resource. -::: - -1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need: - - **Resource name**: This becomes part of your API endpoint (`https://RESOURCE_NAME.openai.azure.com/`) - - **API key**: Either `KEY 1` or `KEY 2` from your resource - -2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model. - - :::note - The deployment name must match the model name for OpenScience to work properly. - ::: - -3. Run the `/connect` command and search for **Azure**. - - ```txt - /connect - ``` - -4. Enter your API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -5. Set your resource name as an environment variable: - - ```bash - AZURE_RESOURCE_NAME=XXX openscience - ``` - - Or add it to your bash profile: - - ```bash title="~/.bash_profile" - export AZURE_RESOURCE_NAME=XXX - ``` - -6. Run the `/models` command to select your deployed model. - - ```txt - /models - ``` - ---- - -### Azure Cognitive Services - -1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need: - - **Resource name**: This becomes part of your API endpoint (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`) - - **API key**: Either `KEY 1` or `KEY 2` from your resource - -2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model. - - :::note - The deployment name must match the model name for OpenScience to work properly. - ::: - -3. Run the `/connect` command and search for **Azure Cognitive Services**. - - ```txt - /connect - ``` - -4. Enter your API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -5. Set your resource name as an environment variable: - - ```bash - AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX openscience - ``` - - Or add it to your bash profile: - - ```bash title="~/.bash_profile" - export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX - ``` - -6. Run the `/models` command to select your deployed model. - - ```txt - /models - ``` - ---- - -### Baseten - -1. Head over to the [Baseten](https://app.baseten.co/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Baseten**. - - ```txt - /connect - ``` - -3. Enter your Baseten API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - ---- - -### Cerebras - -1. Head over to the [Cerebras console](https://inference.cerebras.ai/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Cerebras**. - - ```txt - /connect - ``` - -3. Enter your Cerebras API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Qwen 3 Coder 480B_. - - ```txt - /models - ``` - ---- - -### Cloudflare AI Gateway - -Cloudflare AI Gateway lets you access models from OpenAI, Anthropic, Workers AI, and more through a unified endpoint. With [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) you don't need separate API keys for each provider. - -1. Head over to the [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to **AI** > **AI Gateway**, and create a new gateway. - -2. Set your Account ID and Gateway ID as environment variables. - - ```bash title="~/.bash_profile" - export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id - export CLOUDFLARE_GATEWAY_ID=your-gateway-id - ``` - -3. Run the `/connect` command and search for **Cloudflare AI Gateway**. - - ```txt - /connect - ``` - -4. Enter your Cloudflare API token. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - - Or set it as an environment variable. - - ```bash title="~/.bash_profile" - export CLOUDFLARE_API_TOKEN=your-api-token - ``` - -5. Run the `/models` command to select a model. - - ```txt - /models - ``` - - You can also add models through your OpenScience config. - - ```json title="openscience.json" - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "cloudflare-ai-gateway": { - "models": { - "openai/gpt-4o": {}, - "anthropic/claude-sonnet-4": {} - } - } - } - } - ``` - ---- - -### Cortecs - -1. Head over to the [Cortecs console](https://cortecs.ai/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Cortecs**. - - ```txt - /connect - ``` - -3. Enter your Cortecs API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Kimi K2 Instruct_. - - ```txt - /models - ``` - ---- - -### DeepSeek - -1. Head over to the [DeepSeek console](https://platform.deepseek.com/), create an account, and click **Create new API key**. - -2. Run the `/connect` command and search for **DeepSeek**. - - ```txt - /connect - ``` - -3. Enter your DeepSeek API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a DeepSeek model like _DeepSeek Reasoner_. - - ```txt - /models - ``` - ---- - -### Deep Infra - -1. Head over to the [Deep Infra dashboard](https://deepinfra.com/dash), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Deep Infra**. - - ```txt - /connect - ``` - -3. Enter your Deep Infra API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - ---- - -### Firmware - -1. Head over to the [Firmware dashboard](https://app.firmware.ai/signup), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Firmware**. - - ```txt - /connect - ``` - -3. Enter your Firmware API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - ---- - -### Fireworks AI - -1. Head over to the [Fireworks AI console](https://app.fireworks.ai/), create an account, and click **Create API Key**. - -2. Run the `/connect` command and search for **Fireworks AI**. - - ```txt - /connect - ``` - -3. Enter your Fireworks AI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Kimi K2 Instruct_. - - ```txt - /models - ``` - ---- - -### GitLab Duo - -GitLab Duo provides AI-powered agentic chat with native tool calling capabilities through GitLab's Anthropic proxy. - -1. Run the `/connect` command and select GitLab. - - ```txt - /connect - ``` - -2. Choose your authentication method: - - ```txt - ┌ Select auth method - │ - │ OAuth (Recommended) - │ Personal Access Token - └ - ``` - - #### Using OAuth (recommended) - - Select **OAuth** and your browser will open for authorization. - - #### Using personal access token - 1. Go to [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens) - 2. Click **Add new token** - 3. Name: `OpenScience`, Scopes: `api` - 4. Copy the token (starts with `glpat-`) - 5. Enter it in the workspace - -3. Run the `/models` command to see available models. - - ```txt - /models - ``` - - Three Claude-based models are available: - - **duo-chat-haiku-4-5** (Default): Fast responses for quick tasks - - **duo-chat-sonnet-4-5**: Balanced performance for most workflows - - **duo-chat-opus-4-5**: Most capable for complex analysis - -:::note -You can also specify 'GITLAB_TOKEN' environment variable if you don't want -to store token in OpenScience auth storage. -::: - -##### Self-hosted GitLab - -:::note[compliance note] -OpenScience uses a small model for some AI tasks like generating the session title. -It is configured to use gpt-5-nano by default, hosted by Atlas. To lock OpenScience -to only use your own GitLab-hosted instance, add the following to your -`openscience.json` file. It is also recommended to disable session sharing. - -```json -{ - "$schema": "https://syntheticsciences.ai/config.json", - "small_model": "gitlab/duo-chat-haiku-4-5", - "share": "disabled" -} -``` - -::: - -For self-hosted GitLab instances: - -```bash -export GITLAB_INSTANCE_URL=https://gitlab.company.com -export GITLAB_TOKEN=glpat-... -``` - -If your instance runs a custom AI Gateway: - -```bash -GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com -``` - -Or add to your bash profile: - -```bash title="~/.bash_profile" -export GITLAB_INSTANCE_URL=https://gitlab.company.com -export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com -export GITLAB_TOKEN=glpat-... -``` - -:::note -Your GitLab administrator must enable the following: - -1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) for the user, group, or instance -2. Feature flags (via Rails console): - - `agent_platform_claude_code` - - `third_party_agents_enabled` - ::: - -##### OAuth for self-hosted instances - -In order to make Oauth working for your self-hosted instance, you need to create -a new application (Settings → Applications) with the -callback URL `http://127.0.0.1:8080/callback` and following scopes: - -- api (Access the API on your behalf) -- read_user (Read your personal information) -- read_repository (Allows read-only access to the repository) - -Then expose application ID as environment variable: - -```bash -export GITLAB_OAUTH_CLIENT_ID=your_application_id_here -``` - -More documentation on [openscience-gitlab-auth](https://www.npmjs.com/package/@gitlab/openscience-gitlab-auth) homepage. - -##### Configuration - -Customize through `openscience.json`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "gitlab": { - "options": { - "instanceUrl": "https://gitlab.com", - "featureFlags": { - "duo_agent_platform_agentic_chat": true, - "duo_agent_platform": true - } - } - } - } -} -``` - -##### GitLab API tools (optional, but highly recommended) - -To access GitLab tools (merge requests, issues, pipelines, CI/CD, etc.): - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "plugin": ["@gitlab/openscience-gitlab-plugin"] -} -``` - -This plugin adds GitLab repository management, including MR reviews, issue tracking, and pipeline monitoring. - ---- - -### GitHub Copilot - -To use your GitHub Copilot subscription with openscience: - -:::note -Some models might need a [Pro+ -subscription](https://github.com/features/copilot/plans) to use. - -Some models need to be manually enabled in your [GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). -::: - -1. Run the `/connect` command and search for GitHub Copilot. - - ```txt - /connect - ``` - -2. Navigate to [github.com/login/device](https://github.com/login/device) and enter the code. - - ```txt - ┌ Login with GitHub Copilot - │ - │ https://github.com/login/device - │ - │ Enter code: 8F43-6FCF - │ - └ Waiting for authorization... - ``` - -3. Now run the `/models` command to select the model you want. - - ```txt - /models - ``` - ---- - -### Google Vertex AI - -To use Google Vertex AI with OpenScience: - -1. Head over to the **Model Garden** in the Google Cloud Console and check the - models available in your region. - - :::note - You need to have a Google Cloud project with Vertex AI API enabled. - ::: - -2. Set the required environment variables: - - `GOOGLE_CLOUD_PROJECT`: Your Google Cloud project ID - - `VERTEX_LOCATION` (optional): The region for Vertex AI (defaults to `global`) - - Authentication (choose one): - - `GOOGLE_APPLICATION_CREDENTIALS`: Path to your service account JSON key file - - Authenticate using gcloud CLI: `gcloud auth application-default login` - - Set them while running openscience. - - ```bash - GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id openscience - ``` - - Or add them to your bash profile. - - ```bash title="~/.bash_profile" - export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json - export GOOGLE_CLOUD_PROJECT=your-project-id - export VERTEX_LOCATION=global - ``` - -:::tip -The `global` region improves availability and reduces errors at no extra cost. Use regional endpoints (e.g., `us-central1`) for data residency requirements. [Learn more](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) -::: - -3. Run the `/models` command to select the model you want. - - ```txt - /models - ``` - ---- - -### Groq - -1. Head over to the [Groq console](https://console.groq.com/), click **Create API Key**, and copy the key. - -2. Run the `/connect` command and search for Groq. - - ```txt - /connect - ``` - -3. Enter the API key for the provider. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select the one you want. - - ```txt - /models - ``` - ---- - -### Hugging Face - -[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) provides access to open models supported by 17+ providers. - -1. Head over to [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) to create a token with permission to make calls to Inference Providers. - -2. Run the `/connect` command and search for **Hugging Face**. - - ```txt - /connect - ``` - -3. Enter your Hugging Face token. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Kimi-K2-Instruct_ or _GLM-4.6_. - - ```txt - /models - ``` - ---- - -### Helicone - -[Helicone](https://helicone.ai) is an LLM observability platform that provides logging, monitoring, and analytics for your AI applications. The Helicone AI Gateway routes your requests to the appropriate provider automatically based on the model. - -1. Head over to [Helicone](https://helicone.ai), create an account, and generate an API key from your dashboard. - -2. Run the `/connect` command and search for **Helicone**. - - ```txt - /connect - ``` - -3. Enter your Helicone API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - -For more providers and advanced features like caching and rate limiting, check the [Helicone documentation](https://docs.helicone.ai). - -#### Optional configs - -In the event you see a feature or model from Helicone that isn't configured automatically through OpenScience, you can always configure it yourself. - -Here's [Helicone's Model Directory](https://helicone.ai/models), you'll need this to grab the IDs of the models you want to add. - -```jsonc title="~/.config/openscience/openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "helicone": { - "npm": "@ai-sdk/openai-compatible", - "name": "Helicone", - "options": { - "baseURL": "https://ai-gateway.helicone.ai", - }, - "models": { - "gpt-4o": { - // Model ID (from Helicone's model directory page) - "name": "GPT-4o", // Your own custom name for the model - }, - "claude-sonnet-4-20250514": { - "name": "Claude Sonnet 4", - }, - }, - }, - }, -} -``` - -#### Custom headers - -Helicone supports custom headers for features like caching, user tracking, and session management. Add them to your provider config using `options.headers`: - -```jsonc title="~/.config/openscience/openscience.jsonc" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "helicone": { - "npm": "@ai-sdk/openai-compatible", - "name": "Helicone", - "options": { - "baseURL": "https://ai-gateway.helicone.ai", - "headers": { - "Helicone-Cache-Enabled": "true", - "Helicone-User-Id": "openscience", - }, - }, - }, - }, -} -``` - -##### Session tracking - -Helicone's [Sessions](https://docs.helicone.ai/features/sessions) feature lets you group related LLM requests together. Use the [openscience-helicone-session](https://github.com/H2Shami/openscience-helicone-session) plugin to automatically log each OpenScience conversation as a session in Helicone. - -```bash -npm install -g openscience-helicone-session -``` - -Add it to your config. - -```json title="openscience.json" -{ - "plugin": ["openscience-helicone-session"] -} -``` - -The plugin injects `Helicone-Session-Id` and `Helicone-Session-Name` headers into your requests. In Helicone's Sessions page, you'll see each OpenScience conversation listed as a separate session. - -##### Common Helicone headers - -| Header | Description | -| -------------------------- | ------------------------------------------------------------- | -| `Helicone-Cache-Enabled` | Enable response caching (`true`/`false`) | -| `Helicone-User-Id` | Track metrics by user | -| `Helicone-Property-[Name]` | Add custom properties (e.g., `Helicone-Property-Environment`) | -| `Helicone-Prompt-Id` | Associate requests with prompt versions | - -See the [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for all available headers. - ---- - -### llama.cpp - -You can configure OpenScience to use local models through [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server utility - -```json title="openscience.json" "llama.cpp" {5, 6, 8, 10-15} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "llama.cpp": { - "npm": "@ai-sdk/openai-compatible", - "name": "llama-server (local)", - "options": { - "baseURL": "http://127.0.0.1:8080/v1" - }, - "models": { - "qwen3-coder:a3b": { - "name": "Qwen3-Coder: a3b-30b (local)", - "limit": { - "context": 128000, - "output": 65536 - } - } - } - } - } -} -``` - -In this example: - -- `llama.cpp` is the custom provider ID. This can be any string you want. -- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. -- `name` is the display name for the provider in the UI. -- `options.baseURL` is the endpoint for the local server. -- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list. - ---- - -### IO.NET - -IO.NET offers 17 models optimized for various use cases: - -1. Head over to the [IO.NET console](https://ai.io.net/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **IO.NET**. - - ```txt - /connect - ``` - -3. Enter your IO.NET API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - ---- - -### LM Studio - -You can configure OpenScience to use local models through LM Studio. - -```json title="openscience.json" "lmstudio" {5, 6, 8, 10-14} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "lmstudio": { - "npm": "@ai-sdk/openai-compatible", - "name": "LM Studio (local)", - "options": { - "baseURL": "http://127.0.0.1:1234/v1" - }, - "models": { - "google/gemma-3n-e4b": { - "name": "Gemma 3n-e4b (local)" - } - } - } - } -} -``` - -In this example: - -- `lmstudio` is the custom provider ID. This can be any string you want. -- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. -- `name` is the display name for the provider in the UI. -- `options.baseURL` is the endpoint for the local server. -- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list. - ---- - -### Moonshot AI - -To use Kimi K2 from Moonshot AI: - -1. Head over to the [Moonshot AI console](https://platform.moonshot.ai/console), create an account, and click **Create API key**. - -2. Run the `/connect` command and search for **Moonshot AI**. - - ```txt - /connect - ``` - -3. Enter your Moonshot API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select _Kimi K2_. - - ```txt - /models - ``` - ---- - -### MiniMax - -1. Head over to the [MiniMax API Console](https://platform.minimax.io/login), create an account, and generate an API key. - -2. Run the `/connect` command and search for **MiniMax**. - - ```txt - /connect - ``` - -3. Enter your MiniMax API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _M2.1_. - - ```txt - /models - ``` - ---- - -### Nebius Token Factory - -1. Head over to the [Nebius Token Factory console](https://tokenfactory.nebius.com/), create an account, and click **Add Key**. - -2. Run the `/connect` command and search for **Nebius Token Factory**. - - ```txt - /connect - ``` - -3. Enter your Nebius Token Factory API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Kimi K2 Instruct_. - - ```txt - /models - ``` - ---- - -### Ollama - -You can configure OpenScience to use local models through Ollama. - -```json title="openscience.json" "ollama" {5, 6, 8, 10-14} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "ollama": { - "npm": "@ai-sdk/openai-compatible", - "name": "Ollama (local)", - "options": { - "baseURL": "http://localhost:11434/v1" - }, - "models": { - "llama2": { - "name": "Llama 2" - } - } - } - } -} -``` - -In this example: - -- `ollama` is the custom provider ID. This can be any string you want. -- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API. -- `name` is the display name for the provider in the UI. -- `options.baseURL` is the endpoint for the local server. -- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list. - -:::tip -If tool calls aren't working, try increasing `num_ctx` in Ollama. Start around 16k to 32k. -::: - ---- - -### Ollama Cloud - -To use Ollama Cloud with OpenScience: - -1. Head over to [https://ollama.com/](https://ollama.com/) and sign in or create an account. - -2. Navigate to **Settings** > **Keys** and click **Add API Key** to generate a new API key. - -3. Copy the API key for use in OpenScience. - -4. Run the `/connect` command and search for **Ollama Cloud**. - - ```txt - /connect - ``` - -5. Enter your Ollama Cloud API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -6. **Important**: Before using cloud models in OpenScience, you must pull the model information locally: - - ```bash - ollama pull gpt-oss:20b-cloud - ``` - -7. Run the `/models` command to select your Ollama Cloud model. - - ```txt - /models - ``` - ---- - -### OpenAI - -We recommend signing up for [ChatGPT Plus or Pro](https://chatgpt.com/pricing). - -1. Once you've signed up, run the `/connect` command and select OpenAI. - - ```txt - /connect - ``` - -2. Here you can select the **ChatGPT Plus/Pro** option and it'll open your browser - and ask you to authenticate. - - ```txt - ┌ Select auth method - │ - │ ChatGPT Plus/Pro - │ Manually enter API Key - └ - ``` - -3. Now all the OpenAI models should be available when you use the `/models` command. - - ```txt - /models - ``` - -##### Using API keys - -If you already have an API key, you can select **Manually enter API Key** and paste it into the workspace. - ---- - -### Atlas - -Atlas is Synthetic Sciences' managed platform with a curated set of tested and verified models, served through the `synsci` provider. [Learn more](/docs/atlas). - -1. Run the following command and approve the sign-in from your browser. - - ```bash - openscience connect login - ``` - -2. On headless or CI machines, create an API key at [app.syntheticsciences.ai](https://app.syntheticsciences.ai/cli) and pass it directly. - - ```bash - openscience connect login --key thk_... - ``` - -3. Run the `/models` command to select one of the curated `synsci/...` models. - - ```txt - /models - ``` - ---- - -### OpenRouter - -1. Head over to the [OpenRouter dashboard](https://openrouter.ai/settings/keys), click **Create API Key**, and copy the key. - -2. Run the `/connect` command and search for OpenRouter. - - ```txt - /connect - ``` - -3. Enter the API key for the provider. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Many OpenRouter models are preloaded by default, run the `/models` command to select the one you want. - - ```txt - /models - ``` - - You can also add additional models through your OpenScience config. - - ```json title="openscience.json" {6} - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "openrouter": { - "models": { - "somecoolnewmodel": {} - } - } - } - } - ``` - -5. You can also customize them through your OpenScience config. Here's an example of specifying a provider - - ```json title="openscience.json" - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "openrouter": { - "models": { - "moonshotai/kimi-k2": { - "options": { - "provider": { - "order": ["baseten"], - "allow_fallbacks": false - } - } - } - } - } - } - } - ``` - ---- - -### SAP AI Core - -SAP AI Core provides access to 40+ models from OpenAI, Anthropic, Google, Amazon, Meta, Mistral, and AI21 through a unified platform. - -1. Go to your [SAP BTP Cockpit](https://account.hana.ondemand.com/), navigate to your SAP AI Core service instance, and create a service key. - - :::tip - The service key is a JSON object containing `clientid`, `clientsecret`, `url`, and `serviceurls.AI_API_URL`. You can find your AI Core instance under **Services** > **Instances and Subscriptions** in the BTP Cockpit. - ::: - -2. Run the `/connect` command and search for **SAP AI Core**. - - ```txt - /connect - ``` - -3. Enter your service key JSON. - - ```txt - ┌ Service key - │ - │ - └ enter - ``` - - Or set the `AICORE_SERVICE_KEY` environment variable: - - ```bash - AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' openscience - ``` - - Or add it to your bash profile: - - ```bash title="~/.bash_profile" - export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' - ``` - -4. Optionally set deployment ID and resource group: - - ```bash - AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group openscience - ``` - - :::note - These settings are optional and should be configured according to your SAP AI Core setup. - ::: - -5. Run the `/models` command to select from 40+ available models. - - ```txt - /models - ``` - ---- - -### OVHcloud AI Endpoints - -1. Head over to the [OVHcloud panel](https://ovh.com/manager). Navigate to the `Public Cloud` section, `AI & Machine Learning` > `AI Endpoints` and in `API Keys` tab, click **Create a new API key**. - -2. Run the `/connect` command and search for **OVHcloud AI Endpoints**. - - ```txt - /connect - ``` - -3. Enter your OVHcloud AI Endpoints API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _gpt-oss-120b_. - - ```txt - /models - ``` - ---- - -### Scaleway - -To use [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) with OpenScience: - -1. Head over to the [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys) to generate a new API key. - -2. Run the `/connect` command and search for **Scaleway**. - - ```txt - /connect - ``` - -3. Enter your Scaleway API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _devstral-2-123b-instruct-2512_ or _gpt-oss-120b_. - - ```txt - /models - ``` - ---- - -### Together AI - -1. Head over to the [Together AI console](https://api.together.ai), create an account, and click **Add Key**. - -2. Run the `/connect` command and search for **Together AI**. - - ```txt - /connect - ``` - -3. Enter your Together AI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Kimi K2 Instruct_. - - ```txt - /models - ``` - ---- - -### Venice AI - -1. Head over to the [Venice AI console](https://venice.ai), create an account, and generate an API key. - -2. Run the `/connect` command and search for **Venice AI**. - - ```txt - /connect - ``` - -3. Enter your Venice AI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Llama 3.3 70B_. - - ```txt - /models - ``` - ---- - -### Vercel AI Gateway - -Vercel AI Gateway lets you access models from OpenAI, Anthropic, Google, xAI, and more through a unified endpoint. Models are offered at list price with no markup. - -1. Head over to the [Vercel dashboard](https://vercel.com/), navigate to the **AI Gateway** tab, and click **API keys** to create a new API key. - -2. Run the `/connect` command and search for **Vercel AI Gateway**. - - ```txt - /connect - ``` - -3. Enter your Vercel AI Gateway API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model. - - ```txt - /models - ``` - -You can also customize models through your OpenScience config. Here's an example of specifying provider routing order. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "vercel": { - "models": { - "anthropic/claude-sonnet-4": { - "options": { - "order": ["anthropic", "vertex"] - } - } - } - } - } -} -``` - -Some useful routing options: - -| Option | Description | -| ------------------- | ---------------------------------------------------- | -| `order` | Provider sequence to try | -| `only` | Restrict to specific providers | -| `zeroDataRetention` | Only use providers with zero data retention policies | - ---- - -### xAI - -1. Head over to the [xAI console](https://console.x.ai/), create an account, and generate an API key. - -2. Run the `/connect` command and search for **xAI**. - - ```txt - /connect - ``` - -3. Enter your xAI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _Grok Beta_. - - ```txt - /models - ``` - ---- - -### Z.AI - -1. Head over to the [Z.AI API console](https://z.ai/manage-apikey/apikey-list), create an account, and click **Create a new API key**. - -2. Run the `/connect` command and search for **Z.AI**. - - ```txt - /connect - ``` - - If you are subscribed to the **GLM Coding Plan**, select **Z.AI Coding Plan**. - -3. Enter your Z.AI API key. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Run the `/models` command to select a model like _GLM-4.7_. - - ```txt - /models - ``` - ---- - -### ZenMux - -1. Head over to the [ZenMux dashboard](https://zenmux.ai/settings/keys), click **Create API Key**, and copy the key. - -2. Run the `/connect` command and search for ZenMux. - - ```txt - /connect - ``` - -3. Enter the API key for the provider. - - ```txt - ┌ API key - │ - │ - └ enter - ``` - -4. Many ZenMux models are preloaded by default, run the `/models` command to select the one you want. - - ```txt - /models - ``` - - You can also add additional models through your OpenScience config. - - ```json title="openscience.json" {6} - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "zenmux": { - "models": { - "somecoolnewmodel": {} - } - } - } - } - ``` - ---- - -## Custom provider - -To add any **OpenAI-compatible** provider that's not listed in the `/connect` command: - -:::tip -You can use any OpenAI-compatible provider with OpenScience. Most modern AI providers offer OpenAI-compatible APIs. -::: - -1. Run the `/connect` command and scroll down to **Other**. - - ```bash - $ /connect - - ┌ Add credential - │ - ◆ Select provider - │ ... - │ ● Other - └ - ``` - -2. Enter a unique ID for the provider. - - ```bash - $ /connect - - ┌ Add credential - │ - ◇ Enter provider id - │ myprovider - └ - ``` - - :::note - Choose a memorable ID, you'll use this in your config file. - ::: - -3. Enter your API key for the provider. - - ```bash - $ /connect - - ┌ Add credential - │ - ▲ This only stores a credential for myprovider - you will need to configure it in openscience.json, check the docs for examples. - │ - ◇ Enter your API key - │ sk-... - └ - ``` - -4. Create or update your `openscience.json` file in your project directory: - - ```json title="openscience.json" ""myprovider"" {5-15} - { - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "myprovider": { - "npm": "@ai-sdk/openai-compatible", - "name": "My AI ProviderDisplay Name", - "options": { - "baseURL": "https://api.myprovider.com/v1" - }, - "models": { - "my-model-name": { - "name": "My Model Display Name" - } - } - } - } - } - ``` - - Here are the configuration options: - - **npm**: AI SDK package to use, `@ai-sdk/openai-compatible` for OpenAI-compatible providers - - **name**: Display name in UI. - - **models**: Available models. - - **options.baseURL**: API endpoint URL. - - **options.apiKey**: Optionally set the API key, if not using auth. - - **options.headers**: Optionally set custom headers. - - More on the advanced options in the example below. - -5. Run the `/models` command and your custom provider and models will appear in the selection list. - ---- - -##### Example - -Here's an example setting the `apiKey`, `headers`, and model `limit` options. - -```json title="openscience.json" {9,11,17-20} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "provider": { - "myprovider": { - "npm": "@ai-sdk/openai-compatible", - "name": "My AI ProviderDisplay Name", - "options": { - "baseURL": "https://api.myprovider.com/v1", - "apiKey": "{env:ANTHROPIC_API_KEY}", - "headers": { - "Authorization": "Bearer custom-token" - } - }, - "models": { - "my-model-name": { - "name": "My Model Display Name", - "limit": { - "context": 200000, - "output": 65536 - } - } - } - } - } -} -``` - -Configuration details: - -- **apiKey**: Set using `env` variable syntax, [learn more](/docs/config#env-vars). -- **headers**: Custom headers sent with each request. -- **limit.context**: Maximum input tokens the model accepts. -- **limit.output**: Maximum tokens the model can generate. - -The `limit` fields allow OpenScience to understand how much context you have left. Standard providers pull these from models.dev automatically. - ---- - -## Troubleshooting - -If you are having trouble with configuring a provider, check the following: - -1. **Check the auth setup**: Run `openscience auth list` to see if the credentials - for the provider are added to your config. - - This doesn't apply to providers like Amazon Bedrock, that rely on environment variables for their auth. - -2. For custom providers, check the OpenScience config and: - - Make sure the provider ID used in the `/connect` command matches the ID in your OpenScience config. - - The right npm package is used for the provider. For example, use `@ai-sdk/cerebras` for Cerebras. And for all other OpenAI-compatible providers, use `@ai-sdk/openai-compatible`. - - Check correct API endpoint is used in the `options.baseURL` field. diff --git a/frontend/docs/src/content/docs/rules.mdx b/frontend/docs/src/content/docs/rules.mdx deleted file mode 100644 index 62be427..0000000 --- a/frontend/docs/src/content/docs/rules.mdx +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Rules -description: Set custom instructions for OpenScience. ---- - -You can provide custom instructions to OpenScience by creating an `AGENTS.md` file. This is similar to Cursor's rules. It contains instructions that will be included in the LLM's context to customize its behavior for your specific project. - ---- - -## Initialize - -To create a new `AGENTS.md` file, you can run the `/init` command in OpenScience. - -:::tip -You should commit your project's `AGENTS.md` file to Git. -::: - -This will scan your project and all its contents to understand what the project is about and generate an `AGENTS.md` file with it. This helps OpenScience navigate the project better. - -If you have an existing `AGENTS.md` file, this will try to add to it. - ---- - -## Example - -You can also just create this file manually. Here's an example of some things you can put into an `AGENTS.md` file. - -```markdown title="AGENTS.md" -# SST v3 Monorepo Project - -This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management. - -## Project Structure - -- `packages/` - Contains all workspace packages (functions, core, web, etc.) -- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts) -- `sst.config.ts` - Main SST configuration with dynamic imports - -## Code Standards - -- Use TypeScript with strict mode enabled -- Shared code goes in `packages/core/` with proper exports configuration -- Functions go in `packages/functions/` -- Infrastructure should be split into logical files in `infra/` - -## Monorepo Conventions - -- Import shared modules using workspace names: `@my-app/core/example` -``` - -We are adding project-specific instructions here and this will be shared across your team. - ---- - -## Types - -OpenScience also supports reading the `AGENTS.md` file from multiple locations, each used for a different purpose. - -### Project - -Place an `AGENTS.md` in your project root for project-specific rules. These only apply when you are working in this directory or its sub-directories. - -### Global - -You can also have global rules in a `~/.config/openscience/AGENTS.md` file. This gets applied across all OpenScience sessions. - -Since this isn't committed to Git or shared with your team, we recommend using this to specify any personal rules that the LLM should follow. - -### Claude Code compatibility - -For users migrating from Claude Code, OpenScience supports Claude Code's file conventions as fallbacks: - -- **Project rules**: `CLAUDE.md` in your project directory (used if no `AGENTS.md` exists) -- **Global rules**: `~/.claude/CLAUDE.md` (used if no `~/.config/openscience/AGENTS.md` exists) -- **Skills**: `~/.claude/skills/`, see [Agent Skills](/docs/skills/) for details - -To disable Claude Code compatibility, set one of these environment variables: - -```bash -export OPENSCIENCE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support -export OPENSCIENCE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md -export OPENSCIENCE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills -``` - ---- - -## Precedence - -When OpenScience starts, it looks for rule files in this order: - -1. **Local files** by traversing up from the current directory (`AGENTS.md`, `CLAUDE.md`) -2. **Global file** at `~/.config/openscience/AGENTS.md` -3. **Claude Code file** at `~/.claude/CLAUDE.md` (unless disabled) - -The first matching file wins in each category. For example, if you have both `AGENTS.md` and `CLAUDE.md`, only `AGENTS.md` is used. Similarly, `~/.config/openscience/AGENTS.md` takes precedence over `~/.claude/CLAUDE.md`. - ---- - -## Custom instructions - -You can specify custom instruction files in your `openscience.json` or the global `~/.config/openscience/openscience.json`. This allows you and your team to reuse existing rules rather than having to duplicate them to AGENTS.md. - -Example: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"] -} -``` - -You can also use remote URLs to load instructions from the web. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"] -} -``` - -Remote instructions are fetched with a 5 second timeout. - -All instruction files are combined with your `AGENTS.md` files. - ---- - -## Referencing external files - -While OpenScience doesn't automatically parse file references in `AGENTS.md`, you can get similar behavior in two ways: - -### Using openscience.json - -The recommended approach is to use the `instructions` field in `openscience.json`: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] -} -``` - -### Manual instructions in AGENTS.md - -You can teach OpenScience to read external files by providing explicit instructions in your `AGENTS.md`. Here's a practical example: - -```markdown title="AGENTS.md" -# TypeScript Project Rules - -## External File Loading - -CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand. - -Instructions: - -- Do NOT preemptively load all references - use lazy loading based on actual need -- When loaded, treat content as mandatory instructions that override defaults -- Follow references recursively when needed - -## Development Guidelines - -For TypeScript code style and best practices: @docs/typescript-guidelines.md -For React component architecture and hooks patterns: @docs/react-patterns.md -For REST API design and error handling: @docs/api-standards.md -For testing strategies and coverage requirements: @test/testing-guidelines.md - -## General Guidelines - -Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md. -``` - -This approach allows you to: - -- Create modular, reusable rule files -- Share rules across projects via symlinks or git submodules -- Keep AGENTS.md concise while referencing detailed guidelines -- Ensure OpenScience loads files only when needed for the specific task - -:::tip -For monorepos or projects with shared standards, using `openscience.json` with glob patterns (like `packages/*/AGENTS.md`) is more maintainable than manual instructions. -::: diff --git a/frontend/docs/src/content/docs/sdk.mdx b/frontend/docs/src/content/docs/sdk.mdx deleted file mode 100644 index 100085e..0000000 --- a/frontend/docs/src/content/docs/sdk.mdx +++ /dev/null @@ -1,360 +0,0 @@ ---- -title: SDK -description: Type-safe JS client for the OpenScience server. ---- - -import config from "../../../config.mjs" -export const typesUrl = `${config.github}/blob/dev/tooling/sdk/js/src/gen/types.gen.ts` - -The OpenScience JS/TS SDK provides a type-safe client for interacting with the server. -Use it to build integrations and control OpenScience programmatically. - -[Learn more](/docs/server) about how the server works. For examples, check out the [projects](/docs/ecosystem#projects) built by the community. - ---- - -## Install - -Install the SDK from npm: - -```bash -npm install @synsci/sdk -``` - ---- - -## Create client - -Create an instance of OpenScience: - -```javascript -import { createOpenScience } from "@synsci/sdk" - -const { client } = await createOpenScience() -``` - -This starts both a server and a client - -#### Options - -| Option | Type | Description | Default | -| ---------- | ------------- | ------------------------------ | ----------- | -| `hostname` | `string` | Server hostname | `127.0.0.1` | -| `port` | `number` | Server port | `4096` | -| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` | -| `timeout` | `number` | Timeout in ms for server start | `5000` | -| `config` | `Config` | Configuration object | `{}` | - ---- - -## Config - -You can pass a configuration object to customize behavior. The instance still picks up your `openscience.json`, but you can override or add configuration inline: - -```javascript -import { createOpenScience } from "@synsci/sdk" - -const openscience = await createOpenScience({ - hostname: "127.0.0.1", - port: 4096, - config: { - model: "anthropic/claude-3-5-sonnet-20241022", - }, -}) - -console.log(`Server running at ${openscience.server.url}`) - -openscience.server.close() -``` - -## Client only - -If you already have a running instance of OpenScience, you can create a client instance to connect to it: - -```javascript -import { createOpenScienceClient } from "@synsci/sdk" - -const client = createOpenScienceClient({ - baseUrl: "http://localhost:4096", -}) -``` - -#### Options - -| Option | Type | Description | Default | -| --------------- | ---------- | -------------------------------- | ----------------------- | -| `baseUrl` | `string` | URL of the server | `http://localhost:4096` | -| `fetch` | `function` | Custom fetch implementation | `globalThis.fetch` | -| `parseAs` | `string` | Response parsing method | `auto` | -| `responseStyle` | `string` | Return style: `data` or `fields` | `fields` | -| `throwOnError` | `boolean` | Throw errors instead of return | `false` | - ---- - -## Types - -The SDK includes TypeScript definitions for all API types. Import them directly: - -```typescript -import type { Session, Message, Part } from "@synsci/sdk" -``` - -All types are generated from the server's OpenAPI specification and available in the types file. - ---- - -## Errors - -The SDK can throw errors that you can catch and handle: - -```typescript -try { - await client.session.get({ path: { id: "invalid-id" } }) -} catch (error) { - console.error("Failed to get session:", (error as Error).message) -} -``` - ---- - -## APIs - -The SDK exposes all server APIs through a type-safe client. - ---- - -### Global - -| Method | Description | Response | -| ----------------- | ------------------------------- | ------------------------------------ | -| `global.health()` | Check server health and version | `{ healthy: true, version: string }` | - ---- - -#### Examples - -```javascript -const health = await client.global.health() -console.log(health.data.version) -``` - ---- - -### App - -| Method | Description | Response | -| -------------- | ------------------------- | ------------------------------------------- | -| `app.log()` | Write a log entry | `boolean` | -| `app.agents()` | List all available agents | Agent[] | - ---- - -#### Examples - -```javascript -// Write a log entry -await client.app.log({ - body: { - service: "my-app", - level: "info", - message: "Operation completed", - }, -}) - -// List available agents -const agents = await client.app.agents() -``` - ---- - -### Project - -| Method | Description | Response | -| ------------------- | ------------------- | --------------------------------------------- | -| `project.list()` | List all projects | Project[] | -| `project.current()` | Get current project | Project | - ---- - -#### Examples - -```javascript -// List all projects -const projects = await client.project.list() - -// Get current project -const currentProject = await client.project.current() -``` - ---- - -### Path - -| Method | Description | Response | -| ------------ | ---------------- | ---------------------------------------- | -| `path.get()` | Get current path | Path | - ---- - -#### Examples - -```javascript -// Get current path information -const pathInfo = await client.path.get() -``` - ---- - -### Config - -| Method | Description | Response | -| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `config.get()` | Get config info | Config | -| `config.providers()` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | - ---- - -#### Examples - -```javascript -const config = await client.config.get() - -const { providers, default: defaults } = await client.config.providers() -``` - ---- - -### Sessions - -| Method | Description | Notes | -| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | List sessions | Returns Session[] | -| `session.get({ path })` | Get session | Returns Session | -| `session.children({ path })` | List child sessions | Returns Session[] | -| `session.create({ body })` | Create session | Returns Session | -| `session.delete({ path })` | Delete session | Returns `boolean` | -| `session.update({ path, body })` | Update session properties | Returns Session | -| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | -| `session.abort({ path })` | Abort a running session | Returns `boolean` | -| `session.share({ path })` | Share session | Returns Session | -| `session.unshare({ path })` | Unshare session | Returns Session | -| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | -| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns AssistantMessage with AI response | -| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | -| `session.revert({ path, body })` | Revert a message | Returns Session | -| `session.unrevert({ path })` | Restore reverted messages | Returns Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | - ---- - -#### Examples - -```javascript -// Create and manage sessions -const session = await client.session.create({ - body: { title: "My session" }, -}) - -const sessions = await client.session.list() - -// Send a prompt message -const result = await client.session.prompt({ - path: { id: session.id }, - body: { - model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" }, - parts: [{ type: "text", text: "Hello!" }], - }, -}) - -// Inject context without triggering AI response (useful for plugins) -await client.session.prompt({ - path: { id: session.id }, - body: { - noReply: true, - parts: [{ type: "text", text: "You are a helpful assistant." }], - }, -}) -``` - ---- - -### Files - -| Method | Description | Response | -| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `find.text({ query })` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `find.files({ query })` | Find files and directories by name | `string[]` (paths) | -| `find.symbols({ query })` | Find workspace symbols | Symbol[] | -| `file.read({ query })` | Read a file | `{ type: "raw" \| "patch", content: string }` | -| `file.status({ query? })` | Get status for tracked files | File[] | - -`find.files` supports a few optional query fields: - -- `type`: `"file"` or `"directory"` -- `directory`: override the project root for the search -- `limit`: max results (1 to 200) - ---- - -#### Examples - -```javascript -// Search and read files -const textResults = await client.find.text({ - query: { pattern: "function.*openscience" }, -}) - -const files = await client.find.files({ - query: { query: "*.ts", type: "file" }, -}) - -const directories = await client.find.files({ - query: { query: "packages", type: "directory", limit: 20 }, -}) - -const content = await client.file.read({ - query: { path: "src/index.ts" }, -}) -``` - ---- - -### Auth - -| Method | Description | Response | -| ------------------- | ------------------------------ | --------- | -| `auth.set({ ... })` | Set authentication credentials | `boolean` | - ---- - -#### Examples - -```javascript -await client.auth.set({ - path: { id: "anthropic" }, - body: { type: "api", key: "your-api-key" }, -}) -``` - ---- - -### Events - -| Method | Description | Response | -| ------------------- | ------------------------- | ------------------------- | -| `event.subscribe()` | Server-sent events stream | Server-sent events stream | - ---- - -#### Examples - -```javascript -// Listen to real-time events -const events = await client.event.subscribe() -for await (const event of events.stream) { - console.log("Event:", event.type, event.properties) -} -``` diff --git a/frontend/docs/src/content/docs/server.mdx b/frontend/docs/src/content/docs/server.mdx deleted file mode 100644 index b175002..0000000 --- a/frontend/docs/src/content/docs/server.mdx +++ /dev/null @@ -1,269 +0,0 @@ ---- -title: Server -description: Interact with the OpenScience server over HTTP. ---- - -import config from "../../../config.mjs" -export const typesUrl = `${config.github}/blob/dev/tooling/sdk/js/src/gen/types.gen.ts` - -The `openscience serve` command runs a headless HTTP server that exposes an OpenAPI endpoint that an OpenScience client can use. - ---- - -### Usage - -```bash -openscience serve [--port ] [--hostname ] [--cors ] -``` - -#### Options - -| Flag | Description | Default | -| ------------ | ----------------------------------- | ----------- | -| `--port` | Port to listen on | `4096` | -| `--hostname` | Hostname to listen on | `127.0.0.1` | -| `--mdns` | Enable mDNS discovery | `false` | -| `--cors` | Additional browser origins to allow | `[]` | - -`--cors` can be passed multiple times: - -```bash -openscience serve --cors http://localhost:5173 --cors https://app.example.com -``` - ---- - -### Authentication - -Set `OPENSCIENCE_SERVER_PASSWORD` to protect the server with HTTP basic auth. The username defaults to `openscience`, or set `OPENSCIENCE_SERVER_USERNAME` to override it. This applies to both `openscience serve` and `openscience web`. - -```bash -OPENSCIENCE_SERVER_PASSWORD=your-password openscience serve -``` - ---- - -### How it works - -When you run `openscience` it opens a workspace in your browser, backed by a -local server. The workspace is the client that talks to the server. The server -exposes an OpenAPI 3.1 spec endpoint. This endpoint is also used to generate an -[SDK](/docs/sdk). - -:::tip -Use the OpenScience server to interact with OpenScience programmatically. -::: - -This architecture lets OpenScience support multiple clients and lets you interact with OpenScience programmatically. - -You can run `openscience serve` to start a standalone server. If you already -have a workspace open, `openscience serve` will start a new server. - ---- - -#### Connect to an existing server - -When you open a workspace it randomly assigns a port and hostname. You can instead pass in the `--hostname` and `--port` [flags](/docs/cli). Then use these to connect to its server. - -You can drive a running workspace through the server. For example, you can prefill or run a prompt. - ---- - -## Spec - -The server publishes an OpenAPI 3.1 spec that can be viewed at: - -``` -http://:/doc -``` - -For example, `http://localhost:4096/doc`. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer. - ---- - -## APIs - -The OpenScience server exposes the following APIs. - ---- - -### Global - -| Method | Path | Description | Response | -| ------ | ---------------- | ------------------------------ | ------------------------------------ | -| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | -| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | - ---- - -### Project - -| Method | Path | Description | Response | -| ------ | ------------------ | ----------------------- | --------------------------------------------- | -| `GET` | `/project` | List all projects | Project[] | -| `GET` | `/project/current` | Get the current project | Project | - ---- - -### Path & VCS - -| Method | Path | Description | Response | -| ------ | ------- | ------------------------------------ | ------------------------------------------- | -| `GET` | `/path` | Get the current path | Path | -| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | - ---- - -### Instance - -| Method | Path | Description | Response | -| ------ | ------------------- | ---------------------------- | --------- | -| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` | - ---- - -### Config - -| Method | Path | Description | Response | -| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | -| `GET` | `/config` | Get config info | Config | -| `PATCH` | `/config` | Update config | Config | -| `GET` | `/config/providers` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | - ---- - -### Provider - -| Method | Path | Description | Response | -| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- | -| `GET` | `/provider` | List all providers | `{ all: `Provider[]`, default: {...}, connected: string[] }` | -| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `ProviderAuthMethod[]` }` | -| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | ProviderAuthAuthorization | -| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` | - ---- - -### Sessions - -| Method | Path | Description | Notes | -| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | -| `GET` | `/session` | List all sessions | Returns Session[] | -| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns Session | -| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `SessionStatus` }` | -| `GET` | `/session/:id` | Get session details | Returns Session | -| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` | -| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns Session | -| `GET` | `/session/:id/children` | Get a session's child sessions | Returns Session[] | -| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns Todo[] | -| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns Session | -| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` | -| `POST` | `/session/:id/share` | Share a session | Returns Session | -| `DELETE` | `/session/:id/share` | Unshare a session | Returns Session | -| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns FileDiff[] | -| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` | -| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` | -| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` | - ---- - -### Messages - -| Method | Path | Description | Notes | -| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | -| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` | -| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | - ---- - -### Commands - -| Method | Path | Description | Response | -| ------ | ---------- | ----------------- | --------------------------------------------- | -| `GET` | `/command` | List all commands | Command[] | - ---- - -### Files - -| Method | Path | Description | Response | -| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `GET` | `/find?pattern=` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `GET` | `/find/file?query=` | Find files and directories by name | `string[]` (paths) | -| `GET` | `/find/symbol?query=` | Find workspace symbols | Symbol[] | -| `GET` | `/file?path=` | List files and directories | FileNode[] | -| `GET` | `/file/content?path=

` | Read a file | FileContent | -| `GET` | `/file/status` | Get status for tracked files | File[] | - -#### `/find/file` query parameters - -- `query` (required): search string (fuzzy match) -- `type` (optional): limit results to `"file"` or `"directory"` -- `directory` (optional): override the project root for the search -- `limit` (optional): max results (1 to 200) -- `dirs` (optional): legacy flag (`"false"` returns only files) - ---- - -### Tools (experimental) - -| Method | Path | Description | Response | -| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | -| `GET` | `/experimental/tool/ids` | List all tool IDs | ToolIDs | -| `GET` | `/experimental/tool?provider=

&model=` | List tools with JSON schemas for a model | ToolList | - ---- - -### LSP, formatters & MCP - -| Method | Path | Description | Response | -| ------ | ------------ | -------------------------- | -------------------------------------------------------- | -| `GET` | `/lsp` | Get LSP server status | LSPStatus[] | -| `GET` | `/formatter` | Get formatter status | FormatterStatus[] | -| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `MCPStatus` }` | -| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object | - ---- - -### Agents - -| Method | Path | Description | Response | -| ------ | -------- | ------------------------- | ------------------------------------------- | -| `GET` | `/agent` | List all available agents | Agent[] | - ---- - -### Logging - -| Method | Path | Description | Response | -| ------ | ------ | ------------------------------------------------------------ | --------- | -| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | - ---- - -### Auth - -| Method | Path | Description | Response | -| ------ | ----------- | --------------------------------------------------------------- | --------- | -| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | - ---- - -### Events - -| Method | Path | Description | Response | -| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- | -| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | - ---- - -### Docs - -| Method | Path | Description | Response | -| ------ | ------ | ------------------------- | --------------------------- | -| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | diff --git a/frontend/docs/src/content/docs/share.mdx b/frontend/docs/src/content/docs/share.mdx deleted file mode 100644 index 276474f..0000000 --- a/frontend/docs/src/content/docs/share.mdx +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Share -description: Share your OpenScience conversations. ---- - -OpenScience's share feature lets you create public links to your OpenScience conversations, so you can collaborate with teammates or get help from others. - -:::note -Shared conversations are publicly accessible to anyone with the link. -::: - ---- - -## How it works - -When you share a conversation, OpenScience: - -1. Creates a unique public URL for your session -2. Syncs your conversation history to our servers -3. Makes the conversation accessible at a shareable link: `syntheticsciences.ai/s/` - ---- - -## Sharing - -OpenScience supports three sharing modes that control how conversations are shared: - ---- - -### Manual (default) - -By default, OpenScience uses manual sharing mode. Sessions are not shared automatically, but you can manually share them using the `/share` command: - -``` -/share -``` - -This will generate a unique URL that'll be copied to your clipboard. - -To explicitly set manual mode in your [config file](/docs/config): - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "share": "manual" -} -``` - ---- - -### Auto-share - -You can enable automatic sharing for all new conversations by setting the `share` option to `"auto"` in your [config file](/docs/config): - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "share": "auto" -} -``` - -With auto-share enabled, every new conversation will automatically be shared and a link will be generated. - ---- - -### Disabled - -You can disable sharing entirely by setting the `share` option to `"disabled"` in your [config file](/docs/config): - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "share": "disabled" -} -``` - -To enforce this across your team for a given project, add it to the `openscience.json` in your project and check into Git. - ---- - -## Un-sharing - -To stop sharing a conversation and remove it from public access: - -``` -/unshare -``` - -This will remove the share link and delete the data related to the conversation. - ---- - -## Privacy - -There are a few things to keep in mind when sharing a conversation. - ---- - -### Data retention - -Shared conversations remain accessible until you explicitly unshare them. This -includes: - -- Full conversation history -- All messages and responses -- Session metadata - ---- - -### Recommendations - -- Only share conversations that don't contain sensitive information. -- Review conversation content before sharing. -- Unshare conversations when collaboration is complete. -- Avoid sharing conversations with proprietary code or confidential data. -- For sensitive projects, disable sharing entirely. - ---- - -## For enterprises - -For enterprise deployments, the share feature can be: - -- **Disabled** entirely for security compliance -- **Restricted** to users authenticated through SSO only -- **Self-hosted** on your own infrastructure - -[Learn more](/docs/enterprise) about using openscience in your organization. diff --git a/frontend/docs/src/content/docs/skills.mdx b/frontend/docs/src/content/docs/skills.mdx deleted file mode 100644 index c1827ef..0000000 --- a/frontend/docs/src/content/docs/skills.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: "Agent Skills" -description: "Define reusable behavior via SKILL.md definitions" ---- - -Agent skills let OpenScience discover reusable instructions from your repo or home directory. -Skills are loaded on demand via the native `skill` tool. Agents see the available skills and can load the full content when needed. - ---- - -## Place files - -Create one folder per skill name and put a `SKILL.md` inside it. -OpenScience searches these locations: - -- Project config: `.openscience/skills//SKILL.md` -- Global config: `~/.config/openscience/skills//SKILL.md` -- Project Claude-compatible: `.claude/skills//SKILL.md` -- Global Claude-compatible: `~/.claude/skills//SKILL.md` - ---- - -## Understand discovery - -For project-local paths, OpenScience walks up from your current working directory until it reaches the git worktree. -It loads any matching `skills/*/SKILL.md` in `.openscience/` and any matching `.claude/skills/*/SKILL.md` along the way. - -Global definitions are also loaded from `~/.config/openscience/skills/*/SKILL.md` and `~/.claude/skills/*/SKILL.md`. - ---- - -## Write frontmatter - -Each `SKILL.md` must start with YAML frontmatter. -Only these fields are recognized: - -- `name` (required) -- `description` (required) -- `license` (optional) -- `compatibility` (optional) -- `metadata` (optional, string-to-string map) - -Unknown frontmatter fields are ignored. - ---- - -## Validate names - -`name` must: - -- Be 1-64 characters -- Be lowercase alphanumeric with single hyphen separators -- Not start or end with `-` -- Not contain consecutive `--` -- Match the directory name that contains `SKILL.md` - -Equivalent regex: - -```text -^[a-z0-9]+(-[a-z0-9]+)*$ -``` - ---- - -## Follow length rules - -`description` must be 1-1024 characters. -Keep it specific enough for the agent to choose correctly. - ---- - -## Use an example - -Create `.openscience/skills/git-release/SKILL.md` like this: - -```markdown ---- -name: git-release -description: Create consistent releases and changelogs -license: Apache-2.0 -compatibility: openscience -metadata: - audience: maintainers - workflow: github ---- - -## What I do - -- Draft release notes from merged PRs -- Propose a version bump -- Provide a copy-pasteable `gh release create` command - -## When to use me - -Use this when you are preparing a tagged release. -Ask clarifying questions if the target versioning scheme is unclear. -``` - ---- - -## Recognize tool description - -OpenScience lists available skills in the `skill` tool description. -Each entry includes the skill name and description: - -```xml - - - git-release - Create consistent releases and changelogs - - -``` - -The agent loads a skill by calling the tool: - -``` -skill({ name: "git-release" }) -``` - ---- - -## Configure permissions - -Control which skills agents can access using pattern-based permissions in `openscience.json`: - -```json -{ - "permission": { - "skill": { - "*": "allow", - "pr-review": "allow", - "internal-*": "deny", - "experimental-*": "ask" - } - } -} -``` - -| Permission | Behavior | -| ---------- | ----------------------------------------- | -| `allow` | Skill loads immediately | -| `deny` | Skill hidden from agent, access rejected | -| `ask` | User prompted for approval before loading | - -Patterns support wildcards: `internal-*` matches `internal-docs`, `internal-tools`, etc. - ---- - -## Override per agent - -Give specific agents different permissions than the global defaults. - -**For custom agents** (in agent frontmatter): - -```yaml ---- -permission: - skill: - "documents-*": "allow" ---- -``` - -**For built-in agents** (in `openscience.json`): - -```json -{ - "agent": { - "plan": { - "permission": { - "skill": { - "internal-*": "allow" - } - } - } - } -} -``` - ---- - -## Disable the skill tool - -Completely disable skills for agents that shouldn't use them: - -**For custom agents**: - -```yaml ---- -tools: - skill: false ---- -``` - -**For built-in agents**: - -```json -{ - "agent": { - "plan": { - "tools": { - "skill": false - } - } - } -} -``` - -When disabled, the `` section is omitted entirely. - ---- - -## Troubleshoot loading - -If a skill does not show up: - -1. Verify `SKILL.md` is spelled in all caps -2. Check that frontmatter includes `name` and `description` -3. Ensure skill names are unique across all locations -4. Check permissions, since skills with `deny` are hidden from agents diff --git a/frontend/docs/src/content/docs/themes.mdx b/frontend/docs/src/content/docs/themes.mdx deleted file mode 100644 index 8bdd3cc..0000000 --- a/frontend/docs/src/content/docs/themes.mdx +++ /dev/null @@ -1,352 +0,0 @@ ---- -title: Themes -description: Select a built-in theme or define your own. ---- - -With OpenScience you can select from one of several built-in themes, use a theme that follows your system's light or dark appearance, or define your own custom theme. - -By default, OpenScience uses our own `openscience` theme. - ---- - -## Built-in themes - -OpenScience comes with several built-in themes. - -| Name | Description | -| ---------------------- | ---------------------------------------------------------------------------- | -| `system` | Follows your system's light or dark appearance | -| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme | -| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme | -| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme | -| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme | -| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme | -| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme | -| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme | -| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme | -| `matrix` | Hacker-style green on black theme | -| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme | - -And more, we are constantly adding new themes. - ---- - -## System theme - -The `system` theme follows your operating system's light or dark appearance instead of using fixed colors. It picks a gray scale that keeps good contrast against the workspace background, and it uses `none` for text and background so the workspace keeps its default look. - -The system theme is for users who: - -- Want OpenScience to match their system appearance -- Prefer a consistent look across their other applications - ---- - -## Using a theme - -You can select a theme by bringing up the theme select with the `/theme` command. Or you can specify it in your [config](/docs/config). - -```json title="openscience.json" {3} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "theme": "tokyonight" -} -``` - ---- - -## Custom themes - -OpenScience supports a flexible JSON-based theme system that allows users to create and customize themes easily. - ---- - -### Hierarchy - -Themes are loaded from multiple directories in the following order where later directories override earlier ones: - -1. Built-in themes: embedded in the binary -2. User config directory: `~/.config/openscience/themes/*.json` or `$XDG_CONFIG_HOME/openscience/themes/*.json` -3. Project root directory: `/.openscience/themes/*.json` -4. Current working directory: `./.openscience/themes/*.json` - -If multiple directories contain a theme with the same name, the theme from the directory with higher priority will be used. - ---- - -### Creating a theme - -To create a custom theme, create a JSON file in one of the theme directories. - -For user-wide themes: - -```bash no-frame -mkdir -p ~/.config/openscience/themes -vim ~/.config/openscience/themes/my-theme.json -``` - -And for project-specific themes. - -```bash no-frame -mkdir -p .openscience/themes -vim .openscience/themes/my-theme.json -``` - ---- - -### JSON format - -Themes use a flexible JSON format with support for: - -- **Hex colors**: `"#ffffff"` -- **ANSI colors**: `3` (0-255) -- **Color references**: `"primary"` or custom definitions -- **Dark/light variants**: `{"dark": "#000", "light": "#fff"}` -- **No color**: `"none"` uses the default color or transparent - ---- - -### Color definitions - -The `defs` section is optional and it allows you to define reusable colors that can be referenced in the theme. - ---- - -### Default colors - -The special value `"none"` can be used for any color to inherit the default color or stay transparent. This is useful for themes that follow the surrounding appearance: - -- `"text": "none"` uses the default foreground color -- `"background": "none"` uses the default background color - ---- - -### Example - -Here's an example of a custom theme: - -```json title="my-theme.json" -{ - "$schema": "https://syntheticsciences.ai/theme.json", - "defs": { - "nord0": "#2E3440", - "nord1": "#3B4252", - "nord2": "#434C5E", - "nord3": "#4C566A", - "nord4": "#D8DEE9", - "nord5": "#E5E9F0", - "nord6": "#ECEFF4", - "nord7": "#8FBCBB", - "nord8": "#88C0D0", - "nord9": "#81A1C1", - "nord10": "#5E81AC", - "nord11": "#BF616A", - "nord12": "#D08770", - "nord13": "#EBCB8B", - "nord14": "#A3BE8C", - "nord15": "#B48EAD" - }, - "theme": { - "primary": { - "dark": "nord8", - "light": "nord10" - }, - "secondary": { - "dark": "nord9", - "light": "nord9" - }, - "accent": { - "dark": "nord7", - "light": "nord7" - }, - "error": { - "dark": "nord11", - "light": "nord11" - }, - "warning": { - "dark": "nord12", - "light": "nord12" - }, - "success": { - "dark": "nord14", - "light": "nord14" - }, - "info": { - "dark": "nord8", - "light": "nord10" - }, - "text": { - "dark": "nord4", - "light": "nord0" - }, - "textMuted": { - "dark": "nord3", - "light": "nord1" - }, - "background": { - "dark": "nord0", - "light": "nord6" - }, - "backgroundPanel": { - "dark": "nord1", - "light": "nord5" - }, - "backgroundElement": { - "dark": "nord1", - "light": "nord4" - }, - "border": { - "dark": "nord2", - "light": "nord3" - }, - "borderActive": { - "dark": "nord3", - "light": "nord2" - }, - "borderSubtle": { - "dark": "nord2", - "light": "nord3" - }, - "diffAdded": { - "dark": "nord14", - "light": "nord14" - }, - "diffRemoved": { - "dark": "nord11", - "light": "nord11" - }, - "diffContext": { - "dark": "nord3", - "light": "nord3" - }, - "diffHunkHeader": { - "dark": "nord3", - "light": "nord3" - }, - "diffHighlightAdded": { - "dark": "nord14", - "light": "nord14" - }, - "diffHighlightRemoved": { - "dark": "nord11", - "light": "nord11" - }, - "diffAddedBg": { - "dark": "#3B4252", - "light": "#E5E9F0" - }, - "diffRemovedBg": { - "dark": "#3B4252", - "light": "#E5E9F0" - }, - "diffContextBg": { - "dark": "nord1", - "light": "nord5" - }, - "diffLineNumber": { - "dark": "nord2", - "light": "nord4" - }, - "diffAddedLineNumberBg": { - "dark": "#3B4252", - "light": "#E5E9F0" - }, - "diffRemovedLineNumberBg": { - "dark": "#3B4252", - "light": "#E5E9F0" - }, - "markdownText": { - "dark": "nord4", - "light": "nord0" - }, - "markdownHeading": { - "dark": "nord8", - "light": "nord10" - }, - "markdownLink": { - "dark": "nord9", - "light": "nord9" - }, - "markdownLinkText": { - "dark": "nord7", - "light": "nord7" - }, - "markdownCode": { - "dark": "nord14", - "light": "nord14" - }, - "markdownBlockQuote": { - "dark": "nord3", - "light": "nord3" - }, - "markdownEmph": { - "dark": "nord12", - "light": "nord12" - }, - "markdownStrong": { - "dark": "nord13", - "light": "nord13" - }, - "markdownHorizontalRule": { - "dark": "nord3", - "light": "nord3" - }, - "markdownListItem": { - "dark": "nord8", - "light": "nord10" - }, - "markdownListEnumeration": { - "dark": "nord7", - "light": "nord7" - }, - "markdownImage": { - "dark": "nord9", - "light": "nord9" - }, - "markdownImageText": { - "dark": "nord7", - "light": "nord7" - }, - "markdownCodeBlock": { - "dark": "nord4", - "light": "nord0" - }, - "syntaxComment": { - "dark": "nord3", - "light": "nord3" - }, - "syntaxKeyword": { - "dark": "nord9", - "light": "nord9" - }, - "syntaxFunction": { - "dark": "nord8", - "light": "nord8" - }, - "syntaxVariable": { - "dark": "nord7", - "light": "nord7" - }, - "syntaxString": { - "dark": "nord14", - "light": "nord14" - }, - "syntaxNumber": { - "dark": "nord15", - "light": "nord15" - }, - "syntaxType": { - "dark": "nord7", - "light": "nord7" - }, - "syntaxOperator": { - "dark": "nord9", - "light": "nord9" - }, - "syntaxPunctuation": { - "dark": "nord4", - "light": "nord0" - } - } -} -``` diff --git a/frontend/docs/src/content/docs/tools.mdx b/frontend/docs/src/content/docs/tools.mdx deleted file mode 100644 index d459774..0000000 --- a/frontend/docs/src/content/docs/tools.mdx +++ /dev/null @@ -1,345 +0,0 @@ ---- -title: Tools -description: Manage the tools an LLM can use. ---- - -Tools allow the LLM to perform actions in your codebase. OpenScience comes with a set of built-in tools, but you can extend it with [custom tools](/docs/custom-tools) or [MCP servers](/docs/mcp-servers). - -By default, all tools are **enabled** and don't need permission to run. You can control tool behavior through [permissions](/docs/permissions). - ---- - -## Configure - -Use the `permission` field to control tool behavior. You can allow, deny, or require approval for each tool. - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "deny", - "bash": "ask", - "webfetch": "allow" - } -} -``` - -You can also use wildcards to control multiple tools at once. For example, to require approval for all tools from an MCP server: - -```json title="openscience.json" -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "mymcp_*": "ask" - } -} -``` - -[Learn more](/docs/permissions) about configuring permissions. - ---- - -## Built-in - -Here are all the built-in tools available in OpenScience. - ---- - -### bash - -Execute shell commands in your project environment. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "bash": "allow" - } -} -``` - -This tool allows the LLM to run shell commands like `npm install`, `git status`, or any other command. - ---- - -### edit - -Modify existing files using exact string replacements. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "allow" - } -} -``` - -This tool performs precise edits to files by replacing exact text matches. It's the primary way the LLM modifies code. - ---- - -### write - -Create new files or overwrite existing ones. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "allow" - } -} -``` - -Use this to allow the LLM to create new files. It will overwrite existing files if they already exist. - -:::note -The `write` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`). -::: - ---- - -### read - -Read file contents from your codebase. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "read": "allow" - } -} -``` - -This tool reads files and returns their contents. It supports reading specific line ranges for large files. - ---- - -### grep - -Search file contents using regular expressions. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "grep": "allow" - } -} -``` - -Fast content search across your codebase. Supports full regex syntax and file pattern filtering. - ---- - -### glob - -Find files by pattern matching. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "glob": "allow" - } -} -``` - -Search for files using glob patterns like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time. - ---- - -### list - -List files and directories in a given path. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "list": "allow" - } -} -``` - -This tool lists directory contents. It accepts glob patterns to filter results. - ---- - -### lsp (experimental) - -Interact with your configured LSP servers to get code intelligence features like definitions, references, hover info, and call hierarchy. - -:::note -This tool is only available when `OPENSCIENCE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENSCIENCE_EXPERIMENTAL=true`). -::: - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "lsp": "allow" - } -} -``` - -Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`. - -To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp). - ---- - -### patch - -Apply patches to files. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "edit": "allow" - } -} -``` - -This tool applies patch files to your codebase. Useful for applying diffs and patches from various sources. - -:::note -The `patch` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`). -::: - ---- - -### skill - -Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the conversation. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "skill": "allow" - } -} -``` - ---- - -### todowrite - -Manage todo lists during coding sessions. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "todowrite": "allow" - } -} -``` - -Creates and updates task lists to track progress during complex operations. The LLM uses this to organize multi-step tasks. - -:::note -This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) -::: - ---- - -### todoread - -Read existing todo lists. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "todoread": "allow" - } -} -``` - -Reads the current todo list state. Used by the LLM to track what tasks are pending or completed. - -:::note -This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) -::: - ---- - -### webfetch - -Fetch web content. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "webfetch": "allow" - } -} -``` - -Allows the LLM to fetch and read web pages. Useful for looking up documentation or researching online resources. - ---- - -### question - -Ask the user questions during execution. - -```json title="openscience.json" {4} -{ - "$schema": "https://syntheticsciences.ai/config.json", - "permission": { - "question": "allow" - } -} -``` - -This tool allows the LLM to ask the user questions during a task. It's useful for: - -- Gathering user preferences or requirements -- Clarifying ambiguous instructions -- Getting decisions on implementation choices -- Offering choices about what direction to take - -Each question includes a header, the question text, and a list of options. Users can select from the provided options or type a custom answer. When there are multiple questions, users can navigate between them before submitting all answers. - ---- - -## Custom tools - -Custom tools let you define your own functions that the LLM can call. These are defined in your config file and can execute arbitrary code. - -[Learn more](/docs/custom-tools) about creating custom tools. - ---- - -## MCP servers - -MCP (Model Context Protocol) servers allow you to integrate external tools and services. This includes database access, API integrations, and third-party services. - -[Learn more](/docs/mcp-servers) about configuring MCP servers. - ---- - -## Internals - -Internally, tools like `grep`, `glob`, and `list` use [ripgrep](https://github.com/BurntSushi/ripgrep) under the hood. By default, ripgrep respects `.gitignore` patterns, which means files and directories listed in your `.gitignore` will be excluded from searches and listings. - ---- - -### Ignore patterns - -To include files that would normally be ignored, create a `.ignore` file in your project root. This file can explicitly allow certain paths. - -```text title=".ignore" -!node_modules/ -!dist/ -!build/ -``` - -For example, this `.ignore` file allows ripgrep to search within `node_modules/`, `dist/`, and `build/` directories even if they're listed in `.gitignore`. diff --git a/frontend/docs/src/content/docs/troubleshooting.mdx b/frontend/docs/src/content/docs/troubleshooting.mdx deleted file mode 100644 index bb0e55c..0000000 --- a/frontend/docs/src/content/docs/troubleshooting.mdx +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: Troubleshooting -description: Common issues and how to resolve them. ---- - -To debug issues with OpenScience, start by checking the logs and local data it stores on disk. - ---- - -## Logs - -Log files are written to: - -- **macOS/Linux**: `~/.local/share/openscience/log/` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\openscience\log` - -Log files are named with timestamps (e.g., `2025-01-09T123456.log`) and the most recent 10 log files are kept. - -You can set the log level with the `--log-level` command-line option to get more detailed debug information. For example, `openscience --log-level DEBUG`. - ---- - -## Storage - -OpenScience stores session data and other application data on disk at: - -- **macOS/Linux**: `~/.local/share/openscience/` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\openscience` - -This directory contains: - -- `auth.json` - Authentication data like API keys, OAuth tokens -- `log/` - Application logs -- `project/` - Project-specific data like session and message data - - If the project is within a Git repo, it is stored in `.//storage/` - - If it is not a Git repo, it is stored in `./global/storage/` - ---- - -## Desktop app - -OpenScience Desktop runs a local OpenScience server (the `openscience-cli` sidecar) in the background. Most issues are caused by a misbehaving plugin, a corrupted cache, or a bad server setting. - -### Quick checks - -- Fully quit and relaunch the app. -- If the app shows an error screen, click **Restart** and copy the error details. -- macOS only: `OpenScience` menu -> **Reload Webview** (helps if the UI is blank/frozen). - ---- - -### Disable plugins - -If the desktop app is crashing on launch, hanging, or behaving strangely, start by disabling plugins. - -#### Check the global config - -Open your global config file and look for a `plugin` key. - -- **macOS/Linux**: `~/.config/openscience/openscience.jsonc` (or `~/.config/openscience/openscience.json`) -- **macOS/Linux** (older installs): `~/.local/share/openscience/openscience.jsonc` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\openscience\openscience.jsonc` - -If you have plugins configured, temporarily disable them by removing the key or setting it to an empty array: - -```jsonc -{ - "$schema": "https://syntheticsciences.ai/config.json", - "plugin": [], -} -``` - -#### Check plugin directories - -OpenScience can also load local plugins from disk. Temporarily move these out of the way (or rename the folder) and restart the desktop app: - -- **Global plugins** - - **macOS/Linux**: `~/.config/openscience/plugins/` - - **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\openscience\plugins` -- **Project plugins** (only if you use per-project config) - - `/.openscience/plugins/` - -If the app starts working again, re-enable plugins one at a time to find which one is causing the issue. - ---- - -### Clear the cache - -If disabling plugins doesn't help (or a plugin install is stuck), clear the cache so OpenScience can rebuild it. - -1. Quit OpenScience Desktop completely. -2. Delete the cache directory: - -- **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/openscience` -- **Linux**: delete `~/.cache/openscience` (or run `rm -rf ~/.cache/openscience`) -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.cache\openscience` - -3. Restart OpenScience Desktop. - ---- - -### Fix server connection issues - -OpenScience Desktop can either start its own local server (default) or connect to a server URL you configured. - -If you see a **"Connection Failed"** dialog (or the app never gets past the splash screen), check for a custom server URL. - -#### Clear the desktop default server URL - -From the Home screen, click the server name (with the status dot) to open the Server picker. In the **Default server** section, click **Clear**. - -#### Remove `server.port` / `server.hostname` from your config - -If your `openscience.json(c)` contains a `server` section, temporarily remove it and restart the desktop app. - -#### Check environment variables - -If you have `OPENSCIENCE_PORT` set in your environment, the desktop app will try to use that port for the local server. - -- Unset `OPENSCIENCE_PORT` (or pick a free port) and restart. - ---- - -### Linux: Wayland / X11 issues - -On Linux, some Wayland setups can cause blank windows or compositor errors. - -- If you're on Wayland and the app is blank/crashing, try launching with `OC_ALLOW_WAYLAND=1`. -- If that makes things worse, remove it and try launching under an X11 session instead. - ---- - -### Windows: WebView2 runtime - -On Windows, OpenScience Desktop requires the Microsoft Edge **WebView2 Runtime**. If the app opens to a blank window or won't start, install/update WebView2 and try again. - ---- - -### Notifications not showing - -OpenScience Desktop only shows system notifications when: - -- notifications are enabled for OpenScience in your OS settings, and -- the app window is not focused. - ---- - -### Reset desktop app storage (last resort) - -If the app won't start and you can't clear settings from inside the UI, reset the desktop app's saved state. - -1. Quit OpenScience Desktop. -2. Find and delete these files (they live in the OpenScience Desktop app data directory): - -- `openscience.settings.dat` (desktop default server URL) -- `openscience.global.dat` and `openscience.workspace.*.dat` (UI state like recent servers/projects) - -To find the directory quickly: - -- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (then search for the filenames above) -- **Linux**: search under `~/.local/share` for the filenames above -- **Windows**: Press `WIN+R` -> `%APPDATA%` (then search for the filenames above) - ---- - -## Getting help - -If you're experiencing issues with OpenScience: - -1. **Report issues on GitHub** - - The best way to report bugs or request features is through our GitHub repository: - - [**github.com/synthetic-sciences/OpenScience/issues**](https://github.com/synthetic-sciences/OpenScience/issues) - - Before creating a new issue, search existing issues to see if your problem has already been reported. - -2. **Join our Discord** - - For real-time help and community discussion, join our Discord server: - - [**syntheticsciences.ai/discord**](https://syntheticsciences.ai/discord) - ---- - -## Common issues - -Here are some common issues and how to resolve them. - ---- - -### OpenScience won't start - -1. Check the logs for error messages -2. Try running with `--print-logs` to print logs to the console -3. Ensure you have the latest version with `openscience upgrade` - ---- - -### Authentication issues - -1. Try re-authenticating with the `/connect` command in the workspace -2. Check that your API keys are valid -3. Ensure your network allows connections to the provider's API - ---- - -### Model not available - -1. Check that you've authenticated with the provider -2. Verify the model name in your config is correct -3. Some models may require specific access or subscriptions - -If you encounter `ProviderModelNotFoundError` you are most likely incorrectly -referencing a model somewhere. -Models should be referenced like so: `/` - -Examples: - -- `openai/gpt-4.1` -- `openrouter/google/gemini-2.5-flash` -- `synsci/gpt-5-nano` - -To figure out what models you have access to, run `openscience models` - ---- - -### ProviderInitError - -If you encounter a ProviderInitError, you likely have an invalid or corrupted configuration. - -To resolve this: - -1. First, verify your provider is set up correctly by following the [providers guide](/docs/providers) -2. If the issue persists, try clearing your stored configuration: - - ```bash - rm -rf ~/.local/share/openscience - ``` - - On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\openscience` - -3. Re-authenticate with your provider using the `/connect` command in the workspace. - ---- - -### AI_APICallError and provider package issues - -If you encounter API call errors, this may be due to outdated provider packages. OpenScience dynamically installs provider packages (OpenAI, Anthropic, Google, etc.) as needed and caches them locally. - -To resolve provider package issues: - -1. Clear the provider package cache: - - ```bash - rm -rf ~/.cache/openscience - ``` - - On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\openscience` - -2. Restart OpenScience to reinstall the latest provider packages - -This will force OpenScience to download the most recent versions of provider packages, which often resolves compatibility issues with model parameters and API changes. - ---- - -### Copy/paste not working on Linux - -Linux users need to have one of the following clipboard utilities installed for copy/paste functionality to work: - -**For X11 systems:** - -```bash -apt install -y xclip -# or -apt install -y xsel -``` - -**For Wayland systems:** - -```bash -apt install -y wl-clipboard -``` - -**For headless environments:** - -```bash -apt install -y xvfb -# and run: -Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & -export DISPLAY=:99.0 -``` - -OpenScience will detect if you're using Wayland and prefer `wl-clipboard`, otherwise it will try to find clipboard tools in order of: `xclip` and `xsel`. diff --git a/frontend/docs/src/content/docs/web.mdx b/frontend/docs/src/content/docs/web.mdx deleted file mode 100644 index 69c85d5..0000000 --- a/frontend/docs/src/content/docs/web.mdx +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Web -description: Using OpenScience in your browser. ---- - -OpenScience runs in your browser as a web workspace. - -![OpenScience web, new session](../../assets/web/web-homepage-new-session.png) - -## Getting started - -Start the web interface by running: - -```bash -openscience web -``` - -This starts a local server on `127.0.0.1` with a random available port and automatically opens OpenScience in your default browser. - -:::caution -If `OPENSCIENCE_SERVER_PASSWORD` is not set, the server will be unsecured. This is fine for local use but should be set for network access. -::: - ---- - -## Configuration - -You can configure the web server using command line flags or in your [config file](/docs/config). - -### Port - -By default, OpenScience picks an available port. You can specify a port: - -```bash -openscience web --port 4096 -``` - -### Hostname - -By default, the server binds to `127.0.0.1` (localhost only). To make OpenScience accessible on your network: - -```bash -openscience web --hostname 0.0.0.0 -``` - -When using `0.0.0.0`, OpenScience will display both local and network addresses: - -``` - Local access: http://localhost:4096 - Network access: http://192.168.1.100:4096 -``` - -### mDNS discovery - -Enable mDNS to make your server discoverable on the local network: - -```bash -openscience web --mdns -``` - -This automatically sets the hostname to `0.0.0.0` and advertises the server as `openscience.local`. - -### CORS - -To allow additional domains for CORS (useful for custom frontends): - -```bash -openscience web --cors https://example.com -``` - -### Authentication - -To protect access, set a password using the `OPENSCIENCE_SERVER_PASSWORD` environment variable: - -```bash -OPENSCIENCE_SERVER_PASSWORD=secret openscience web -``` - -The username defaults to `openscience` but can be changed with `OPENSCIENCE_SERVER_USERNAME`. - ---- - -## Using the web interface - -Once started, the web interface provides access to your OpenScience sessions. - -### Sessions - -View and manage your sessions from the homepage. You can see active sessions and start new ones. - -![OpenScience web, active session](../../assets/web/web-homepage-active-session.png) - -### Server status - -Click "See Servers" to view connected servers and their status. - -![OpenScience web, see servers](../../assets/web/web-homepage-see-servers.png) - ---- - -## Config file - -You can also configure server settings in your `openscience.json` config file: - -```json -{ - "server": { - "port": 4096, - "hostname": "0.0.0.0", - "mdns": true, - "cors": ["https://example.com"] - } -} -``` - -Command line flags take precedence over config file settings. diff --git a/frontend/docs/src/content/openscience/agents.mdx b/frontend/docs/src/content/openscience/agents.mdx new file mode 100644 index 0000000..0713fd7 --- /dev/null +++ b/frontend/docs/src/content/openscience/agents.mdx @@ -0,0 +1,89 @@ +--- +title: "Agents" +description: "The research agent roster — a default research agent, three domain specialists, critique sub-agents, and a read-only plan mode — plus how to build your own." +icon: "bot" +--- + +The default agent is `research`, a scientific research agent that runs the whole loop: literature review, hypothesis, code, experiments on real compute, analysis, and write-up. Three domain specialists ship alongside it, backed by read-only critique sub-agents and a `plan` mode that cannot edit files. + +## Built-in roster + +| Agent | Role | What it does | +| --- | --- | --- | +| `research` | Default | Scientific research across the full skill library — literature, data analysis, GPU compute, and synthesis. | +| `biology` | Specialist | Computational biology: bioinformatics workflows and 30+ biological database integrations. | +| `physics` | Specialist | Computational physics: simulation, PDE solving, dynamical systems, symbolic regression. | +| `ml` | Specialist | Trains, evaluates, and analyzes models end to end — deep learning, LLMs, classical ML, RL. | +| `plan` | Mode | Read-only planning. Edit tools are disabled except for plan files. | + +Two sub-agents back the roster. The main agent delegates to them like tools: + +| Sub-agent | What it does | +| --- | --- | +| `critique` | Read-only scientific critique. Finds blocking errors — data leakage, wrong statistics, unsupported claims — before expensive or irreversible actions. | +| `literature-review` | Full PRISMA literature review: systematic search, screening, eligibility, synthesis, verification. | + +Run `openscience agent list` to print the complete set on your install, including utility sub-agents like `explore` and `reviewer`. + +## Pick an agent + +```bash +# one-shot run with a specific agent +openscience run --agent physics "Fit the dispersion relation in data/spectra.csv" +``` + +In the workspace, switch agents from the session picker. To change the default, set `default_agent` in `openscience.json`. Only agents with mode `primary` or `all` can lead a session; `subagent` profiles are reachable only by delegation. + +## Create a custom agent + +`openscience agent create` walks you through it interactively. The non-interactive form: + +```bash +openscience agent create \ + --path .openscience \ + --description "Reviews analysis notebooks for data leakage and unsound statistics" \ + --mode subagent \ + --tools "read,grep,glob" \ + --model anthropic/claude-sonnet-5 +``` + +| Flag | Use | +| --- | --- | +| `--path

` | Where to write the definition; an `agent/` folder is created inside it. Omit to choose project or global interactively. | +| `--description ` | What the agent is for. A model expands this into the name, system prompt, and delegation description. | +| `--mode ` | `primary`: leads a session. `subagent`: only reachable by delegation. `all`: both. | +| `--tools ` | Allow-list of tools. Anything left off the list is disabled. | +| `--model ` | Default model for this agent. | + +The result is a Markdown file: YAML frontmatter (description, mode, tools) plus a body that is the system prompt. Edit it like any prose file. + +## Tool restrictions + +`--tools "read,grep,glob"` produces a read-only agent that cannot be tricked into editing files. The available tools are `bash`, `read`, `write`, `edit`, `list`, `glob`, `grep`, `webfetch`, `task`, `todowrite`, and `todoread` — run `openscience agent create --help` for the list on your version. + +## Where agents live + +```text +.openscience/agent/ # project-scoped +~/.config/openscience/agent/ # user-global + # ships with OpenScience +``` + +Resolution is project-local, then user-global, then built-in. + +## What's next + + + + The 250+ skill library the agents draw on. + + + Start, resume, and share sessions with any agent. + + + Per-agent default models and provider routing. + + + Full `agent create` and `agent list` reference. + + diff --git a/frontend/docs/src/content/openscience/atlas.mdx b/frontend/docs/src/content/openscience/atlas.mdx new file mode 100644 index 0000000..57a2979 --- /dev/null +++ b/frontend/docs/src/content/openscience/atlas.mdx @@ -0,0 +1,79 @@ +--- +title: "Connect to Atlas" +description: "Optionally link OpenScience to the Atlas managed platform for wallet-billed frontier models, synced credentials, and research recorded into Atlas Graphs." +icon: "link" +--- + +OpenScience never requires an account: bring-your-own-key usage is free and never gated. Atlas is the managed platform, and connecting to it is optional. Atlas only meters the models it serves. + +## What connecting adds + +- **A managed model route.** Curated frontier models billed from a prepaid wallet, so you do not need per-provider keys. The default endpoint is `app.syntheticsciences.ai` (override with `OPENSCIENCE_API_BASE`). +- **Spend controls.** Managed/BYOK toggles for LLM and compute spend, per surface, in **Settings → Billing** on the dashboard. +- **Synced service credentials.** Store cloud and ML keys (Hugging Face, W&B, Modal, and others) once on your account and pull them to any machine. +- **Research graphs.** Record sessions and findings into Atlas Graphs, the durable research map. + +## Link your account + + + + ```bash + openscience connect login + ``` + Opens your browser to approve the device. On headless or CI machines, pass `--no-browser` and paste a key, or run `openscience connect login --key thk_...` with a key created at `app.syntheticsciences.ai/cli`. + + + ```bash + openscience connect status + ``` + Shows the connected user, this device, and how many service credentials synced. + + + ```bash + openscience connect sync + ``` + Refreshes synced service credentials after you change them on the dashboard. + + + +## Model routing and billing + +Key routing is per-provider and automatic: if you set a BYOK key for a provider, OpenScience uses it; otherwise the request goes through the Atlas managed route and debits your wallet. + +```bash +openscience billing # wallet balance and current key routing +openscience billing topup # opens the Plan tab — $50 or $200, one-time or recurring monthly +``` + +Flip managed versus BYOK per surface (LLM and compute) in **Settings → Billing**. BYOK works on every plan. + +## Where credentials live + +Connected, your account holds the canonical copy of every synced credential; the local `~/.config/openscience/credentials.json` is a mirror you can delete and re-pull with `openscience connect sync`. In BYOK mode, keys exist only on your machine — see [Security](/openscience/security) for the storage and subprocess rules. + +## `connect` commands + +| Command | Use | +| --- | --- | +| `openscience connect login` | Authenticate via browser; `--key thk_...` or `--no-browser` for headless machines. | +| `openscience connect status` | Connection, user, device, and synced credential count. | +| `openscience connect sync` | Re-pull synced service credentials from the dashboard. | +| `openscience connect devices` | List authenticated devices; revoke from the Devices tab on the dashboard. | +| `openscience connect logout` | Disconnect this machine. BYOK keeps working. | + +## What's next + + + + Run one continuous research session end to end. + + + Every subcommand, including connect and billing. + + + BYOK provider setup and model selection. + + + What leaves your machine in each mode. + + diff --git a/frontend/docs/src/content/openscience/commands.mdx b/frontend/docs/src/content/openscience/commands.mdx new file mode 100644 index 0000000..4932fba --- /dev/null +++ b/frontend/docs/src/content/openscience/commands.mdx @@ -0,0 +1,129 @@ +--- +title: "Command reference" +description: "Every openscience subcommand: workspace, run, sessions, models, agents, skills, and lifecycle." +icon: "terminal" +--- + +The OpenScience command surface. For live help, run `openscience --help` and `openscience --help`. + +The bare `openscience` (no arguments) starts the local server and opens the **browser workspace** in your working directory. Everything else is grouped below. + +## Global flags + +| Flag | Use | +| --- | --- | +| `-v, --version` | Print the installed version. | +| `-h, --help` | Print help for a command. | +| `--print-logs` | Stream agent diagnostics to stderr. | +| `--log-level ` | Override the log threshold. | + +## Workspace and runs + +| Command | Use | +| --- | --- | +| `openscience` | Start the server and open the browser workspace. | +| `openscience run [message..]` | One-shot prompt in the terminal; streams, then exits. | +| `openscience session list` | List recent sessions (`-n`, `--format`). | + +`run` flags: `-c/--continue`, `-s/--session `, `-m/--model `, `--variant ` (provider-specific reasoning effort), `--agent `, `--format `, `-f/--file `, `--attach ` (attach to a running server, e.g. `http://localhost:4096`), `--port`, `--title `. + +```bash +openscience run "Plot the attention entropy across layers for this checkpoint" +openscience run -c "Now sweep the temperature and re-plot" +openscience run --format json "Summarize the experiment in results/" > summary.json +``` + +## Account + +Connecting an Atlas account is optional — see [Atlas](/openscience/atlas). OpenScience runs fully standalone with your own provider keys. + +| Command | Use | +| --- | --- | +| `openscience connect login` | Connect your Atlas account (browser flow, or `--key thk_…`). | +| `openscience connect status` | Show the active account, default model, synced services, and credit. | +| `openscience connect sync` | Re-pull synced credentials. | +| `openscience connect devices` | List authorized devices. | +| `openscience connect logout` | Disconnect this device from Atlas. | + +## Providers and routing + +| Command | Use | +| --- | --- | +| `openscience auth` | Interactive provider sign-in (BYOK keys; OAuth where supported). | +| `openscience logout [provider]` | Log out of a connected provider. | +| `openscience models` | List configured providers and their models. | +| `openscience billing show` | Credit and recent managed-route usage (Atlas-connected mode). | +| `openscience billing topup` | Open the app to add credit. | + +## Agent profiles + +| Command | Use | +| --- | --- | +| `openscience agent list` | Print the agent roster on this install. | +| `openscience agent create` | Scaffold a custom agent (system prompt + tool set + routing policy). | + +Flags: `--path`, `--description`, `--mode `, `--tools`, `--model`. See [Agents](/openscience/agents). + +## Skills + +| Command | Use | +| --- | --- | +| `openscience skill list` | Show installed skills (`--all` for the bundled set). | +| `openscience skill show ` | Print a skill's metadata and entrypoints. | +| `openscience skill add ` | Install a skill (URL or `gh:owner/repo`). | +| `openscience skill new` / `edit` / `validate` | Author, edit, and check user skills. | +| `openscience skill remove ` | Uninstall a skill. | +| `openscience skill set-entries ` | Update which skills surface in the `/` picker. | + +## Local server and protocols + +| Command | Use | +| --- | --- | +| `openscience web` | Start the server and open the browser workspace (prints the URL, e.g. `http://localhost:4096`). | +| `openscience serve` | Headless local server — loopback-only (`127.0.0.1`), no browser. | +| `openscience acp` | Start an Agent Client Protocol server for editors like Zed. | +| `openscience mcp` | Manage MCP servers (`list`, `add`, `remove`, `auth`). | + +`web` and `serve` take `--port` and `--cors`. See [Workspace](/openscience/workspace). + +## GitHub and PRs + +| Command | Use | +| --- | --- | +| `openscience github` | GitHub agent for CI/Actions (`install`, `run`). | +| `openscience pr ` | Check out a PR branch, then launch the agent on it. | + +## Project and lifecycle + +| Command | Use | +| --- | --- | +| `openscience project` | Pin the Atlas project root for this folder (`merge`). | +| `openscience export` / `openscience import` | Export or import a session as JSON. | +| `openscience generate` | Emit the OpenAPI spec for the local server to stdout. | +| `openscience stats` | Local token-usage and cost stats. | +| `openscience debug` | Structured diagnostics for support (`debug paths` shows data/config dirs). | +| `openscience upgrade` | Update to the latest version. | +| `openscience uninstall` | Remove the binary and local config. | +| `openscience completion` | Shell completion for bash, zsh, or fish. | + +```bash +openscience upgrade +openscience completion zsh > ~/.zsh/completions/_openscience +``` + +## What's next + + + + The browser workspace: files, editor, terminal, inline scientific rendering. + + + Credential boundary, env hygiene, the trust boundary. + + + 250+ research skills and the scientific databases. + + + The research agent, the specialists, and custom profiles. + + diff --git a/frontend/docs/src/content/openscience/docs.json b/frontend/docs/src/content/openscience/docs.json new file mode 100644 index 0000000..e1af8e1 --- /dev/null +++ b/frontend/docs/src/content/openscience/docs.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "name": "OpenScience", + "navigation": { + "tabs": [ + { + "tab": "Guides", + "groups": [ + { + "group": "Start", + "pages": ["index", "quickstart", "workspace"] + }, + { + "group": "Use the agent", + "pages": ["agents", "models", "skills", "sessions", "atlas"] + } + ] + }, + { + "tab": "Reference", + "groups": [ + { + "group": "CLI", + "pages": ["commands", "security"] + } + ] + } + ], + "global": { + "anchors": [ + { "anchor": "openscience.sh", "href": "https://openscience.sh" }, + { "anchor": "GitHub", "href": "https://github.com/synthetic-sciences/openscience" }, + { "anchor": "npm", "href": "https://www.npmjs.com/package/@synsci/openscience" }, + { "anchor": "Releases", "href": "https://github.com/synthetic-sciences/openscience/releases" } + ] + } + }, + "navbar": { + "primary": { + "type": "button", + "label": "Star on GitHub", + "href": "https://github.com/synthetic-sciences/openscience" + } + } +} diff --git a/frontend/docs/src/content/openscience/index.mdx b/frontend/docs/src/content/openscience/index.mdx new file mode 100644 index 0000000..795339b --- /dev/null +++ b/frontend/docs/src/content/openscience/index.mdx @@ -0,0 +1,78 @@ +--- +title: "OpenScience" +description: "The open-source AI workbench for scientific research. Give it a goal — it reads the literature, writes and runs code, runs the experiments, and writes up what it found." +icon: "flask-conical" +--- + + + +OpenScience is an AI workbench for scientific research. You give it a goal, and it works through the research loop the way a capable collaborator would: it reads the papers that matter, forms a hypothesis, writes and runs code, runs experiments on real compute, queries the major scientific databases, and writes up the result. + +It runs as a workspace in your browser, works with any frontier or open-weight model using your own API keys, and requires no account. It is model-agnostic, Apache-2.0 licensed, and built to do real work in machine learning, biology, physics, and chemistry. + +```bash +npm install -g @synsci/openscience +openscience +``` + +That's the whole install. The command is `openscience`, and it opens the workspace in your browser. Prefer not to install globally? `npx synsci` does the same thing in one step. + +## What we built + +Everything below ships in the open-source CLI — no gated tiers, no server-side magic you can't read. + + + + Literature review, hypothesis, code, experiment, analysis, and write-up in one continuous session. Queue follow-up prompts while it streams; rewind with undo-from-here. + + + A `research` agent by default, plus `biology`, `physics`, and `ml` specialists — with critique and literature-review sub-agents and a read-only plan mode. + + + Training (DeepSpeed, PEFT, TRL), evaluation, dataset work, molecular and clinical biology, cheminformatics, papers and LaTeX, figures, and cloud compute. + + + UniProt, PDB, Ensembl, ChEMBL, PubChem, arXiv, OpenAlex, Semantic Scholar, and around 30 more, queryable directly by the agent. + + + A browser UI with a file tree, an editor, a terminal, session history, and inline rendering for molecules, structures, genomes, and plots. + + + LSP integration, MCP servers, plugins, custom agents and commands, and a TypeScript SDK. + + + +## Any model, your keys + +Set an API key from any provider and start working. Keys stay on your machine. + +```bash +export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY, GEMINI_API_KEY, ... +openscience +``` + +OpenScience routes to frontier and open-weight models from Anthropic, OpenAI, Google, and dozens of other providers. Reasoning-effort tiers are first-class: `--variant high|max|minimal` on any run. See [Models](/openscience/models). + +## Open source, all the way down + +The workbench is [Apache-2.0 on GitHub](https://github.com/synthetic-sciences/openscience). No account, no telemetry wall, no closed core: the agent loop, the skills, the database tools, and the workspace are all in the repo. Read it, fork it, extend it — and if it does real work for you, [star it](https://github.com/synthetic-sciences/openscience) so other researchers find it. + +- **Site** — [openscience.sh](https://openscience.sh) +- **Issues and ideas** — [github.com/synthetic-sciences/openscience/issues](https://github.com/synthetic-sciences/openscience/issues) +- **Releases and platform binaries** — [GitHub Releases](https://github.com/synthetic-sciences/openscience/releases) +- **Package** — [`@synsci/openscience` on npm](https://www.npmjs.com/package/@synsci/openscience) + +## Works with Atlas, never requires it + +Connect an Atlas account and OpenScience records its research into [Atlas graphs](/openscience/atlas) — durable hypotheses, runs, and decisions your whole team can audit — plus an optional managed model route with spend controls. Standalone mode keeps everything local. See [Connect to Atlas](/openscience/atlas). + +## Start here + + + + Install, set a key, and run your first research session in five minutes. + + + A tour of the browser workspace and the local server behind it. + + diff --git a/frontend/docs/src/content/openscience/models.mdx b/frontend/docs/src/content/openscience/models.mdx new file mode 100644 index 0000000..e510bab --- /dev/null +++ b/frontend/docs/src/content/openscience/models.mdx @@ -0,0 +1,72 @@ +--- +title: "Models & providers" +description: "Bring your own keys for any provider, switch models per run, and optionally route through Atlas managed." +icon: "package-check" +--- + +OpenScience is model-agnostic. A **model** is one inference endpoint the agent routes through; a **provider** is a vendor that exposes models. Routing happens on your machine: with your own keys (the default), each call goes straight from your machine to the provider — no gateway in the middle, no account required. + +## Bring your own keys + +Set a key from any provider and start working: + +```bash +export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY, GEMINI_API_KEY, ... +openscience +``` + +Keys stay on your machine. Anthropic, OpenAI, Google, OpenRouter, Groq, Mistral, xAI, DeepSeek, and dozens more work the same way — the catalogue is models.dev-backed, so any `provider/model` id a provider currently exposes is addressable. You can also paste keys into the Credentials panel in the [workspace](/openscience/workspace) instead of exporting them, and OpenAI Codex signs in via OAuth. + +## List what is configured + +```bash +openscience models # grouped by provider, with a routing label per provider +openscience models anthropic # one provider +``` + +Each provider is labeled `your key`, `managed`, `Signed in with Codex`, or `unconfigured`, so you always know which route a model takes. `--verbose` adds per-model metadata like costs, `--refresh` refetches the catalogue, and `--flat` prints one `provider/model` id per line for scripting. + +## Pick a model per run + +```bash +openscience run --model anthropic/claude-opus-4-8 --variant xhigh "Design the ablation study" +openscience run --model anthropic/claude-sonnet-5 "Clean up the plotting code" +``` + +`--model /` overrides the default for one run; in the workspace, use the model selector per session. `--variant` picks a reasoning-effort tier — `minimal`, `high`, `max`, and so on. Available tiers depend on the model: Claude Opus 4.8 exposes the full range up to `xhigh` and `max`; other adaptive Claude models cap at `max`. + +## Atlas managed (optional) + +[Atlas](/openscience/atlas) is the managed platform. Connecting adds a curated set of frontier models billed from a prepaid wallet, so you can skip per-provider keys entirely: + +```bash +openscience connect login # defaults to app.syntheticsciences.ai +``` + +Once connected, launching the workspace syncs your provider config and credentials, and Settings → Billing has independent managed/BYOK spend toggles for LLM calls and compute — mix routes freely, per concern. BYOK usage is always free and never gated; Atlas only meters the models it serves. + +| Path | What runs where | Billing | +| --- | --- | --- | +| BYOK (default) | Your machine calls the provider directly. | Your provider account. | +| Atlas managed | Your machine calls Atlas, which calls the provider. | Prepaid wallet. See [Connect to Atlas](/openscience/atlas). | + +## Key hygiene + +Provider keys and synced credentials are filtered out of the environment of every subprocess the agent spawns and redacted from output. The agent talks to providers itself; the code it runs never needs your keys. Credentials are stored per user in your home directory, never in the project's `.openscience/` directory, so they cannot end up in a commit. See [Security](/openscience/security). + +## What's next + + + + First key to first result. + + + Per-run model and variant flags in context. + + + What connecting to Atlas adds. + + + The env allow-list and trust boundary. + + diff --git a/frontend/docs/src/content/openscience/quickstart.mdx b/frontend/docs/src/content/openscience/quickstart.mdx new file mode 100644 index 0000000..6320aee --- /dev/null +++ b/frontend/docs/src/content/openscience/quickstart.mdx @@ -0,0 +1,71 @@ +--- +title: "Quickstart" +description: "Install OpenScience, set a provider key, and run your first research session." +icon: "rocket" +--- + +Five minutes from zero to a running research session. No account required. + + + + ```bash + npm install -g @synsci/openscience + ``` + + Or without a global install, `npx synsci` runs the same workbench in one step. The install script (`curl -fsSL https://openscience.sh/install | bash`) drops a standalone `openscience` binary into `~/.openscience/bin`, and platform binaries are attached to every [GitHub release](https://github.com/synthetic-sciences/openscience/releases). + + + ```bash + export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY, GEMINI_API_KEY, ... + ``` + + Any provider works — bring your own key and it stays on your machine. `openscience auth` gives you an interactive sign-in for providers that support it. See [Models](/openscience/models) for routing and reasoning-effort tiers. + + + ```bash + openscience + ``` + + The command starts a local server and opens the browser workspace: file tree, editor, terminal, and session history, with inline rendering for molecules, structures, genomes, and plots. See [Workspace](/openscience/workspace). + + + Ask for the outcome, not the steps. The default `research` agent plans, reads, codes, runs, and reports: + + ```text + Reproduce the headline result of arXiv:2305.13245 on a small model + and tell me whether it holds at 125M parameters. + ``` + + Prefer the terminal? One-shot runs work without the browser: + + ```bash + openscience run "Profile train.py and find the input-pipeline bottleneck" + ``` + + + ```bash + openscience connect login + ``` + + Connecting an [Atlas](/openscience/atlas) account records your research into durable graphs and unlocks a managed model route with spend controls. OpenScience never requires it. See [Connect to Atlas](/openscience/atlas). + + + +## Verify the install + +```bash +openscience --version +openscience models # configured providers and models +openscience skill list # installed skills +``` + +## Where next + + + + The research agent, the biology / physics / ml specialists, and plan mode. + + + Every subcommand: runs, sessions, skills, server, lifecycle. + + diff --git a/frontend/docs/src/content/openscience/security.mdx b/frontend/docs/src/content/openscience/security.mdx new file mode 100644 index 0000000..024ebc5 --- /dev/null +++ b/frontend/docs/src/content/openscience/security.mdx @@ -0,0 +1,51 @@ +--- +title: "Security" +description: "The trust boundary, credential storage, and subprocess environment hygiene — in an open-source agent you can audit end to end." +icon: "shield-check" +--- + +OpenScience is open source under Apache-2.0, so the whole security model below is auditable in the [repository](https://github.com/synthetic-sciences/openscience). The agent runs locally with the same filesystem and shell access you have. Two principles anchor the design: keep credentials out of subprocesses that do not need them, and make the trust boundary explicit instead of pretending the agent is a sandbox. + +## The agent is not a sandbox + +The permission system prompts you before the agent runs a command or writes a file. That keeps you aware of what it is doing — it is not an isolation boundary. The agent can read, write, and execute anywhere your user can. For real isolation, run OpenScience inside a container or a VM. + +## Credential storage + +| Surface | Where | Notes | +| --- | --- | --- | +| BYOK provider keys | Environment variables or the local credential store | Never leave your machine; requests go straight to the provider. No account required. | +| Atlas session | `~/.config/openscience/config.json` | `thk_*` key created by `openscience connect login`; revocable from the dashboard. | +| Synced service credentials | `~/.config/openscience/credentials.json` | Present only when [connected to Atlas](/openscience/atlas); refresh with `openscience connect sync`. | +| Native binary (curl install) | `~/.openscience/bin/openscience` | Added to PATH through your shell rc. | + +Override the config parent directory with `XDG_CONFIG_HOME`. + +## Subprocess environment allow-list + +When the agent shells out, it rebuilds the subprocess environment from a curated allow-list rather than inheriting your full shell. Provider keys stay out of commands that have no business seeing them. + +**Always passed through:** `PATH`, `HOME`, `USER`, `SHELL`, `TERM`, `LANG`, `LC_*`, `TMPDIR`, `XDG_*`, `EDITOR`, `VISUAL`. + +**Passed through only when a subprocess needs them:** `HF_TOKEN`, `WANDB_API_KEY`, `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`, `LAMBDA_API_KEY`, `RUNPOD_API_KEY`, `PRIME_INTELLECT_API_KEY`, `TENSORPOOL_API_KEY`, `VAST_API_KEY`, `TINKER_API_KEY`, `LANGSMITH_API_KEY`, `PINECONE_API_KEY`, `TOGETHER_API_KEY`, `GROQ_API_KEY`, `FIREWORKS_API_KEY`, `OPENROUTER_API_KEY`. + +**Explicitly filtered out, even if set in your shell:** `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, `GEMINI_API_KEY`. The agent talks to model providers itself; subprocesses do not need these keys. + +## Output redaction + +Known credential patterns are redacted from agent output before it lands in a transcript. If you spot an unredacted secret, report it (see below). + +## Server mode + +Server mode is opt-in. The server binds to localhost (127.0.0.1) only and enforces a Host and Origin allowlist to block DNS-rebinding and cross-origin requests. It is not built for remote exposure — if you tunnel or reverse-proxy it, securing that exposure is on you. + +## What leaves your machine + +- Prompts and responses sent to your model provider, governed by that provider's policy. +- Nothing else, in BYOK mode. If you [connect to Atlas](/openscience/atlas), synced credentials and usage metering are held against your account. + +Source files stay local unless the agent explicitly uploads them through a tool you approve, and local environment variables outside the allow-list above are never forwarded. + +## Reporting a vulnerability + +Report security issues through the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/synthetic-sciences/openscience/security/advisories/new) form — not on public issue trackers. If you do not hear back within six business days, email security@syntheticsciences.ai. diff --git a/frontend/docs/src/content/openscience/sessions.mdx b/frontend/docs/src/content/openscience/sessions.mdx new file mode 100644 index 0000000..e2e118f --- /dev/null +++ b/frontend/docs/src/content/openscience/sessions.mdx @@ -0,0 +1,89 @@ +--- +title: "Sessions & one-shot runs" +description: "One agent conversation: history, tool calls, and a working directory. Create, resume, attach, and export." +icon: "layers" +--- + +A **session** is a single agent conversation: a thread of prompts and replies, the tool calls the agent made, and the working directory those calls ran against. Sessions are stored on disk, so everything below works offline and without an account. + +## Start a session + +| Entrypoint | Use | +| --- | --- | +| `openscience` | Open the [browser workspace](/openscience/workspace) in the current directory. | +| `openscience run [message..]` | Send one prompt from the terminal, stream the result, and exit. Good for pipelines, CI, and git hooks. | +| `openscience serve` | Start a headless server (no browser) for `run --attach` to target. | + +The workspace is interactive; `openscience run` is the one to script. Each produces a session you can resume from either surface. + +## One-shot runs + +```bash +openscience run "Set up a DFT optimization for this structure" -f data/sample.cif +git diff | openscience run "Review this diff for race conditions" +``` + +Piped stdin is appended to the message. `openscience run` supports: + +| Flag | Use | +| --- | --- | +| `-c, --continue` | Continue the most recent session. | +| `-s, --session ` | Continue a specific session by id. | +| `-m, --model ` | Model for this run, e.g. `anthropic/claude-opus-4-8`. See [Models](/openscience/models). | +| `--variant ` | Reasoning-effort tier (`high`, `max`, `minimal`; model-dependent). | +| `--agent ` | Run a specific primary agent. See [Agents](/openscience/agents). | +| `--command ` | Run a custom command, with the message as its arguments. | +| `-f, --file ` | Attach a local file to the message (repeatable). | +| `--title ` | Title for the session in `session list`. | +| `--format ` | `json` emits one JSON event per line (`tool_use`, `step_start`, `step_finish`, `text`, `error`), tagged with the session id — pipe it to a file and parse line by line. | +| `--attach ` | Send the prompt to a running server instead of starting one. | +| `--port ` | Port for the throwaway local server (random by default). | + +To pick up a file, always use `-f`; `--attach` targets a server, it does not fetch documents. + +## Continue or resume + +```bash +openscience session list # recent sessions (-n 10 to cap, --format json) +openscience run -c "Now add tests for the refactored module" +openscience run -s ses_8f2ka91xk "Rerun the sweep with lr=3e-4" +``` + +`session list` prints a table of ids, titles, and update times (paged through `less` in a terminal). In the workspace, the same sessions appear in the session history pane, where you can also queue prompts and undo from any message. + +## Attach to a running server + +Leave `openscience serve` (or the workspace) running and drive it from another terminal: + +```bash +openscience run --attach http://localhost:4096 "Summarize today's results" # new session on the server +openscience run --attach http://localhost:4096 -s ses_8f2ka91xk "Continue" # a specific session (-c: latest) +``` + +The run shares the server's sessions, so work started in the browser continues from the terminal and vice versa. + +## Export and import + +```bash +openscience export ses_8f2ka91xk > session.json # no id: interactive picker +openscience import session.json +``` + +`export` writes the full session as JSON to stdout; `import` loads it on another machine. Useful for sharing reproductions or attaching a transcript to an issue. + +## What's next + + + + The browser surface for the same sessions. + + + Per-run and per-session model choice. + + + Primary agents, specialists, and plan mode. + + + The full command reference. + + diff --git a/frontend/docs/src/content/openscience/skills.mdx b/frontend/docs/src/content/openscience/skills.mdx new file mode 100644 index 0000000..2612ef0 --- /dev/null +++ b/frontend/docs/src/content/openscience/skills.mdx @@ -0,0 +1,85 @@ +--- +title: "Skills" +description: "250+ bundled research skills, direct access to around 30 scientific databases, and commands for installing, writing, and pinning skills." +icon: "book-open" +--- + +A **skill** is a portable instruction bundle the agent loads into a session to prime it for a domain. OpenScience ships more than 250 of them, spanning the surface a working scientist actually hits. + +## Built-in categories + +| Category | Covers | +| --- | --- | +| Training | DeepSpeed, PEFT, TRL, distributed and parameter-efficient fine-tuning. | +| Evaluation | Harnesses, benchmarks, regression suites. | +| Datasets | Acquisition, cleaning, splits, augmentation. | +| Molecular & clinical biology | Sequence analysis, structures, omics, clinical data workflows. | +| Cheminformatics | Molecule handling, descriptors, property prediction. | +| Papers & LaTeX | Manuscript drafting, citations, submission-ready LaTeX. | +| Figures | Publication-quality plots and layouts. | +| Cloud compute | Modal, Tinker, and other GPU backends. | + +Run `openscience skill list --all` to print the full bundled set, grouped by category. + +## Scientific databases + +The major scientific databases are wired in as tools, not skills: UniProt, PDB, Ensembl, ChEMBL, PubChem, arXiv, OpenAlex, Semantic Scholar, and around 30 in total. The agent queries them directly during a session — no API keys, no manual downloads — and the specialist agents lean on them heavily (see [Agents](/openscience/agents)). + +## Skill commands + +| Command | Use | +| --- | --- | +| `openscience skill list` | Show learned and installed skills; `--all` includes the bundled set. | +| `openscience skill show [/]` | Namespace summary, or a single skill's full `SKILL.md`. | +| `openscience skill add ` | Install every skill from a public git repo; `gh:owner/repo` shorthand works. Runs a safety review. | +| `openscience skill new ` | Scaffold a local user skill. | +| `openscience skill edit ` | Open a user skill in `$EDITOR`. | +| `openscience skill validate ` | Check a skill's frontmatter and safety (`--strict` fails on warnings). | +| `openscience skill set-entries ` | Choose which skills in a namespace surface in the `/` picker. | +| `openscience skill remove ` | Uninstall a skill or a whole namespace. | + +## Install third-party skills + +```bash +openscience skill add gh:anthropics/superpowers +openscience skill list +``` + +Each skill in the repo passes a static safety check and an LLM safety review before it installs; rejected skills are skipped and reported. Installed skills are namespaced by repo, so `remove ` uninstalls the whole set. + +## Write your own + +```bash +openscience skill new leakage-checks --description "Checklists for spotting data leakage" --editor +``` + +A skill is a `SKILL.md` file with `name`, `description`, and `category` frontmatter and an instruction body. Iterate with `openscience skill edit` and check it with `openscience skill validate`. + +## Pin skills to a project + +Point the project config at extra skill folders with `skills.paths` in `openscience.json` at the project root: + +```json +{ + "skills": { "paths": ["./skills", "../shared-skills"] } +} +``` + +Sessions started in that directory load those skills, so teammates and CI get the same primed agent. Existing `.claude/skills/` directories are picked up unchanged. + +## What's next + + + + Pair skills with custom agent profiles to build specialists. + + + Full `skill` subcommand reference. + + + How the safety review and the subprocess allow-list protect you. + + + Sync the cloud and ML credentials a skill needs. + + diff --git a/frontend/docs/src/content/openscience/workspace.mdx b/frontend/docs/src/content/openscience/workspace.mdx new file mode 100644 index 0000000..c0990e2 --- /dev/null +++ b/frontend/docs/src/content/openscience/workspace.mdx @@ -0,0 +1,71 @@ +--- +title: "Workspace" +description: "The bare openscience command opens the browser workspace: files, editor, terminal, sessions, and inline scientific rendering." +icon: "app-window" +--- + +The workspace is how you use OpenScience. Run the bare command and it starts a local server, opens your browser, and gives you the full research surface: a file tree, an editor, a terminal, session history, and inline rendering for molecules, structures, genomes, and plots. + +```bash +openscience # open the workspace in the current directory +openscience ~/code/my-project # open it in a specific project +``` + +The server is local by design: it binds `127.0.0.1`, holds the agent in its own process, and serves the UI from the same port (`http://localhost:4096` by default; if 4096 is taken it falls back to a free port and prints the URL). Closing the browser tab does not kill the agent — reopen the URL to pick up where you left off. + +| Flag | Use | +| --- | --- | +| `--port ` | Bind a specific local port instead of the default 4096. | +| `--cors ` | Allow an extra CORS origin (repeatable). | + +The server always binds localhost — the deprecated `server.hostname` / `server.mdns` config keys are parsed but ignored. Persistent settings live in `~/.config/openscience/openscience.json` under `server.port` and `server.cors`. + +## What the workspace gives you + +- **File tree and editor.** Browse and edit the project the agent is working in; edits and diffs render inline. +- **Terminal.** A real shell in the project directory, alongside the agent's own tool calls. +- **Session history.** Every conversation is a session; switch between them without losing context. +- **Inline scientific rendering.** Molecules, protein structures, genomes, and plots render directly in the transcript instead of as file paths. +- **Prompt queueing.** Type your next prompt while the agent is still streaming; queued prompts run in order. +- **Undo from here.** Roll the session back to any message and take a different path from that point. +- **Model selector and credentials panel.** Pick any configured model per session and add provider keys without leaving the browser. See [Models](/openscience/models). + +## Headless server + +`openscience serve` starts the same server without opening a browser — useful for keeping a long-lived agent running that other terminals attach to. It takes the same `--port` and `--cors` flags and is loopback-only (`127.0.0.1`). + +```bash +openscience serve --port 4096 +openscience run --attach http://localhost:4096 "Continue the ablation sweep" +``` + +There is no separate attach subcommand: `openscience run --attach ` sends a one-shot prompt to the running server. See [Sessions](/openscience/sessions). + + +The workspace is intended for local use on a machine you control. The server binds `127.0.0.1` only and has no remote-access mode; do not reverse-proxy it to the public internet. + + +## macOS Full Disk Access + +On macOS, launching the workspace probes whether the binary can read `~/Desktop`. Without Full Disk Access, macOS silently returns empty listings for `~/Desktop`, `~/Documents`, and `~/Downloads`, so the folder picker and file tree look empty. If the probe fails, OpenScience opens System Settings on the Privacy & Security pane and prints the binary path to add: + +1. In **Full Disk Access**, click **+**, press ⌘⇧G, and paste the printed path. +2. Toggle the `openscience` entry on. +3. Quit (Ctrl+C) and relaunch `openscience`. + +## What's next + + + + Resume, attach, export, and one-shot runs. + + + BYOK providers and per-session model switching. + + + The research agent and its specialists. + + + The trust boundary and credential handling. + + diff --git a/frontend/docs/src/main.tsx b/frontend/docs/src/main.tsx new file mode 100644 index 0000000..90b1fc4 --- /dev/null +++ b/frontend/docs/src/main.tsx @@ -0,0 +1,10 @@ +import React from "react" +import { createRoot } from "react-dom/client" +import { App } from "./App" +import "./styles/index.css" + +createRoot(document.getElementById("root")!).render( + + + , +) diff --git a/frontend/docs/src/pages/[...slug].md.ts b/frontend/docs/src/pages/[...slug].md.ts deleted file mode 100644 index 51c63b5..0000000 --- a/frontend/docs/src/pages/[...slug].md.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { APIRoute } from "astro" -import { getCollection } from "astro:content" - -export const GET: APIRoute = async ({ params }) => { - const slug = params.slug || "index" - const docs = await getCollection("docs") - const doc = docs.find((d) => d.id === slug) - - if (!doc) { - return new Response("Not found", { status: 404 }) - } - - return new Response(doc.body, { - headers: { - "Content-Type": "text/plain; charset=utf-8", - }, - }) -} diff --git a/frontend/docs/src/pages/s/[id].astro b/frontend/docs/src/pages/s/[id].astro deleted file mode 100644 index 87f35dc..0000000 --- a/frontend/docs/src/pages/s/[id].astro +++ /dev/null @@ -1,113 +0,0 @@ ---- -import { Base64 } from "js-base64"; - -import config from '../../../config.mjs' -import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; -import Share from "../../components/Share.tsx"; - -const apiUrl = import.meta.env.VITE_API_URL; - -const { id } = Astro.params; -const res = await fetch(`${apiUrl}/share_data?id=${id}`); -const data = await res.json(); - -if (!data.info) { - return new Response(null, { - status: 404, - statusText: 'Not found' - }); -} - -const models: Set = new Set(); -const version = data.info.version ? `v${data.info.version}` : "v0.0.1"; - -Object.values(data.messages).forEach((d) => { - if (d.role === "assistant" && d.modelID) { - models.add(d.modelID); - } -}); - -const encodedTitle = encodeURIComponent( - Base64.encode( - // Convert to ASCII - encodeURIComponent( - // Truncate to fit S3's max key size - data.info.title.substring(0, 700), - ) - ) -); - -const modelsArray = Array.from(models); -let modelParam; -if (modelsArray.length === 1) { - modelParam = modelsArray[0]; -} -else if (modelsArray.length === 2) { - modelParam = encodeURIComponent(`${modelsArray[0]} & ${modelsArray[1]}`); -} -else { - modelParam = encodeURIComponent(`${modelsArray[0]} & ${modelsArray.length - 1} others`); -} - -const ogImage = `${config.socialCard}/openscience-share/${encodedTitle}.png?model=${modelParam}&version=${version}&id=${id}`; ---- - - - - - diff --git a/frontend/docs/src/styles/custom.css b/frontend/docs/src/styles/custom.css deleted file mode 100644 index 04331dd..0000000 --- a/frontend/docs/src/styles/custom.css +++ /dev/null @@ -1,405 +0,0 @@ -:root { - --sl-color-bg: hsl(0, 20%, 99%); - --sl-color-gray-5: hsl(0, 1%, 85%); - --sl-nav-gap: 40px; - --sl-color-text: hsl(0, 1%, 39%); - --sl-border-color: hsl(0, 1%, 85%); - --sl-color-hairline-shade: hsl(0, 1%, 85%); - - --color-background: hsl(0, 20%, 99%); - --color-background-weak: hsl(0, 8%, 97%); - --color-background-weak-hover: hsl(0, 8%, 94%); - --color-background-strong: hsl(0, 5%, 12%); - --color-background-strong-hover: hsl(0, 5%, 18%); - --color-background-interactive: hsl(62, 84%, 88%); - --color-background-interactive-weaker: hsl(64, 74%, 95%); - - --color-text: hsl(0, 1%, 39%); - --color-text-weak: hsl(0, 1%, 60%); - --color-text-weaker: hsl(0, 3%, 88%); - --color-text-strong: hsl(0, 5%, 12%); - --color-text-inverted: hsl(0, 20%, 99%); - - --color-border: hsl(30, 2%, 81%); - --color-border-weak: hsl(0, 1%, 85%); - - --color-icon: hsl(0, 1%, 55%); - - /* For the share component */ - --sl-color-bg-surface: var(--sl-color-bg-nav); - --sl-color-divider: var(--sl-color-gray-5); -} - -body { - color: var(--color-text) !important; - font-size: 14px !important; - - @media (prefers-color-scheme: dark) { - --sl-color-bg: hsl(0, 9%, 7%); - --sl-color-gray-5: hsl(0, 4%, 23%); - --sl-color-text: hsl(0, 4%, 71%); - --sl-border-color: hsl(0, 4%, 23%); - --sl-color-hairline-shade: hsl(0, 4%, 23%); - - --color-background: hsl(0, 9%, 7%); - --color-background-weak: hsl(0, 6%, 10%); - --color-background-strong: hsl(0, 15%, 94%); - --color-background-strong-hover: hsl(0, 15%, 97%); - --color-background-interactive: hsl(62, 100%, 90%); - --color-background-interactive-weaker: hsl(60, 20%, 8%); - - --color-text: hsl(0, 4%, 71%); - --color-text-weak: hsl(0, 2%, 49%); - --color-text-weaker: hsl(0, 3%, 28%); - --color-text-strong: hsl(0, 15%, 94%); - --color-text-inverted: hsl(0, 9%, 7%); - - --color-border: hsl(0, 3%, 28%); - --color-border-weak: hsl(0, 4%, 23%); - - --color-icon: hsl(10, 3%, 43%); - } -} - -.header:where(.astro-tcroauqe) { - border-bottom: 1px solid var(--color-border-weak) !important; -} - -.sl-markdown-content hr { - border-bottom: 1px solid var(--color-border-weak) !important; -} - -#starlight__on-this-page--mobile { - border-bottom: 1px solid var(--color-border-weak) !important; -} - -mobile-starlight-toc nav summary .toggle { - opacity: 60% !important; - text-decoration: none !important; -} - -nav.sidebar summary svg.caret { - color: var(--color-icon) !important; -} - -/* Search button style overrides */ -body > .page > header button[data-open-modal] > kbd { - position: relative; - display: flex; - gap: 4px; -} -body > .page > header button[data-open-modal] > kbd > kbd { - color: var(--color-icon) !important; - font-size: 15px; -} -/* Make the Cmd (⌘) keystroke bigger */ -body > .page > header button[data-open-modal][aria-keyshortcuts="Meta+K"] > kbd > kbd:first-child { - font-size: 20px; - line-height: 0.73; -} - -.starlight-aside__title { - flex: 0 0 auto; - margin-top: 3px; -} - -body > .page > .main-frame .main-pane > main > .content-panel + .content-panel { - border-top: none !important; -} - -body > .page > header a.site-title img { - height: 2rem !important; -} - -a { - color: var(--color-text-strong) !important; -} - -.page-description { - color: var(--color-text) !important; -} - -.right-sidebar { - border-inline-start: none !important; -} - -.sidebar-pane { - border-inline-end: 1px solid var(--color-border-weak) !important; -} - -.right-sidebar-panel { - padding: 24px 0 !important; - color: var(--color-text-weaker); -} - -.sidebar-content { - padding: 24px 0 !important; -} - -a[aria-current="page"] { - border-left: 2px solid var(--color-background-strong); - background: var(--color-background-weak) !important; - font-weight: 600 !important; -} - -ul.top-level a[aria-current="page"] > span { - color: var(--color-text-strong) !important; -} - -#starlight__sidebar > div > sl-sidebar-state-persist > ul > li > details > summary { - padding: 0 24px !important; - margin-top: 20px !important; -} - -#starlight__sidebar > div > sl-sidebar-state-persist > ul > li > details > summary:hover { - background: var(--color-background-weak); -} - -#starlight__sidebar > div > sl-sidebar-state-persist > ul > li > details > summary span { - color: var(--color-text-strong) !important; - font-weight: 600 !important; -} - -.top-level li a { - border-radius: 0; - width: 100%; - padding: 4px 24px !important; -} - -.top-level li a:hover { - background: var(--color-background-weak) !important; -} - -.right-group { - gap: 40px !important; -} - -.social-icons { - gap: 24px !important; -} - -.social-icons a svg { - height: 18px !important; - width: 18px !important; -} - -site-search > button { - text-transform: none !important; -} - -body > .page > header button[data-open-modal] { - gap: 12px !important; - background: var(--color-background-weak); - border: 1px solid var(--color-border-weak) !important; - padding: 6px 12px !important; - border-radius: 4px; - - @media (prefers-color-scheme: dark) { - background: var(--color-background-weak); - } -} - -body > .page > header button[data-open-modal] { - background: var(--color-background-weaker); -} - -site-search > button span { - text-decoration: none !important; -} - -.starlight-aside { - display: flex; - gap: 16px; - align-items: start; - - .starlight-aside__content { - margin-top: 0; - } - - @media (max-width: 768px) { - flex-direction: column; - gap: 6px; - } -} - -site-search > button > kbd { - font-size: 14px !important; -} - -h1 a, -h2 a, -h3 a, -h4 a, -h5 a, -h6 a { - color: var(--color-text-strong) !important; -} - -h1 { - font-size: 26px !important; - text-transform: none !important; - font-weight: 500 !important; - color: var(--color-text-strong) !important; -} - -h2 { - font-size: 22px !important; - text-transform: none !important; - font-weight: 500 !important; - color: var(--color-text-strong) !important; -} - -h3 { - font-size: 18px !important; - text-transform: none !important; - font-weight: 500 !important; - color: var(--color-text-strong) !important; -} - -h4 { - font-size: 16px !important; - text-transform: none !important; - font-weight: 500 !important; - color: var(--color-text-strong) !important; -} - -strong { - font-weight: 500 !important; -} - -ul, -ol { - list-style: none !important; - padding: 0 !important; -} - -.sl-markdown-content .tab > [role="tab"][aria-selected="true"] { - border-color: var(--color-text-strong); -} - -.social-icons a svg { - color: var(--color-text-weak) !important; -} - -.social-icons a svg:hover { - color: var(--color-text-strong) !important; -} - -body > .page > header, -:root[data-has-sidebar] body > .page > header { - background: var(--color-background) !important; - padding: 24px !important; -} - -.sl-container { - box-sizing: border-box !important; - width: 100% !important; -} - -.right-sidebar-panel nav, -.right-sidebar-panel h2, -.right-sidebar-panel ul, -.right-sidebar-panel li, -.right-sidebar-panel a { - display: block; - width: 100%; -} - -.sl-container { - max-width: 100% !important; -} - -nav.sidebar .sl-container ul li a, -div.right-sidebar .sl-container ul li a { - padding: 4px 24px !important; - width: 100% !important; - color: var(--color-text-weaker); - opacity: 50%; -} - -nav.sidebar .sl-container ul li a:hover, -div.right-sidebar .sl-container ul li a:hover { - background: var(--color-background-weak); - - @media (prefers-color-scheme: dark) { - background: var(--color-background-weak); - } -} - -nav.sidebar .sl-container ul li ul li, -div.right-sidebar .sl-container ul li ul li { - padding: 4px 12px 0 12px !important; -} - -nav.sidebar .sl-container ul li a[aria-current="true"], -div.right-sidebar .sl-container ul li a[aria-current="true"] { - color: var(--color-text-strong) !important; - opacity: 100%; -} - -h2#starlight__on-this-page { - font-size: 14px !important; - color: var(--color-text-strong) !important; - margin: 0 !important; - font-weight: 400 !important; - padding: 0 24px 12px 24px; -} - -#starlight__on-this-page ul { - color: var(--color-text-strong) !important; - font-size: 16px !important; -} - -.middle-group .links { - color: var(--color-icon); - text-decoration: none; - text-transform: none; - font-size: 16px; - display: none !important; -} - -.middle-group .links:hover { - text-decoration: underline; - text-underline-offset: 4px; - text-decoration-thickness: 1px; -} - -nav.sidebar ul.top-level > li > details > summary .group-label > span { - margin-top: 24px !important; - color: var(--color-text-strong) !important; - text-transform: none !important; - font-weight: 500 !important; -} - -.content-panel { - padding: 2rem 3rem !important; - - @media (max-width: 768px) { - padding: 1rem 1.5rem !important; - } -} - -.expressive-code { - margin: 0.75rem 0 3rem 0 !important; - border-radius: 6px; -} - -.expressive-code figure { - background: var(--color-background-weak) !important; -} - -.expressive-code .frame { - box-shadow: none; -} - -@media (prefers-color-scheme: dark) { - .shiki, - .shiki span { - color: var(--shiki-dark) !important; - background-color: var(--shiki-dark-bg) !important; - /* Optional, if you also want font styles */ - font-style: var(--shiki-dark-font-style) !important; - font-weight: var(--shiki-dark-font-weight) !important; - text-decoration: var(--shiki-dark-text-decoration) !important; - } -} diff --git a/frontend/docs/src/styles/index.css b/frontend/docs/src/styles/index.css new file mode 100644 index 0000000..98f6110 --- /dev/null +++ b/frontend/docs/src/styles/index.css @@ -0,0 +1,46 @@ +@font-face { + font-family: "Computer Modern Concrete"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/fonts/cmc/cmunorm.woff2") format("woff2"); +} +@font-face { + font-family: "Computer Modern Concrete"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url("/fonts/cmc/cmunobx.woff2") format("woff2"); +} + +:root { + color-scheme: light; +} + +html, +body { + margin: 0; + padding: 0; + min-height: 100dvh; + background: #fafbfc; + color: #0f172a; + font-family: "Computer Modern Concrete", "Concrete Roman", Georgia, "Times New Roman", serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-feature-settings: "kern", "liga"; +} + +#root { + min-height: 100dvh; + display: flex; + flex-direction: column; + isolation: isolate; +} + +* { + box-sizing: border-box; +} + +a { + color: inherit; +} diff --git a/frontend/docs/src/theme.ts b/frontend/docs/src/theme.ts new file mode 100644 index 0000000..52672d9 --- /dev/null +++ b/frontend/docs/src/theme.ts @@ -0,0 +1,34 @@ +import { useEffect, useState } from "react" + +export type Theme = "light" | "dark" + +function readStoredTheme(): Theme { + if (typeof window === "undefined") return "light" + try { + const stored = window.localStorage.getItem("docs-theme") + if (stored === "light" || stored === "dark") return stored + } catch { + /* localStorage unavailable */ + } + return "light" +} + +function applyTheme(theme: Theme) { + if (typeof document === "undefined") return + document.documentElement.classList.toggle("dark", theme === "dark") + document.documentElement.style.colorScheme = theme +} + +export function useTheme() { + const [theme, setTheme] = useState(readStoredTheme) + useEffect(() => { + applyTheme(theme) + try { + window.localStorage.setItem("docs-theme", theme) + } catch { + /* ignore */ + } + }, [theme]) + const toggle = () => setTheme((prev) => (prev === "dark" ? "light" : "dark")) + return { theme, toggle } +} diff --git a/frontend/docs/src/types/lang-map.d.ts b/frontend/docs/src/types/lang-map.d.ts deleted file mode 100644 index 6df26d6..0000000 --- a/frontend/docs/src/types/lang-map.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -declare module "lang-map" { - /** Returned by calling `map()` */ - export interface MapReturn { - /** All extensions keyed by language name */ - extensions: Record - /** All languages keyed by file-extension */ - languages: Record - } - - /** - * Calling `map()` gives you the raw lookup tables: - * - * ```js - * const { extensions, languages } = map(); - * ``` - */ - function map(): MapReturn - - /** Static method: get extensions for a given language */ - namespace map { - function extensions(language: string): string[] - /** Static method: get languages for a given extension */ - function languages(extension: string): string[] - } - - export = map -} diff --git a/frontend/docs/tsconfig.json b/frontend/docs/tsconfig.json index 9736038..1c7b947 100644 --- a/frontend/docs/tsconfig.json +++ b/frontend/docs/tsconfig.json @@ -1,9 +1,18 @@ { - "extends": "astro/tsconfigs/strict", - "include": [".astro/types.d.ts", "**/*"], - "exclude": ["dist"], "compilerOptions": { - "jsx": "preserve", - "jsxImportSource": "solid-js" - } + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "jsx": "react-jsx", + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "types": ["vite/client"] + }, + "include": ["src", "vite.config.ts"] } diff --git a/frontend/docs/vercel.json b/frontend/docs/vercel.json new file mode 100644 index 0000000..d5da268 --- /dev/null +++ b/frontend/docs/vercel.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "framework": "vite", + "buildCommand": "bun run build", + "installCommand": "bun install", + "outputDirectory": "dist", + "rewrites": [{ "source": "/docs/(.*)", "destination": "/docs/index.html" }] +} diff --git a/frontend/docs/vite.config.ts b/frontend/docs/vite.config.ts new file mode 100644 index 0000000..4056b5f --- /dev/null +++ b/frontend/docs/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vite" +import react from "@vitejs/plugin-react" + +// Served under openscience.sh/docs, so every asset URL resolves beneath /docs/. +export default defineConfig({ + base: "/docs/", + plugins: [react()], + assetsInclude: ["**/*.mdx"], +})