From a2cf22aff7e261c6930cad7c32acc88febfbebed Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:27:15 +0100 Subject: [PATCH 01/13] docs: add dependencies and build infrastructure for auto-generated provider docs --- bun.lock | 265 ++++++++- cli.json | 13 + package.json | 6 + .../generate-provider-docs.cpython-313.pyc | Bin 0 -> 19372 bytes scripts/generate-provider-docs.py | 511 ++++++++++++++++++ scripts/generate-provider-docs.sh | 24 + 6 files changed, 813 insertions(+), 6 deletions(-) create mode 100644 cli.json create mode 100644 scripts/__pycache__/generate-provider-docs.cpython-313.pyc create mode 100644 scripts/generate-provider-docs.py create mode 100644 scripts/generate-provider-docs.sh diff --git a/bun.lock b/bun.lock index 173a7b5..007e676 100644 --- a/bun.lock +++ b/bun.lock @@ -5,11 +5,14 @@ "": { "name": "docs", "dependencies": { + "@radix-ui/react-popover": "^1.1.15", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "fumadocs-core": "16.0.10", "fumadocs-mdx": "13.0.7", "fumadocs-ui": "16.0.10", "lucide-react": "^0.552.0", + "mermaid": "^11.12.2", "next": "16.0.1", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -32,6 +35,8 @@ "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], + "@biomejs/biome": ["@biomejs/biome@2.3.5", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.5", "@biomejs/cli-darwin-x64": "2.3.5", "@biomejs/cli-linux-arm64": "2.3.5", "@biomejs/cli-linux-arm64-musl": "2.3.5", "@biomejs/cli-linux-x64": "2.3.5", "@biomejs/cli-linux-x64-musl": "2.3.5", "@biomejs/cli-win32-arm64": "2.3.5", "@biomejs/cli-win32-x64": "2.3.5" }, "bin": { "biome": "bin/biome" } }, "sha512-HvLhNlIlBIbAV77VysRIBEwp55oM/QAjQEin74QQX9Xb259/XP/D5AGGnZMOyF1el4zcvlNYYR3AyTMUV3ILhg=="], "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fLdTur8cJU33HxHUUsii3GLx/TR0BsfQx8FkeqIiW33cGMtUD56fAtrh+2Fx1uhiCsVZlFh6iLKUU3pniZREQw=="], @@ -50,6 +55,18 @@ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.5", "", { "os": "win32", "cpu": "x64" }, "sha512-nUmR8gb6yvrKhtRgzwo/gDimPwnO5a4sCydf8ZS2kHIJhEmSmk+STsusr1LHTuM//wXppBawvSQi2xFXJCdgKQ=="], + "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.1", "", {}, "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw=="], + + "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@11.0.3", "", { "dependencies": { "@chevrotain/gast": "11.0.3", "@chevrotain/types": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ=="], + + "@chevrotain/gast": ["@chevrotain/gast@11.0.3", "", { "dependencies": { "@chevrotain/types": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q=="], + + "@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.0.3", "", {}, "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA=="], + + "@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="], + + "@chevrotain/utils": ["@chevrotain/utils@11.0.3", "", {}, "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="], + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.1", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg=="], "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.11", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "^1.20251106.1" }, "optionalPeers": ["workerd"] }, "sha512-se23f1D4PxKrMKOq+Stz+Yn7AJ9ITHcEecXo2Yjb+UgbUDCEBch1FXQC6hx6uT5fNA3kmX3mfzeZiUmpK1W9IQ=="], @@ -130,6 +147,10 @@ "@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.6.2", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA=="], + "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], + + "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="], + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], "@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=="], @@ -192,6 +213,8 @@ "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "1.0.8", "@types/estree-jsx": "1.0.5", "@types/hast": "3.0.4", "@types/mdx": "2.0.13", "acorn": "8.15.0", "collapse-white-space": "2.1.0", "devlop": "1.1.0", "estree-util-is-identifier-name": "3.0.0", "estree-util-scope": "1.0.0", "estree-walker": "3.0.3", "hast-util-to-jsx-runtime": "2.3.6", "markdown-extensions": "2.0.0", "recma-build-jsx": "1.0.0", "recma-jsx": "1.0.1", "recma-stringify": "1.0.0", "rehype-recma": "1.0.0", "remark-mdx": "3.1.1", "remark-parse": "11.0.0", "remark-rehype": "11.1.2", "source-map": "0.7.6", "unified": "11.0.5", "unist-util-position-from-estree": "2.0.0", "unist-util-stringify-position": "4.0.0", "unist-util-visit": "5.0.0", "vfile": "6.0.3" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], + "@mermaid-js/parser": ["@mermaid-js/parser@0.6.3", "", { "dependencies": { "langium": "3.3.1" } }, "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA=="], + "@next/env": ["@next/env@16.0.1", "", {}, "sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw=="], "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg=="], @@ -262,7 +285,7 @@ "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "optionalDependencies": { "@types/react": "19.2.3", "@types/react-dom": "19.2.2" }, "peerDependencies": { "react": "19.2.0", "react-dom": "19.2.0" } }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="], - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "optionalDependencies": { "@types/react": "19.2.3", "@types/react-dom": "19.2.2" }, "peerDependencies": { "react": "19.2.0", "react-dom": "19.2.0" } }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="], @@ -342,12 +365,76 @@ "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.17", "", { "dependencies": { "@alloc/quick-lru": "5.2.0", "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "postcss": "8.5.6", "tailwindcss": "4.1.17" } }, "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw=="], + "@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="], + + "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="], + + "@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="], + + "@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="], + + "@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="], + + "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="], + + "@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="], + + "@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="], + + "@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="], + + "@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="], + + "@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="], + + "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="], + + "@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="], + + "@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="], + + "@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="], + + "@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="], + + "@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="], + + "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="], + + "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="], + + "@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="], + + "@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="], + + "@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="], + + "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="], + + "@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="], + + "@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="], + + "@types/d3-shape": ["@types/d3-shape@3.1.7", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg=="], + + "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], + + "@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="], + + "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="], + + "@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="], + + "@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="], + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "2.1.0" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "1.0.8" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "3.0.3" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "3.0.3" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], @@ -362,6 +449,8 @@ "@types/react-dom": ["@types/react-dom@19.2.2", "", { "peerDependencies": { "@types/react": "19.2.3" } }, "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw=="], + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], @@ -394,6 +483,10 @@ "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], + "chevrotain": ["chevrotain@11.0.3", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.0.3", "@chevrotain/gast": "11.0.3", "@chevrotain/regexp-to-ast": "11.0.3", "@chevrotain/types": "11.0.3", "@chevrotain/utils": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw=="], + + "chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "4.1.2" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], @@ -414,18 +507,100 @@ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + "commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], + "compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="], + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "cookie": ["cookie@1.1.0", "", {}, "sha512-vXiThu1/rlos7EGu8TuNZQEg2e9TvhH9dmS4T4ZVzB7Ao1agEZ6EG3sn5n+hZRYUgduISd1HpngFzAZiDGm5vQ=="], + "cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="], + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="], + + "cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="], + + "cytoscape-fcose": ["cytoscape-fcose@2.2.0", "", { "dependencies": { "cose-base": "^2.2.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="], + + "d3": ["d3@7.9.0", "", { "dependencies": { "d3-array": "3", "d3-axis": "3", "d3-brush": "3", "d3-chord": "3", "d3-color": "3", "d3-contour": "4", "d3-delaunay": "6", "d3-dispatch": "3", "d3-drag": "3", "d3-dsv": "3", "d3-ease": "3", "d3-fetch": "3", "d3-force": "3", "d3-format": "3", "d3-geo": "3", "d3-hierarchy": "3", "d3-interpolate": "3", "d3-path": "3", "d3-polygon": "3", "d3-quadtree": "3", "d3-random": "3", "d3-scale": "4", "d3-scale-chromatic": "3", "d3-selection": "3", "d3-shape": "3", "d3-time": "3", "d3-time-format": "4", "d3-timer": "3", "d3-transition": "3", "d3-zoom": "3" } }, "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="], + + "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], + + "d3-axis": ["d3-axis@3.0.0", "", {}, "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="], + + "d3-brush": ["d3-brush@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "3", "d3-transition": "3" } }, "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="], + + "d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="], + + "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], + + "d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="], + + "d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="], + + "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], + + "d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="], + + "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="], + + "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="], + + "d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="], + + "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="], + + "d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="], + + "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="], + + "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="], + + "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], + + "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], + + "d3-polygon": ["d3-polygon@3.0.1", "", {}, "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="], + + "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="], + + "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="], + + "d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="], + + "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], + + "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="], + + "d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="], + + "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], + + "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], + + "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], + + "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], + + "d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="], + + "d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="], + + "dagre-d3-es": ["dagre-d3-es@7.0.13", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q=="], + + "dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "2.0.2" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], + "delaunator": ["delaunator@5.0.1", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw=="], + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], @@ -434,6 +609,8 @@ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "2.0.3" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + "dompurify": ["dompurify@3.3.1", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q=="], + "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "4.2.11", "tapable": "2.3.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], @@ -484,6 +661,8 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="], + "hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "1.0.8", "@types/estree-jsx": "1.0.5", "@types/hast": "3.0.4", "comma-separated-tokens": "2.0.3", "devlop": "1.1.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.1", "mdast-util-mdx-jsx": "3.2.0", "mdast-util-mdxjs-esm": "2.0.1", "property-information": "7.1.0", "space-separated-tokens": "2.0.2", "style-to-js": "1.1.19", "unist-util-position": "5.0.0", "zwitch": "2.0.4" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="], "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "3.0.4", "@types/unist": "3.0.3", "ccount": "2.0.1", "comma-separated-tokens": "2.0.3", "hast-util-whitespace": "3.0.0", "html-void-elements": "3.0.0", "mdast-util-to-hast": "13.2.0", "property-information": "7.1.0", "space-separated-tokens": "2.0.2", "stringify-entities": "4.0.4", "zwitch": "2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], @@ -496,10 +675,14 @@ "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "image-size": ["image-size@2.0.2", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w=="], "inline-style-parser": ["inline-style-parser@0.2.6", "", {}, "sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg=="], + "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], + "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.1", "is-decimal": "2.0.1" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], @@ -516,8 +699,16 @@ "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "katex": ["katex@0.16.27", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw=="], + + "khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "langium": ["langium@3.3.1", "", { "dependencies": { "chevrotain": "~11.0.3", "chevrotain-allstar": "~0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.0.8" } }, "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w=="], + + "layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="], + "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "2.1.2" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], @@ -542,6 +733,8 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + "lodash-es": ["lodash-es@4.17.22", "", {}, "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], @@ -556,6 +749,8 @@ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "4.0.4", "escape-string-regexp": "5.0.0", "unist-util-is": "6.0.1", "unist-util-visit-parents": "6.0.2" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "4.0.4", "@types/unist": "3.0.3", "decode-named-character-reference": "1.2.0", "devlop": "1.1.0", "mdast-util-to-string": "4.0.0", "micromark": "4.0.2", "micromark-util-decode-numeric-character-reference": "2.0.2", "micromark-util-decode-string": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2", "unist-util-stringify-position": "4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], @@ -588,6 +783,8 @@ "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "4.0.4" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + "mermaid": ["mermaid@11.12.2", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", "@mermaid-js/parser": "^0.6.3", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.13", "dayjs": "^1.11.18", "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", "lodash-es": "^4.17.21", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w=="], + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "4.1.12", "debug": "4.4.3", "decode-named-character-reference": "1.2.0", "devlop": "1.1.0", "micromark-core-commonmark": "2.0.3", "micromark-factory-space": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-combine-extensions": "2.0.1", "micromark-util-decode-numeric-character-reference": "2.0.2", "micromark-util-encode": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-sanitize-uri": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "1.2.0", "devlop": "1.1.0", "micromark-factory-destination": "2.0.1", "micromark-factory-label": "2.0.1", "micromark-factory-space": "2.0.1", "micromark-factory-title": "2.0.1", "micromark-factory-whitespace": "2.0.1", "micromark-util-character": "2.1.1", "micromark-util-chunked": "2.0.1", "micromark-util-classify-character": "2.0.1", "micromark-util-html-tag-name": "2.0.1", "micromark-util-normalize-identifier": "2.0.1", "micromark-util-resolve-all": "2.0.1", "micromark-util-subtokenize": "2.1.0", "micromark-util-symbol": "2.0.1", "micromark-util-types": "2.0.2" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], @@ -662,6 +859,8 @@ "miniflare": ["miniflare@4.20251125.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251125.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-xY6deLx0Drt8GfGG2Fv0fHUocHAIG/Iv62Kl36TPfDzgq7/+DQ5gYNisxnmyISQdA/sm7kOvn2XRBncxjWYrLg=="], + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], @@ -678,8 +877,12 @@ "oniguruma-to-es": ["oniguruma-to-es@4.3.3", "", { "dependencies": { "oniguruma-parser": "0.12.1", "regex": "6.0.1", "regex-recursion": "6.0.2" } }, "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg=="], + "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "2.0.11", "character-entities-legacy": "3.0.0", "character-reference-invalid": "2.0.1", "decode-named-character-reference": "1.2.0", "is-alphanumerical": "2.0.1", "is-decimal": "2.0.1", "is-hexadecimal": "2.0.1" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="], + "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -688,6 +891,12 @@ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="], + + "points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="], + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "3.3.11", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], "postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "3.0.0", "util-deprecate": "1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], @@ -736,6 +945,14 @@ "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "4.0.4", "mdast-util-to-markdown": "2.1.2", "unified": "11.0.5" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + "robust-predicates": ["robust-predicates@3.0.2", "", {}, "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="], + + "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="], + + "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "3.1.1" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="], @@ -764,6 +981,8 @@ "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], + "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], @@ -780,10 +999,14 @@ "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "ufo": ["ufo@1.6.2", "", {}, "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q=="], + "undici": ["undici@7.14.0", "", {}, "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ=="], "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], @@ -812,10 +1035,24 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "3.0.3", "vfile-message": "4.0.3" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "3.0.3", "unist-util-stringify-position": "4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], + + "vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], + + "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="], + + "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="], + + "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], + + "vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="], + "workerd": ["workerd@1.20251125.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251125.0", "@cloudflare/workerd-darwin-arm64": "1.20251125.0", "@cloudflare/workerd-linux-64": "1.20251125.0", "@cloudflare/workerd-linux-arm64": "1.20251125.0", "@cloudflare/workerd-windows-64": "1.20251125.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-oQYfgu3UZ15HlMcEyilKD1RdielRnKSG5MA0xoi1theVs99Rop9AEFYicYCyK1R4YjYblLRYEiL1tMgEFqpReA=="], "wrangler": ["wrangler@4.51.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.1", "@cloudflare/unenv-preset": "2.7.11", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251125.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20251125.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251125.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-JHv+58UxM2//e4kf9ASDwg016xd/OdDNDUKW6zLQyE7Uc9ayYKX1QJ9NsYtpo4dC1dfg6rT67pf1aNK1cTzUDg=="], @@ -830,19 +1067,25 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + "@chevrotain/cst-dts-gen/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + + "@chevrotain/gast/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + "@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=="], "@mdx-js/mdx/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "acorn-jsx/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "chevrotain/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], - "@radix-ui/react-popover/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="], - "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - "acorn-jsx/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], + + "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="], "esast-util-from-js/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], @@ -850,18 +1093,28 @@ "fumadocs-mdx/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=="], + "fumadocs-ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "optionalDependencies": { "@types/react": "19.2.3" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], + "micromark-extension-mdxjs/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "miniflare/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=="], "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], + "mlly/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "3.3.11", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "recma-jsx/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="], + + "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="], + + "d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="], + "fumadocs-mdx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], "fumadocs-mdx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], diff --git a/cli.json b/cli.json new file mode 100644 index 0000000..89d5151 --- /dev/null +++ b/cli.json @@ -0,0 +1,13 @@ +{ + "$schema": "node_modules/@fumadocs/cli/dist/schema/src.json", + "aliases": { + "uiDir": "./components/ui", + "componentsDir": "./components", + "blockDir": "./components", + "cssDir": "./styles", + "libDir": "./lib" + }, + "baseDir": "src", + "uiLibrary": "radix-ui", + "commands": {} +} \ No newline at end of file diff --git a/package.json b/package.json index 5fd7e70..a140c75 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "version": "0.0.0", "private": true, "scripts": { + "generate-provider-docs": "bash scripts/generate-provider-docs.sh", "build": "next build", "dev": "next dev", + "prebuild": "CELESTE_SOURCE=local bun run generate-provider-docs", + "predev": "CELESTE_SOURCE=local bun run generate-provider-docs", "start": "next start", "postinstall": "fumadocs-mdx", "lint": "biome check", @@ -13,11 +16,14 @@ "deploy": "bun run build && bunx wrangler deploy" }, "dependencies": { + "@radix-ui/react-popover": "^1.1.15", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "fumadocs-core": "16.0.10", "fumadocs-mdx": "13.0.7", "fumadocs-ui": "16.0.10", "lucide-react": "^0.552.0", + "mermaid": "^11.12.2", "next": "16.0.1", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/scripts/__pycache__/generate-provider-docs.cpython-313.pyc b/scripts/__pycache__/generate-provider-docs.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..514496a54995dbd3024cc542107859756e7c5f93 GIT binary patch literal 19372 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 J3SP!S{tph?G1&kB literal 0 HcmV?d00001 diff --git a/scripts/generate-provider-docs.py b/scripts/generate-provider-docs.py new file mode 100644 index 0000000..d8c086b --- /dev/null +++ b/scripts/generate-provider-docs.py @@ -0,0 +1,511 @@ +#!/usr/bin/env python3 +"""Generate provider documentation pages from the Celeste model registry. + +This script keeps docs/content/docs/providers in sync with the source-of-truth +Celeste registry (celeste.list_models()). + +Design goals: +- Avoid documentation drift: model lists and providers nav are generated. +- Preserve manual prose: only the models block is rewritten (marker-based). +""" + +from __future__ import annotations + +import json +import re +from dataclasses import dataclass +from pathlib import Path + + +# MDX does not support HTML comments (``) because it treats them as JSX-like tags. +# Use MDX-safe JSX comments instead. +MODELS_START_MARKER = "{/* AUTO-GENERATED:MODELS:START */}" +MODELS_END_MARKER = "{/* AUTO-GENERATED:MODELS:END */}" + +# Backward compatibility: migrate legacy HTML markers created by earlier versions of this script. +LEGACY_MODELS_START_MARKER = "" +LEGACY_MODELS_END_MARKER = "" + +SUPPORTED_PROVIDERS_START_MARKER = "{/* AUTO-GENERATED:SUPPORTED_PROVIDERS:START */}" +SUPPORTED_PROVIDERS_END_MARKER = "{/* AUTO-GENERATED:SUPPORTED_PROVIDERS:END */}" + + +@dataclass(frozen=True) +class ProviderPageInput: + provider: object + slug: str + title: str + description: str + logo_slug: str | None + + +def _docs_root() -> Path: + # docs/scripts/generate-provider-docs.py -> docs/ + return Path(__file__).resolve().parents[1] + + +def _providers_dir(docs_root: Path) -> Path: + return docs_root / "content" / "docs" / "providers" + +def _index_page_path(docs_root: Path) -> Path: + return docs_root / "content" / "docs" / "index.mdx" + + +def _logos_dir(docs_root: Path) -> Path: + return docs_root / "public" / "logos" + + +def _provider_title(provider: object) -> str: + """Human-friendly provider name from Provider StrEnum (with a few casing exceptions).""" + from celeste.core import Provider # type: ignore + + mapping: dict[Provider, str] = { + Provider.OPENAI: "OpenAI", + Provider.XAI: "xAI", + Provider.BYTEPLUS: "BytePlus", + Provider.ELEVENLABS: "ElevenLabs", + Provider.STABILITYAI: "StabilityAI", + Provider.TOPAZLABS: "TopazLabs", + Provider.DEEPSEEK: "DeepSeek", + Provider.HUGGINGFACE: "HuggingFace", + Provider.BFL: "Black Forest Labs", + } + + if isinstance(provider, Provider) and provider in mapping: + return mapping[provider] + + provider_slug = getattr(provider, "value", str(provider)) + return provider_slug.replace("-", " ").title() + + +def _provider_logo_slug(provider: object) -> str | None: + # Docs currently have bytedance.svg; Celeste provider slug is byteplus. + provider_slug = getattr(provider, "value", str(provider)) + if provider_slug == "byteplus": + return "bytedance" + return provider_slug + + +def _build_provider_page_input(provider: object, docs_root: Path) -> ProviderPageInput: + provider_slug = getattr(provider, "value", str(provider)) + title = _provider_title(provider) + description = f"Documentation for the {title} provider." + + candidate_logo_slug = _provider_logo_slug(provider) + if candidate_logo_slug is None: + return ProviderPageInput( + provider=provider, + slug=provider_slug, + title=title, + description=description, + logo_slug=None, + ) + + logo_path = _logos_dir(docs_root) / f"{candidate_logo_slug}.svg" + logo_slug = candidate_logo_slug if logo_path.exists() else None + + return ProviderPageInput( + provider=provider, + slug=provider_slug, + title=title, + description=description, + logo_slug=logo_slug, + ) + + +def _render_supported_providers_block(providers: list[ProviderPageInput]) -> str: + # For logos that are mostly monochrome, invert in dark mode. + dark_invert_logo_slugs = {"anthropic", "openai", "xai", "elevenlabs", "bfl", "groq"} + + lines: list[str] = [] + lines.append('") + return "\n".join(lines).strip() + "\n" + + +def _replace_supported_providers_region(page_text: str, block: str) -> str: + pattern = re.compile( + rf"(?s){re.escape(SUPPORTED_PROVIDERS_START_MARKER)}.*?{re.escape(SUPPORTED_PROVIDERS_END_MARKER)}" + ) + replacement = ( + f"{SUPPORTED_PROVIDERS_START_MARKER}\n\n" + f"{block.rstrip()}\n\n" + f"{SUPPORTED_PROVIDERS_END_MARKER}" + ) + + if not pattern.search(page_text): + msg = ( + "Supported Providers markers not found in docs/content/docs/index.mdx. " + "Add the markers so the section can be auto-generated." + ) + raise ValueError(msg) + + return pattern.sub(replacement, page_text, count=1) + + +def _ensure_supported_providers_index_section( + *, + docs_root: Path, + providers: list[ProviderPageInput], +) -> None: + index_path = _index_page_path(docs_root) + if not index_path.exists(): + return + + existing = index_path.read_text(encoding="utf-8") + updated = _replace_supported_providers_region( + existing, _render_supported_providers_block(providers) + ) + index_path.write_text(updated.rstrip() + "\n", encoding="utf-8") + + +def _format_supported_ops_cell(ops_by_modality: dict[str, set[str]]) -> str: + parts: list[str] = [] + for modality in sorted(ops_by_modality.keys()): + for operation in sorted(ops_by_modality[modality]): + parts.append(f"`{modality}.{operation}`") + return ", ".join(parts) if parts else "-" + + +def _render_models_table(models: list[object]) -> str: + """Render a models list as a markdown table (legacy).""" + lines: list[str] = [] + lines.append("| Model ID | Display name | Supports (modality.operation) | Streaming |") + lines.append("| :--- | :--- | :--- | :--- |") + + for model in sorted( + models, + key=lambda m: (getattr(m, "display_name"), getattr(m, "id")), + ): + model_id = getattr(model, "id") + display_name = getattr(model, "display_name") + streaming = "Yes" if bool(getattr(model, "streaming", False)) else "No" + + ops_by_modality: dict[str, set[str]] = {} + operations = getattr(model, "operations", {}) or {} + for modality, ops in operations.items(): + modality_value = getattr(modality, "value", str(modality)) + ops_values = {getattr(op, "value", str(op)) for op in (ops or set())} + if ops_values: + ops_by_modality.setdefault(modality_value, set()).update(ops_values) + + supports_cell = _format_supported_ops_cell(ops_by_modality) + + lines.append( + f"| `{model_id}` | {display_name} | {supports_cell} | {streaming} |" + ) + + return "\n".join(lines).strip() + "\n" + + +def _collect_ops_by_modality(models: list[object]) -> dict[str, set[str]]: + ops_by_modality: dict[str, set[str]] = {} + for model in models: + operations = getattr(model, "operations", {}) or {} + for modality, ops in operations.items(): + modality_value = getattr(modality, "value", str(modality)) + ops_values = {getattr(op, "value", str(op)) for op in (ops or set())} + if ops_values: + ops_by_modality.setdefault(modality_value, set()).update(ops_values) + return ops_by_modality + + +def _collect_models_by_modality(models: list[object]) -> dict[str, list[object]]: + models_by_modality: dict[str, list[object]] = {} + for model in models: + operations = getattr(model, "operations", {}) or {} + for modality, ops in operations.items(): + modality_value = getattr(modality, "value", str(modality)) + ops_values = {getattr(op, "value", str(op)) for op in (ops or set())} + if ops_values: + models_by_modality.setdefault(modality_value, []).append(model) + return models_by_modality + + +def _render_available_modalities(models: list[object]) -> str: + """Render a provider-level modalities summary (union of ops across models).""" + ops_by_modality: dict[str, set[str]] = {} + ops_by_modality = _collect_ops_by_modality(models) + + if not ops_by_modality: + return "" + + lines: list[str] = [] + lines.append("Available modalities:") + lines.append("") + for modality in sorted(ops_by_modality.keys()): + ops = ", ".join(f"`{op}`" for op in sorted(ops_by_modality[modality])) + lines.append(f"- `{modality}`: {ops}") + return "\n".join(lines).strip() + + +def _modality_title(modality: str) -> str: + mapping = { + "text": "Text", + "images": "Images", + "audio": "Audio", + "videos": "Videos", + "embeddings": "Embeddings", + } + return mapping.get(modality, modality.replace("-", " ").title()) + + +def _format_operations_list(ops: set[str]) -> str: + return ", ".join(f"`{op}`" for op in sorted(ops)) if ops else "-" + + +def _render_models_table_for_modality(models: list[object], modality: str) -> str: + lines: list[str] = [] + lines.append("| Model ID | Display name | Operations | Streaming |") + lines.append("| :--- | :--- | :--- | :--- |") + + rows: list[tuple[str, str, str, str]] = [] + for model in models: + operations = getattr(model, "operations", {}) or {} + ops_set: set[str] = set() + for mod, ops in operations.items(): + mod_value = getattr(mod, "value", str(mod)) + if mod_value != modality: + continue + ops_set = {getattr(op, "value", str(op)) for op in (ops or set())} + break + + if not ops_set: + continue + + model_id = getattr(model, "id") + display_name = getattr(model, "display_name") + streaming = "Yes" if bool(getattr(model, "streaming", False)) else "No" + rows.append((display_name, model_id, _format_operations_list(ops_set), streaming)) + + for display_name, model_id, ops_cell, streaming in sorted(rows): + lines.append(f"| `{model_id}` | {display_name} | {ops_cell} | {streaming} |") + + return "\n".join(lines).strip() + "\n" + + +def _render_models_block(models: list[object]) -> str: + """Render the full auto-generated content inserted between the models markers.""" + parts: list[str] = [] + parts.append("This section is auto-generated from the Celeste registry. Do not edit manually.") + + summary = _render_available_modalities(models) + if summary: + parts.append("") + parts.append(summary) + + models_by_modality = _collect_models_by_modality(models) + modality_order = ["text", "images", "audio", "videos", "embeddings"] + extra_modalities = sorted(set(models_by_modality.keys()) - set(modality_order)) + ordered_modalities = [m for m in modality_order if m in models_by_modality] + extra_modalities + + for modality in ordered_modalities: + parts.append("") + parts.append(f"### {_modality_title(modality)}") + parts.append("") + parts.append(_render_models_table_for_modality(models_by_modality[modality], modality).strip()) + + return "\n".join(parts).strip() + "\n" + + +def _render_credentials(provider: object) -> str: + """Render the credential guidance for a provider (env var or auth class).""" + try: + from celeste.credentials import get_auth_config # type: ignore + from celeste.exceptions import UnsupportedProviderError # type: ignore + except ImportError: + return "See the Celeste authentication guide for provider-specific credential setup." + + try: + auth_config = get_auth_config(provider) + except UnsupportedProviderError: + return "See the Celeste authentication guide for provider-specific credential setup." + + if isinstance(auth_config, tuple): + secret_name, _header, _prefix = auth_config + return "\n".join( + [ + f"Set the `{secret_name}` environment variable.", + "", + "```bash", + f'export {secret_name}="..."', + "```", + ] + ) + + # Auth config is a class (ADC/OAuth/custom auth), so there is no API key env var. + auth_class = auth_config + auth_name = getattr(auth_class, "__name__", "Authentication") + return f"This provider uses `{auth_name}` authentication (no API key required)." + + +def _render_models_section(models: list[object]) -> str: + block = _render_models_block(models) + return ( + "## Models\n\n" + f"{MODELS_START_MARKER}\n\n" + f"{block}\n" + f"{MODELS_END_MARKER}\n" + ) + + +def _strip_legacy_models_lists(page_text: str) -> str: + # Replace legacy manually-maintained bullet lists under "### Models" headings. + # + # Example: + # ### Models + # - `gpt-4o` + # - `gpt-4o-mini` + # + # becomes: + # ### Models + # + # (See the auto-generated **Models** section below.) + # + pattern = re.compile(r"(?ms)^### Models\\s*\\n(?:\\s*\\n)*(?:- .*(?:\\n|$))+") + + def repl(_: re.Match[str]) -> str: + return "### Models\n\n(See the auto-generated **Models** section below.)\n\n" + + return pattern.sub(repl, page_text) + + +def _normalize_models_markers(page_text: str) -> str: + """Normalize legacy HTML markers to MDX-safe markers.""" + if LEGACY_MODELS_START_MARKER not in page_text and LEGACY_MODELS_END_MARKER not in page_text: + return page_text + return ( + page_text.replace(LEGACY_MODELS_START_MARKER, MODELS_START_MARKER).replace( + LEGACY_MODELS_END_MARKER, MODELS_END_MARKER + ) + ) + + +def _replace_models_region(page_text: str, models_table: str) -> str: + """Replace the content between MODELS_START_MARKER and MODELS_END_MARKER.""" + start = page_text.index(MODELS_START_MARKER) + len(MODELS_START_MARKER) + end = page_text.index(MODELS_END_MARKER) + return page_text[:start] + "\n\n" + models_table.strip() + "\n" + page_text[end:] + + +def _ensure_provider_page( + *, + provider: ProviderPageInput, + models: list[object], + providers_dir: Path, +) -> None: + target = providers_dir / f"{provider.slug}.mdx" + models_section = _render_models_section(models) + models_block = _render_models_block(models) + + if target.exists(): + existing = _normalize_models_markers(target.read_text(encoding="utf-8")) + + updated = existing + if MODELS_START_MARKER in existing and MODELS_END_MARKER in existing: + updated = _replace_models_region(existing, models_block) + else: + # First-time migration of a manually-written page. + updated = _strip_legacy_models_lists(existing).rstrip() + "\n\n" + models_section + + target.write_text(updated.rstrip() + "\n", encoding="utf-8") + return + + # Create a new provider page. + logo_block = "" + if provider.logo_slug is not None: + logo_block = ( + f'\n\n' + ) + + new_page = ( + "---\n" + f"title: {provider.title}\n" + f"description: {provider.description}\n" + "---\n\n" + f"{logo_block}" + f"Celeste supports the **{provider.title}** provider.\n\n" + "## Credentials\n\n" + f"{_render_credentials(provider.provider)}\n\n" + f"{models_section}\n" + "## Notes\n\n" + "_Add provider-specific tips, caveats, and examples here._\n" + ) + + target.write_text(new_page.rstrip() + "\n", encoding="utf-8") + + +def main() -> None: + # Import Celeste lazily so this script can be invoked via `uv run` easily. + from celeste import list_models # type: ignore + + docs_root = _docs_root() + providers_dir = _providers_dir(docs_root) + providers_dir.mkdir(parents=True, exist_ok=True) + + all_models = list_models() + + # Group models by provider (Provider StrEnum from Celeste). + providers_to_models: dict[object, list[object]] = {} + for model in all_models: + provider = getattr(model, "provider") + providers_to_models.setdefault(provider, []).append(model) + + # Create/update provider pages. + for provider, provider_models in sorted( + providers_to_models.items(), + key=lambda item: getattr(item[0], "value", str(item[0])), + ): + provider_input = _build_provider_page_input(provider, docs_root) + _ensure_provider_page( + provider=provider_input, + models=provider_models, + providers_dir=providers_dir, + ) + + # Generate providers meta.json for sidebar navigation. + meta_path = providers_dir / "meta.json" + providers_pages = [ + getattr(provider, "value", str(provider)) + for provider in sorted( + providers_to_models.keys(), + key=lambda p: getattr(p, "value", str(p)), + ) + ] + meta = {"title": "Providers", "pages": providers_pages} + meta_path.write_text(json.dumps(meta, indent=2) + "\n", encoding="utf-8") + + # Keep the home page "Supported Providers" section in sync. + index_providers = [ + _build_provider_page_input(provider, docs_root) + for provider in sorted( + providers_to_models.keys(), + key=lambda p: getattr(p, "value", str(p)), + ) + ] + _ensure_supported_providers_index_section(docs_root=docs_root, providers=index_providers) + + +if __name__ == "__main__": + main() + diff --git a/scripts/generate-provider-docs.sh b/scripts/generate-provider-docs.sh new file mode 100644 index 0000000..f570d8f --- /dev/null +++ b/scripts/generate-provider-docs.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Generate provider docs from the Celeste model registry. +# +# Mirrors the website pattern: +# - CELESTE_SOURCE=local -> run against local workspace (celeste-python-private) +# - otherwise -> run against PyPI (celeste-ai[all]) + +set -euo pipefail + +cd "$(dirname "$0")/.." +DOCS_ROOT="$(pwd)" + +if [ "${CELESTE_SOURCE:-}" = "local" ]; then + WORKSPACE_ROOT="$(cd .. && pwd)" + CELESTE_PY_PRIVATE_ROOT="$WORKSPACE_ROOT/celeste-python-private" + + cd "$CELESTE_PY_PRIVATE_ROOT" + # Run against the local workspace project. + uv run python "$DOCS_ROOT/scripts/generate-provider-docs.py" + cd "$DOCS_ROOT" +else + uv run --no-project --with "celeste-ai" python scripts/generate-provider-docs.py +fi + From 8efbf0418b5cd0d65c1ba13a8819a5709403e858 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:27:35 +0100 Subject: [PATCH 02/13] docs: migrate from capability-based to modality-based structure --- .../docs/capabilities/image-generation.mdx | 57 ------- .../docs/capabilities/speech-generation.mdx | 65 ------- content/docs/capabilities/text-generation.mdx | 66 -------- .../docs/capabilities/video-generation.mdx | 56 ------- content/docs/core-concepts/capabilities.mdx | 50 ------ content/docs/core-concepts/meta.json | 5 + .../core-concepts/modality-and-operation.mdx | 158 ++++++++++++++++++ content/docs/domains/audio.mdx | 38 +++++ content/docs/domains/images.mdx | 38 +++++ content/docs/domains/index.mdx | 41 +++++ content/docs/domains/meta.json | 4 + content/docs/domains/text.mdx | 35 ++++ content/docs/domains/video.mdx | 37 ++++ content/docs/meta.json | 3 + content/docs/modalities/audio.mdx | 68 ++++++++ content/docs/modalities/embeddings.mdx | 67 ++++++++ content/docs/modalities/images.mdx | 69 ++++++++ content/docs/modalities/index.mdx | 26 +++ content/docs/modalities/meta.json | 4 + content/docs/modalities/text.mdx | 94 +++++++++++ content/docs/modalities/video.mdx | 52 ++++++ 21 files changed, 739 insertions(+), 294 deletions(-) delete mode 100644 content/docs/capabilities/image-generation.mdx delete mode 100644 content/docs/capabilities/speech-generation.mdx delete mode 100644 content/docs/capabilities/text-generation.mdx delete mode 100644 content/docs/capabilities/video-generation.mdx delete mode 100644 content/docs/core-concepts/capabilities.mdx create mode 100644 content/docs/core-concepts/meta.json create mode 100644 content/docs/core-concepts/modality-and-operation.mdx create mode 100644 content/docs/domains/audio.mdx create mode 100644 content/docs/domains/images.mdx create mode 100644 content/docs/domains/index.mdx create mode 100644 content/docs/domains/meta.json create mode 100644 content/docs/domains/text.mdx create mode 100644 content/docs/domains/video.mdx create mode 100644 content/docs/meta.json create mode 100644 content/docs/modalities/audio.mdx create mode 100644 content/docs/modalities/embeddings.mdx create mode 100644 content/docs/modalities/images.mdx create mode 100644 content/docs/modalities/index.mdx create mode 100644 content/docs/modalities/meta.json create mode 100644 content/docs/modalities/text.mdx create mode 100644 content/docs/modalities/video.mdx diff --git a/content/docs/capabilities/image-generation.mdx b/content/docs/capabilities/image-generation.mdx deleted file mode 100644 index 382ae7a..0000000 --- a/content/docs/capabilities/image-generation.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Image Generation -description: Generate images from text descriptions. ---- - -# Image Generation - -Generate images from text prompts using diffusion models and other generative AI. - -## Usage - -```python -from celeste import create_client, Capability, Provider - -client = create_client(Capability.IMAGE_GENERATION, Provider.OPENAI) - -response = await client.generate( - prompt="A cyberpunk city at night, neon lights, rain", - aspect_ratio="16:9", - quality="hd" -) - -# Save the image -with open("city.png", "wb") as f: - f.write(response.content.blob) -``` - -## Parameters - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `prompt` | `str` | The text description of the image. | -| `aspect_ratio` | `str` | Aspect ratio (e.g., "1:1", "16:9"). | -| `quality` | `str` | Quality setting (e.g., "standard", "hd"). | -| `watermark` | `bool` | Whether to add a watermark. | -| `partial_images` | `int` | Number of images to generate (batch size). | - -## Output - -The `generate` method returns an `ImageGenerationOutput` object. - -```python -class ImageGenerationOutput: - content: ImageArtifact - usage: ImageGenerationUsage - finish_reason: ImageGenerationFinishReason | None -``` - -### ImageArtifact - -The `content` is an `ImageArtifact` which abstracts the image data. - -- **`blob`**: Raw bytes of the image. -- **`url`**: URL of the image (if hosted by provider). -- **`mime_type`**: MIME type (e.g., "image/png"). -- **`save(path)`**: Helper method to save to disk. - diff --git a/content/docs/capabilities/speech-generation.mdx b/content/docs/capabilities/speech-generation.mdx deleted file mode 100644 index c94406e..0000000 --- a/content/docs/capabilities/speech-generation.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Speech Generation -description: Turn text into lifelike speech (TTS). ---- - -# Speech Generation - -Generate spoken audio from text (Text-to-Speech). - -## Usage - -```python -from celeste import create_client, Capability, Provider - -client = create_client(Capability.SPEECH_GENERATION, Provider.ELEVENLABS) - -response = await client.generate( - prompt="Welcome to the future of AI.", - voice="rachel", - speed=1.1 -) - -# Save audio -with open("speech.mp3", "wb") as f: - f.write(response.content.blob) -``` - -## Parameters - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `prompt` | `str` | The text to speak. | -| `voice` | `str` | Voice ID or name (provider specific). | -| `speed` | `float` | Speech speed multiplier (1.0 is normal). | -| `response_format` | `str` | Audio format (e.g., "mp3_44100_128"). | - -## Output - -The `generate` method returns a `SpeechGenerationOutput`. - -```python -class SpeechGenerationOutput: - content: AudioArtifact - usage: SpeechGenerationUsage -``` - -### AudioArtifact - -The `content` is an `AudioArtifact`. - -- **`blob`**: Raw audio bytes. -- **`mime_type`**: Audio MIME type (e.g., "audio/mpeg"). - -## Streaming - -Stream audio bytes for real-time playback. - -```python -stream = client.stream(prompt="This is being spoken as it generates.") - -async for chunk in stream: - # chunk.content is bytes - audio_player.write(chunk.content) -``` - diff --git a/content/docs/capabilities/text-generation.mdx b/content/docs/capabilities/text-generation.mdx deleted file mode 100644 index 9611738..0000000 --- a/content/docs/capabilities/text-generation.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: Text Generation -description: Generate text with LLMs. ---- - -# Text Generation - -Generate text from text prompts using Large Language Models (LLMs). - -## Usage - -```python -from celeste import create_client, Capability, Provider - -client = create_client(Capability.TEXT_GENERATION, Provider.ANTHROPIC) - -response = await client.generate( - prompt="Explain quantum computing", - temperature=0.7, - max_tokens=100 -) - -print(response.content) -``` - -## Parameters - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `prompt` | `str` | The input prompt (positional or keyword). | -| `temperature` | `float` | Controls randomness (0.0 to 2.0). | -| `max_tokens` | `int` | Maximum number of tokens to generate. | -| `thinking_budget` | `int` | Budget for reasoning tokens (e.g., O1, Claude 3.7). | -| `thinking_level` | `str` | Level of thinking (provider specific). | -| `verbosity` | `str` | Desired verbosity of the response. | -| `output_schema` | `Type[BaseModel]` | Pydantic model for structured output. | - -## Output - -The `generate` method returns a `TextGenerationOutput` object. - -```python -class TextGenerationOutput: - content: str - usage: TextGenerationUsage - finish_reason: TextGenerationFinishReason | None - metadata: dict[str, Any] -``` - -- **`content`**: The generated text string. -- **`usage`**: Token usage statistics (`input_tokens`, `output_tokens`, `total_tokens`). -- **`finish_reason`**: Why generation stopped (e.g., "stop", "length"). - -## Streaming - -Stream text chunks as they are generated. - -```python -stream = client.stream(prompt="Write a long story...") - -async for chunk in stream: - print(chunk.content, end="", flush=True) -``` - -- **`chunk.content`**: A string containing the next piece of text. - diff --git a/content/docs/capabilities/video-generation.mdx b/content/docs/capabilities/video-generation.mdx deleted file mode 100644 index 0c33fab..0000000 --- a/content/docs/capabilities/video-generation.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Video Generation -description: Generate videos from text prompts. ---- - -# Video Generation - -Generate short video clips from text descriptions. - -## Usage - -```python -from celeste import create_client, Capability, Provider - -client = create_client(Capability.VIDEO_GENERATION, Provider.LUMA) - -response = await client.generate( - prompt="A drone shot of a mountain peak", - duration=5, - aspect_ratio="16:9" -) - -# Save video -with open("video.mp4", "wb") as f: - f.write(response.content.blob) -``` - -## Parameters - -| Parameter | Type | Description | -| :--- | :--- | :--- | -| `prompt` | `str` | Text description of the video. | -| `aspect_ratio` | `str` | Aspect ratio (e.g., "16:9"). | -| `resolution` | `str` | Video resolution (e.g., "720p"). | -| `duration` | `int` | Duration in seconds. | -| `first_frame` | `ImageArtifact` | Image to start the video with (img2vid). | -| `last_frame` | `ImageArtifact` | Image to end the video with. | - -## Output - -The `generate` method returns a `VideoGenerationOutput`. - -```python -class VideoGenerationOutput: - content: VideoArtifact - usage: VideoGenerationUsage -``` - -### VideoArtifact - -The `content` is a `VideoArtifact`. - -- **`blob`**: Raw video bytes. -- **`url`**: URL of the video (if hosted). -- **`mime_type`**: Video MIME type (e.g., "video/mp4"). - diff --git a/content/docs/core-concepts/capabilities.mdx b/content/docs/core-concepts/capabilities.mdx deleted file mode 100644 index d6cb73c..0000000 --- a/content/docs/core-concepts/capabilities.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Capabilities -description: Supported AI capabilities in Celeste. ---- - -# Capabilities - -Celeste organizes AI features into "Capabilities". A capability defines a standard interface (Input, Output, Parameters) that providers implement. - -## Available Capabilities - -Import `Capability` from `celeste`. - -```python -from celeste import Capability -``` - -### Text - -- **`Capability.TEXT_GENERATION`**: Generate text from text prompts (LLMs). -- **`Capability.EMBEDDINGS`**: Convert text into vector embeddings. - -### Image - -- **`Capability.IMAGE_GENERATION`**: Generate images from text prompts. -- **`Capability.IMAGE_INTELLIGENCE`**: Analyze images (Vision). - -### Video - -- **`Capability.VIDEO_GENERATION`**: Generate videos from text or images. -- **`Capability.VIDEO_INTELLIGENCE`**: Analyze videos. - -### Audio & Speech - -- **`Capability.SPEECH_GENERATION`**: Generate speech from text (TTS). -- **`Capability.AUDIO_INTELLIGENCE`**: Analyze audio (Speech-to-Text). - -### Tools - -- **`Capability.SEARCH`**: Web search and retrieval. - -## Checking Support - -You can check if a model supports a capability: - -```python -if Capability.TEXT_GENERATION in model.capabilities: - print("Model supports text generation") -``` - diff --git a/content/docs/core-concepts/meta.json b/content/docs/core-concepts/meta.json new file mode 100644 index 0000000..1db1686 --- /dev/null +++ b/content/docs/core-concepts/meta.json @@ -0,0 +1,5 @@ +{ + "title": "Core concepts", + "pages": ["modality-and-operation", "client", "providers"] +} + diff --git a/content/docs/core-concepts/modality-and-operation.mdx b/content/docs/core-concepts/modality-and-operation.mdx new file mode 100644 index 0000000..9ceda47 --- /dev/null +++ b/content/docs/core-concepts/modality-and-operation.mdx @@ -0,0 +1,158 @@ +--- +title: Modality & operations +description: The core mental model of Celeste v1. +--- + +# Architecture & Concepts + +Celeste v1 is built around a simple mental model: **Domain (what you work with) + Operation → Modality (output)**. + +
+
+
+
Domain
+
What you work with
+
+ Images, Audio, Video, Text +
+
+ Namespace API +
+
+
+
Modality
+
What comes out
+
+ Output type and client +
+
+ create_client(modality=...) +
+
+
+
+
Operation
+
How input becomes output
+
+
+ Generate + Prompt → domain output + output = modality +
+
+ Edit + Domain → same domain + images client +
+
+ Analyze + Media → text + text client +
+
+ Embed + Any domain → vector + embeddings client +
+
+
+
+ +
+
+ Namespaces use domains + celeste.images.analyze(...) +
+
+ Clients use modalities + create_client(modality=\"text\") +
+
+ +
+
Image generation → domain: images, output modality: images
+
Image analysis → domain: images, output modality: text
+
+ +## The Core Trinity + +### 1. Modality (The output) +**What comes out.** +Modality defines the output type you receive: text, images, audio, video, or embeddings. + +### 2. Domain (What you work with) +**The resource you operate on.** +Domain is not input vs output; it is the thing you are working with. That resource can be input or output depending on the operation. + +- Image generation: domain = images, output modality = images. +- Image analysis: domain = images, output modality = text. + +### 3. Operation (The transformation) +**The method you call.** +Operations describe how the domain is transformed into the output modality. + +## Operation Matrix (Namespace-first) + +This matrix explains where to find every operation in Celeste. + +| What you work with (Domain) | Operation | Output (Modality) | Namespace call | +| :--- | :--- | :--- | :--- | +| Text | `generate` | Text | `await celeste.text.generate(...)` | +| Text | `embed` | Embeddings | `await celeste.text.embed(...)` | +| Images | `generate` | Images | `await celeste.images.generate(...)` | +| Images | `edit` | Images | `await celeste.images.edit(...)` | +| Images | `analyze` | Text | `await celeste.images.analyze(...)` | +| Audio | `speak` | Audio | `await celeste.audio.speak(...)` | +| Audio | `analyze` | Text | `await celeste.audio.analyze(...)` | +| Videos | `generate` | Videos | `await celeste.videos.generate(...)` | +| Videos | `analyze` | Text | `await celeste.videos.analyze(...)` | + +### Operations by Domain + +| Action | text | images | videos | audio | +|--------|------|--------|--------|-------| +| `generate` | ✓ | ✓ | ✓ | ○ | +| `edit` | · | ✓ | · | · | +| `analyze` | · | ✓ | ✓ | ✓ | +| `upscale` | · | ○ | ○ | · | +| `speak` | · | · | · | ✓ | +| `transcribe` | · | · | · | ○ | +| `embed` | ✓ | ○ | ○ | · | + +**Legend:** ✓ = Available · ○ = Planned · · = Not applicable + +**Note:** This table is by **domain (what you work with)**. **Embeddings** is a **modality** (vector output) produced by the `embed` operation, so it is not listed as a domain. + +## Examples + +### Image Generation (Image domain → Image output) + +```python +import celeste + +response = await celeste.images.generate( + model="gpt-image-1", + prompt="A red apple", +) +image = response.content +``` + +### Image Analysis (Image domain → Text output) + +```python +import celeste +from celeste.artifacts import ImageArtifact + +image = ImageArtifact(path="apple.png") + +response = await celeste.images.analyze( + model="gpt-4o", + prompt="Describe this image", + image=image, +) +text = response.content +``` + +## Why this design? + +Celeste keeps outputs predictable: a text response always returns `TextOutput`, an image response always returns `ImageOutput`, and so on. The namespace-first API mirrors how people think (“I have an image; I want to analyze it”) while the modality system keeps output types consistent and type-safe. diff --git a/content/docs/domains/audio.mdx b/content/docs/domains/audio.mdx new file mode 100644 index 0000000..7cd34c6 --- /dev/null +++ b/content/docs/domains/audio.mdx @@ -0,0 +1,38 @@ +--- +title: Audio +description: Operations on the audio domain. +--- + +# Audio Domain + +The **audio domain** covers text-to-speech and audio analysis. Analysis returns **text output** because the modality is text. + +## Operations + +| Operation | Output Modality | Namespace call | +| :--- | :--- | :--- | +| `speak` | Audio | `await celeste.audio.speak(...)` | +| `analyze` | Text | `await celeste.audio.analyze(...)` | + +## Examples + +```python +import celeste +from celeste.artifacts import AudioArtifact + +# Speak → audio output +audio = await celeste.audio.speak( + model="eleven_multilingual_v2", + text="Hello from Celeste", + voice="Rachel", +) + +# Analyze → text output +recording = AudioArtifact(path="recording.mp3") +summary = await celeste.audio.analyze( + model="gpt-4o", + prompt="Summarize this audio", + audio=recording, +) +print(summary.content) +``` diff --git a/content/docs/domains/images.mdx b/content/docs/domains/images.mdx new file mode 100644 index 0000000..ec72b21 --- /dev/null +++ b/content/docs/domains/images.mdx @@ -0,0 +1,38 @@ +--- +title: Images +description: Operations on the images domain. +--- + +# Images Domain + +The **images domain** covers image generation, editing, and analysis. Analysis returns **text output** because the modality is text. + +## Operations + +| Operation | Output Modality | Namespace call | +| :--- | :--- | :--- | +| `generate` | Images | `await celeste.images.generate(...)` | +| `edit` | Images | `await celeste.images.edit(...)` | +| `analyze` | Text | `await celeste.images.analyze(...)` | + +## Examples + +```python +import celeste +from celeste.artifacts import ImageArtifact + +# Generate → images output +image = await celeste.images.generate( + model="gpt-image-1", + prompt="A futuristic city at sunset", +) + +# Analyze → text output +photo = ImageArtifact(path="photo.png") +description = await celeste.images.analyze( + model="gpt-4o", + prompt="Describe the scene", + image=photo, +) +print(description.content) +``` diff --git a/content/docs/domains/index.mdx b/content/docs/domains/index.mdx new file mode 100644 index 0000000..4a1270e --- /dev/null +++ b/content/docs/domains/index.mdx @@ -0,0 +1,41 @@ +--- +title: Domains +description: Domain-first namespaces for day-to-day usage. +--- + +# Domains + +Domains are **what you work with**. The namespace API is domain-first, so you start from the resource and pick an operation. + +**Rule of thumb** +- **Namespaces use domains**: `celeste.images.analyze(...)` +- **Clients use modalities**: `create_client(modality="text")` + +## Available Domains + +- **Text**: prompts, documents, structured outputs. +- **Images**: image generation, editing, and image analysis. +- **Audio**: text-to-speech and audio analysis. +- **Video**: video generation and video analysis. + +## Domain vs Modality + +Modality is the **output type** (and the client you create). Domain is the **resource you work with**. The same domain can map to different output modalities depending on the operation. + +Example: +- `celeste.images.generate(...)` → **images** output +- `celeste.images.analyze(...)` → **text** output + +## Quick Example + +```python +import celeste + +# Domain: images → output: text +response = await celeste.images.analyze( + model="gpt-4o", + prompt="Describe this image", + image=img, +) +print(response.content) +``` diff --git a/content/docs/domains/meta.json b/content/docs/domains/meta.json new file mode 100644 index 0000000..ff5821b --- /dev/null +++ b/content/docs/domains/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Domains", + "pages": ["index", "text", "images", "audio", "video"] +} diff --git a/content/docs/domains/text.mdx b/content/docs/domains/text.mdx new file mode 100644 index 0000000..2917179 --- /dev/null +++ b/content/docs/domains/text.mdx @@ -0,0 +1,35 @@ +--- +title: Text +description: Operations on the text domain. +--- + +# Text Domain + +The **text domain** is for prompts, documents, and structured outputs. It supports **text generation** and **embeddings**. + +## Operations + +| Operation | Output Modality | Namespace call | +| :--- | :--- | :--- | +| `generate` | Text | `await celeste.text.generate(...)` | +| `embed` | Embeddings | `await celeste.text.embed(...)` | + +## Examples + +```python +import celeste + +# Text generation → text output +story = await celeste.text.generate( + model="gpt-4o", + prompt="Write a short story about a lighthouse.", +) +print(story.content) + +# Embeddings → embeddings output +embeddings = await celeste.text.embed( + model="text-embedding-3-large", + text="The quick brown fox jumps over the lazy dog", +) +print(len(embeddings.content)) +``` diff --git a/content/docs/domains/video.mdx b/content/docs/domains/video.mdx new file mode 100644 index 0000000..105ca0e --- /dev/null +++ b/content/docs/domains/video.mdx @@ -0,0 +1,37 @@ +--- +title: Video +description: Operations on the video domain. +--- + +# Video Domain + +The **video domain** covers video generation and analysis. Analysis returns **text output** because the modality is text. + +## Operations + +| Operation | Output Modality | Namespace call | +| :--- | :--- | :--- | +| `generate` | Videos | `await celeste.videos.generate(...)` | +| `analyze` | Text | `await celeste.videos.analyze(...)` | + +## Examples + +```python +import celeste +from celeste.artifacts import VideoArtifact + +# Generate → video output +video = await celeste.videos.generate( + model="veo-3.0-generate-001", + prompt="Waves crashing on a rocky shore", +) + +# Analyze → text output +clip = VideoArtifact(path="clip.mp4") +description = await celeste.videos.analyze( + model="gpt-4o", + prompt="Describe what happens in this video", + video=clip, +) +print(description.content) +``` diff --git a/content/docs/meta.json b/content/docs/meta.json new file mode 100644 index 0000000..5a8e91d --- /dev/null +++ b/content/docs/meta.json @@ -0,0 +1,3 @@ +{ + "pages": ["index", "getting-started", "core-concepts", "domains", "modalities", "providers", "guides", "contributing"] +} \ No newline at end of file diff --git a/content/docs/modalities/audio.mdx b/content/docs/modalities/audio.mdx new file mode 100644 index 0000000..981eb86 --- /dev/null +++ b/content/docs/modalities/audio.mdx @@ -0,0 +1,68 @@ +--- +title: Audio +description: Speech synthesis (TTS) and transcription. +--- + +# Audio Modality + +The **Audio** modality is the **output type** for speech synthesis and audio generation. When you work with audio and want **text output** (analysis), use `celeste.audio.analyze(...)` and the response will be text. + +## Operations + +| Operation | Description | +| :--- | :--- | +| **`speak`** | Convert text to speech (TTS). | +| **`transcribe`** | Convert audio to text (STT). (Planned) | +| **`generate`** | Generate audio/music from a text prompt. (Planned) | + +## Quick Start + +```python +import celeste + +# Speak (TTS) +audio = await celeste.audio.speak( + model="eleven_v3", + text="Hello, this is a generated voice.", + voice="rachel", +) + +# Save to file +with open("output.mp3", "wb") as f: + f.write(audio.content.get_bytes()) +``` + +## Streaming Audio + +```python +stream = celeste.audio.stream.speak( + model="eleven_v3", + text="Reading a long book...", +) + +async for chunk in stream: + # chunk.content is bytes + player.write(chunk.content) +``` + +## Audio Analysis (Text Output) + +```python +from celeste.artifacts import AudioArtifact + +audio = AudioArtifact(path="recording.mp3") + +response = await celeste.audio.analyze( + model="gpt-4o", + audio=audio, + prompt="Summarize what is being said", +) +print(response.content) +``` + +## Providers + +Supported providers for Audio: +- ElevenLabs +- OpenAI (TTS) +- Google (Cloud TTS) diff --git a/content/docs/modalities/embeddings.mdx b/content/docs/modalities/embeddings.mdx new file mode 100644 index 0000000..f851164 --- /dev/null +++ b/content/docs/modalities/embeddings.mdx @@ -0,0 +1,67 @@ +--- +title: Embeddings +description: Generate vector embeddings from text. +--- + +# Embeddings Modality + +The **Embeddings** modality is the **output type** for vector representations. You typically work with the **text domain** and call `celeste.text.embed(...)` to get embeddings. + +## Operations + +| Operation | Description | +| :--- | :--- | +| **`embed`** | Convert text into a vector embedding. | + +## Quick Start + +```python +import celeste + +# Generate embedding (domain: text → modality: embeddings) +response = await celeste.text.embed( + model="text-embedding-3-large", + text="The quick brown fox jumps over the lazy dog", +) + +# Access the vector +vector = response.content +print(f"Vector length: {len(vector)}") +``` + +## Batch Processing + +You can embed multiple texts in a single request for efficiency. + +```python +response = await celeste.text.embed( + model="text-embedding-3-large", + text=[ + "First document", + "Second document", + "Third document" + ] +) + +for vector in response.content: + print(vector[:5]) # Print first 5 dimensions +``` + +## Sync Usage + +For scripts or notebooks where async is not needed: + +```python +response = celeste.text.sync.embed( + model="text-embedding-3-large", + text="Hello world", +) +print(response.content) +``` + +## Providers + +Supported providers for Embeddings: +- OpenAI (`text-embedding-3-small`, `text-embedding-3-large`, etc.) +- Google (Gecko) +- Cohere (`embed-english-v3.0`, etc.) diff --git a/content/docs/modalities/images.mdx b/content/docs/modalities/images.mdx new file mode 100644 index 0000000..422674c --- /dev/null +++ b/content/docs/modalities/images.mdx @@ -0,0 +1,69 @@ +--- +title: Images +description: Image generation and editing. +--- + +# Images Modality + +The **Images** modality is the **output type** for image generation and editing. When you work with images and want **text output** (analysis), you still use the **images domain** via `celeste.images.analyze(...)`, but the output modality is text. + +## Operations + +| Operation | Description | +| :--- | :--- | +| **`generate`** | Create an image from a text prompt. | +| **`edit`** | Modify an existing image using a prompt and mask. | +| **`upscale`** | Increase the resolution of an image. (Planned) | + +## Quick Start + +```python +import celeste + +# Generate (domain: images) +response = await celeste.images.generate( + model="gpt-image-1", + prompt="A cyberpunk city at night", + aspect_ratio="1:1" +) +with open("cyberpunk.png", "wb") as f: + f.write(response.content.get_bytes()) +``` + +## Editing + +```python +from celeste.artifacts import ImageArtifact + +base_image = ImageArtifact(path="photo.png") + +response = await celeste.images.edit( + model="gpt-image-1", + image=base_image, + prompt="Add a red hat", + mask=... # optional mask +) +``` + +## Image Analysis (Text Output) + +```python +from celeste.artifacts import ImageArtifact + +image = ImageArtifact(path="photo.png") + +response = await celeste.images.analyze( + model="gpt-4o", + image=image, + prompt="Describe the scene", +) +print(response.content) +``` + +## Providers + +Supported providers for Images: +- OpenAI (DALL·E 3) +- Google (Imagen 3) +- BFL (Flux) +- BytePlus diff --git a/content/docs/modalities/index.mdx b/content/docs/modalities/index.mdx new file mode 100644 index 0000000..7eab0a2 --- /dev/null +++ b/content/docs/modalities/index.mdx @@ -0,0 +1,26 @@ +--- +title: Modalities +description: Modality-first clients and operation-based methods in Celeste v1. +--- + +# Modalities + +Modalities are **output types** (text, images, audio, video, embeddings). The public API is **namespace-first**, so you usually start from the domain you work with and let Celeste route to the correct modality. + +For day-to-day usage, see the [Domains](/docs/domains) section. + +```python +import celeste + +# Domain: images → output: text +result = await celeste.images.analyze( + model="gpt-4o", + prompt="Describe this image", + image=img, +) +``` + +Next: +- Text (output): `celeste.text.generate(...)`, `celeste.text.embed(...)` +- Images (output): `celeste.images.generate(...)`, `celeste.images.edit(...)` + diff --git a/content/docs/modalities/meta.json b/content/docs/modalities/meta.json new file mode 100644 index 0000000..66adf6e --- /dev/null +++ b/content/docs/modalities/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Modalities", + "pages": ["index", "text", "images", "audio", "video", "embeddings"] +} \ No newline at end of file diff --git a/content/docs/modalities/text.mdx b/content/docs/modalities/text.mdx new file mode 100644 index 0000000..44e6b4b --- /dev/null +++ b/content/docs/modalities/text.mdx @@ -0,0 +1,94 @@ +--- +title: Text +description: Text generation and analysis (LLMs). +--- + +# Text Modality + +The **Text** modality is the **output type** for text. Use `celeste.text.generate(...)` when you work with text, and use domain namespaces like `celeste.images.analyze(...)` or `celeste.audio.analyze(...)` when you work with media but want text output. + +## Operations + +| Operation | Description | +| :--- | :--- | +| **`generate`** | Generate text from a text prompt. | +| **`analyze`** | Analyze images, video, or audio to generate a text description. | + +## Quick Start + +```python +import celeste + +# Generate (domain: text) +response = await celeste.text.generate( + model="claude-sonnet-4-5", + prompt="Write a haiku about rust.", +) +print(response.content) + +# Streaming +async for chunk in celeste.text.stream.generate( + model="claude-sonnet-4-5", + prompt="Explain quantum mechanics", +): + print(chunk.content, end="") +``` + +## Analyze (Multi-Modal) + +The `analyze` operation on a **Text** client can process images, videos, or audio to generate text descriptions. + +### Image Analysis + +```python +from celeste.artifacts import ImageArtifact + +image = ImageArtifact(path="screenshot.png") + +response = await celeste.images.analyze( + model="gpt-4o", + prompt="What is in this image?", + image=image +) +print(response.content) +``` + +### Video Analysis + +```python +from celeste.artifacts import VideoArtifact + +video = VideoArtifact(path="clip.mp4") + +response = await celeste.videos.analyze( + model="gpt-4o", + prompt="Describe what happens in this video", + video=video +) +print(response.content) +``` + +### Audio Analysis + +```python +from celeste.artifacts import AudioArtifact + +audio = AudioArtifact(path="recording.mp3") + +response = await celeste.audio.analyze( + model="gpt-4o", + prompt="What is being said in this audio?", + audio=audio +) +print(response.content) +``` + +## Providers + +Supported providers for Text: +- OpenAI (GPT-4o, etc.) +- Anthropic (Claude) +- Google (Gemini) +- Mistral +- Cohere +- Meta (Llama via providers) diff --git a/content/docs/modalities/video.mdx b/content/docs/modalities/video.mdx new file mode 100644 index 0000000..d671b4b --- /dev/null +++ b/content/docs/modalities/video.mdx @@ -0,0 +1,52 @@ +--- +title: Video +description: Video generation and analysis. +--- + +# Video Modality + +The **Video** modality is the **output type** for video generation. For video **analysis**, use the **video domain** (`celeste.videos.analyze(...)`) and you will receive **text output**. + +## Operations + +| Operation | Description | +| :--- | :--- | +| **`generate`** | Create a video from a text or image prompt. | + +## Quick Start + +```python +import celeste + +# Generate +video = await celeste.videos.generate( + model="ray-2", + prompt="A drone shot of a beautiful coastline at sunset", + duration=8, +) + +with open("coast.mp4", "wb") as f: + f.write(video.content.get_bytes()) +``` + +## Video Analysis (Text Output) + +```python +from celeste.artifacts import VideoArtifact + +video = VideoArtifact(path="clip.mp4") + +response = await celeste.videos.analyze( + model="gpt-4o", + video=video, + prompt="Describe what happens in this video", +) +print(response.content) +``` + +## Providers + +Supported providers for Video: +- Luma (Ray) +- BytePlus (PixelDance) +- Google (Veo) From 426f84336108fd343d4e926d4660e83097c9a769 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:27:57 +0100 Subject: [PATCH 03/13] docs: update core concepts to reflect new API pattern --- content/docs/core-concepts/client.mdx | 87 +++++++++++++++--------- content/docs/core-concepts/providers.mdx | 49 ++++++------- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/content/docs/core-concepts/client.mdx b/content/docs/core-concepts/client.mdx index f43a802..a9b95dd 100644 --- a/content/docs/core-concepts/client.mdx +++ b/content/docs/core-concepts/client.mdx @@ -1,66 +1,85 @@ --- -title: The Client -description: The unified interface for all AI capabilities. +title: The client +description: Create modality clients and call operation methods. --- -# The Client +# The client -The `Client` is the core primitive in Celeste. It provides a consistent interface for interacting with different AI models and capabilities. +Celeste v1 is **namespace-first**, but this page focuses on the **client** pattern. The client API is **modality-first**, meaning you choose the output type you want. -## Creating a Client +## Create a client (advanced) -Use the `create_client` function to instantiate a client. +Use `create_client` when you want explicit control or reuse a configured client. This is **modality-first**, so you specify the output type and (optionally) the operation. ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client( - capability=Capability.TEXT_GENERATION, - provider=Provider.ANTHROPIC, +client = celeste.create_client( + modality="text", + provider="openai", + model="gpt-4o", ) ``` ### Arguments -- **`capability`** (`Capability`): The capability to use (e.g., `TEXT_GENERATION`, `IMAGE_GENERATION`). -- **`provider`** (`Provider`, optional): The provider to use. Required if `model` is a string ID. -- **`model`** (`Model | str`, optional): Specific model to use. If omitted, a default model for the provider/capability is selected. -- **`api_key`** (`SecretStr`, optional): API key override. If omitted, loaded from environment variables. +- **`modality`** (`str | Modality`): The modality to use (e.g., `"text"`, `"images"`). +- **`operation`** (`str | Operation`, optional): Optional operation filter. +- **`provider`** (`str | Provider`, optional): The provider to use (e.g., `"openai"`, `"anthropic"`). +- **`model`** (`str | Model`, optional): Specific model to use. +- **`api_key`** (`str`, optional): API key override. +- **`auth`** (`Authentication`, optional): Custom authentication override (advanced). -## The Client Interface +## Execution modes -All clients share a common interface with two main methods: `generate` and `stream`. +Celeste supports three execution modes to handle different use cases: -### `generate` +| Mode | Pattern | Return Type | Use Case | +|------|---------|-------------|----------| +| **Async** | `await client.generate()` | `Output` | Production, async apps | +| **Streaming** | `client.stream.generate()` | `AsyncIterator[Chunk]` | Chat UIs, real-time feedback | +| **Sync** | `client.sync.generate()` | `Output` | Scripts, notebooks, testing | -The `generate` method creates a complete response. +### Async (default) + +Async operation methods return a complete typed output object. Best for production applications. ```python -response = await client.generate( - prompt="Hello world", - temperature=0.7 -) +response = await client.generate(prompt="Hello world", temperature=0.7) +print(response.content) ``` -- **Arguments**: Positional arguments (like `prompt`) and keyword arguments (parameters like `temperature`) vary by capability. -- **Returns**: A strongly-typed output object (e.g., `TextGenerationOutput`). +### Streaming (`client.stream.()`) -### `stream` - -The `stream` method yields chunks of the response as they are generated. +Streaming returns chunks as they are generated. Best for UIs requiring real-time feedback. ```python -stream = client.stream( - prompt="Hello world", - temperature=0.7 -) +stream = client.stream.generate(prompt="Count from 1 to 5") async for chunk in stream: print(chunk.content, end="") + +final_response = stream.output +print(final_response.content) +``` + +### Sync (`client.sync.()`) + +Sync methods are blocking calls. Best for scripts, notebooks, and testing. + +```python +response = client.sync.generate(prompt="Hello world") +print(response.content) ``` -- **Arguments**: Same as `generate`. -- **Returns**: An async iterator yielding typed chunks. +Sync streaming is also supported: + +```python +stream = client.sync.stream.generate(prompt="Hello world") +for chunk in stream: + print(chunk.content, end="") +print(stream.output.content) +``` ## Type Safety @@ -70,7 +89,7 @@ Clients are generic over their Input, Output, and Parameters. This means your ID - **Response**: `response.content`, `response.usage`, etc. ```python -# IDE knows this is TextGenerationOutput +# IDE knows this is a TextOutput (for text modality) response = await client.generate(prompt="...") # IDE knows this is int diff --git a/content/docs/core-concepts/providers.mdx b/content/docs/core-concepts/providers.mdx index 9b15096..d2831f3 100644 --- a/content/docs/core-concepts/providers.mdx +++ b/content/docs/core-concepts/providers.mdx @@ -5,7 +5,7 @@ description: Supported AI providers in Celeste. # Providers -Celeste supports a wide range of AI providers through a unified interface. +Celeste supports multiple AI providers through a unified interface. ## Available Providers @@ -15,20 +15,19 @@ Import `Provider` from `celeste`. from celeste import Provider ``` -- **`Provider.OPENAI`**: GPT-4, DALL-E, TTS. -- **`Provider.ANTHROPIC`**: Claude 3.5 Sonnet, Haiku, Opus. +- **`Provider.OPENAI`**: GPT-4o, GPT-Image, DALL·E. +- **`Provider.ANTHROPIC`**: Claude. - **`Provider.GOOGLE`**: Gemini, Imagen. -- **`Provider.MISTRAL`**: Mistral Large, Small. -- **`Provider.COHERE`**: Command R, R+. +- **`Provider.MISTRAL`**: Mistral. +- **`Provider.COHERE`**: Command. +- **`Provider.DEEPSEEK`**: DeepSeek. +- **`Provider.GROQ`**: Groq. +- **`Provider.MOONSHOT`**: Moonshot. - **`Provider.XAI`**: Grok. -- **`Provider.HUGGINGFACE`**: Open source models. -- **`Provider.REPLICATE`**: Flux, Stable Diffusion. -- **`Provider.STABILITYAI`**: Stable Diffusion 3. -- **`Provider.LUMA`**: Ray. -- **`Provider.TOPAZLABS`**: Image upscaling. -- **`Provider.PERPLEXITY`**: Online models. -- **`Provider.BYTEDANCE`**: Doubao (PixelDance). -- **`Provider.ELEVENLABS`**: Speech synthesis. +- **`Provider.BYTEPLUS`**: BytePlus. +- **`Provider.BFL`**: BFL. +- **`Provider.ELEVENLABS`**: ElevenLabs. +- **`Provider.GRADIUM`**: Gradium. ## Credentials @@ -40,25 +39,27 @@ Celeste automatically loads API keys from environment variables. | Anthropic | `ANTHROPIC_API_KEY` | | Google | `GOOGLE_API_KEY` | | Mistral | `MISTRAL_API_KEY` | -| Hugging Face | `HUGGINGFACE_TOKEN` | -| Stability AI | `STABILITYAI_API_KEY` | -| Replicate | `REPLICATE_API_TOKEN` | | Cohere | `COHERE_API_KEY` | +| DeepSeek | `DEEPSEEK_API_KEY` | +| Groq | `GROQ_API_KEY` | +| Moonshot | `MOONSHOT_API_KEY` | | xAI | `XAI_API_KEY` | -| Luma | `LUMA_API_KEY` | -| Topaz Labs | `TOPAZLABS_API_KEY` | -| Perplexity | `PERPLEXITY_API_KEY` | -| ByteDance | `BYTEDANCE_API_KEY` | +| BytePlus | `BYTEPLUS_API_KEY` | +| BFL | `BFL_API_KEY` | | ElevenLabs | `ELEVENLABS_API_KEY` | +| Gradium | `GRADIUM_API_KEY` | You can also pass keys explicitly when creating a client: ```python -from pydantic import SecretStr +from celeste import Provider +import celeste -client = create_client( - ..., - api_key=SecretStr("sk-...") +response = await celeste.text.generate( + model="gpt-4o", + provider=Provider.OPENAI, + api_key="sk-...", + prompt="Hello from OpenAI", ) ``` From 54bffc7bcd33c7868014fa6afb4c0ad5a5cebd6e Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:28:08 +0100 Subject: [PATCH 04/13] docs: update getting started and guides for new API --- content/docs/getting-started/meta.json | 5 + content/docs/getting-started/quickstart.mdx | 82 ++++++++++----- content/docs/guides/authentication.mdx | 111 ++++++++++++++++++++ content/docs/guides/error-handling.mdx | 13 +-- content/docs/guides/meta.json | 5 + content/docs/guides/multi-modal.mdx | 57 +++++----- content/docs/guides/streaming.mdx | 19 ++-- 7 files changed, 224 insertions(+), 68 deletions(-) create mode 100644 content/docs/getting-started/meta.json create mode 100644 content/docs/guides/authentication.mdx create mode 100644 content/docs/guides/meta.json diff --git a/content/docs/getting-started/meta.json b/content/docs/getting-started/meta.json new file mode 100644 index 0000000..ec9b750 --- /dev/null +++ b/content/docs/getting-started/meta.json @@ -0,0 +1,5 @@ +{ + "title": "Getting started", + "pages": ["installation", "quickstart"] +} + diff --git a/content/docs/getting-started/quickstart.mdx b/content/docs/getting-started/quickstart.mdx index 8478ebd..cf341d9 100644 --- a/content/docs/getting-started/quickstart.mdx +++ b/content/docs/getting-started/quickstart.mdx @@ -13,10 +13,10 @@ This guide will help you make your first generation request with Celeste. ## Install -Install Celeste with the text generation capability: +Install Celeste: ```bash -uv add "celeste-ai[text-generation]" +uv add celeste-ai ``` @@ -39,56 +39,82 @@ OPENAI_API_KEY=sk-... -## Create a Client +## Use a domain namespace (recommended) -Import `create_client` and define the capability and provider you want to use. +Import `celeste` and call the domain you work with. Domain is what you work with, not input or output. ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client( - capability=Capability.TEXT_GENERATION, - provider=Provider.ANTHROPIC, +# Domain: text +response = await celeste.text.generate( + model="claude-sonnet-4-5", + prompt="Explain quantum computing in one sentence.", ) +print(response.content) ``` ## Generate Content -Use the `generate` method to create content. +import { MethodSelector } from '@/components/MethodSelector'; + + + +
+Non-blocking I/O. Recommended for production apps and notebooks. ```python -import asyncio +response = await celeste.text.generate( + model="claude-sonnet-4-5", + prompt="Explain quantum computing in one sentence.", + temperature=0.7, +) +print(response.content) +``` +
-async def main(): - response = await client.generate( - prompt="Explain quantum computing in one sentence.", - temperature=0.7 - ) - print(response.content) +
+Blocking I/O. Suitable for scripts and simple tools. -if __name__ == "__main__": - asyncio.run(main()) +```python +response = celeste.text.sync.generate( + model="claude-sonnet-4-5", + prompt="Explain quantum computing in one sentence.", + temperature=0.7, +) +print(response.content) ``` +
+ +
## Multi-Modal Example -Celeste uses the same interface for all modalities. +Celeste uses the same interface for every domain and operation. ```python -# Text -text_client = create_client(Capability.TEXT_GENERATION, Provider.ANTHROPIC) -text = await text_client.generate(prompt="Write a haiku about AI") +import celeste -# Image -image_client = create_client(Capability.IMAGE_GENERATION, Provider.OPENAI) -image = await image_client.generate(prompt="A futuristic city at sunset") +# Text domain → text output +text = await celeste.text.generate( + model="claude-sonnet-4-5", + prompt="Write a haiku about AI", +) -# Video -video_client = create_client(Capability.VIDEO_GENERATION, Provider.GOOGLE) -video = await video_client.generate(prompt="Waves crashing on a beach") +# Images domain → image output +image = await celeste.images.generate( + model="gpt-image-1", + prompt="A futuristic city at sunset", +) + +# Videos domain → video output +video = await celeste.videos.generate( + model="veo-3", + prompt="Waves crashing on a beach", +) ``` diff --git a/content/docs/guides/authentication.mdx b/content/docs/guides/authentication.mdx new file mode 100644 index 0000000..e91c0d0 --- /dev/null +++ b/content/docs/guides/authentication.mdx @@ -0,0 +1,111 @@ +--- +title: Authentication +description: Configure API keys and OAuth for Celeste providers. +--- + +# Authentication + +Celeste supports two authentication methods: API keys for most providers, and OAuth for Google Cloud APIs. + +## API Keys (Most Providers) + +### Environment Variables + +Set your API key as an environment variable: + +```bash +export OPENAI_API_KEY="sk-..." +``` + +Or use a `.env` file: + +```bash title=".env" +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=sk-... +``` + +### Provider Reference + +| Provider | Environment Variable | +|----------|---------------------| +| OpenAI | `OPENAI_API_KEY` | +| Anthropic | `ANTHROPIC_API_KEY` | +| Google (Gemini) | `GOOGLE_API_KEY` | +| Mistral | `MISTRAL_API_KEY` | +| Cohere | `COHERE_API_KEY` | +| ElevenLabs | `ELEVENLABS_API_KEY` | +| Groq | `GROQ_API_KEY` | +| BFL | `BFL_API_KEY` | +| DeepSeek | `DEEPSEEK_API_KEY` | +| xAI | `XAI_API_KEY` | + +## Google Cloud (OAuth) + +Google Cloud APIs (like Cloud TTS with Gemini voices) require OAuth authentication instead of API keys. + +### Setup + +1. Install the [gcloud CLI](https://cloud.google.com/sdk/docs/install) + +2. Login with Application Default Credentials: + +```bash +gcloud auth application-default login +``` + +3. Set your project (for billing/quota): + +```bash +gcloud config set project YOUR_PROJECT_ID +``` + +### Usage + +```python +import celeste + +# No API key needed - uses OAuth automatically +response = await celeste.audio.speak( + model="gemini-2.5-flash-tts", + provider="google", + text="Hello from Google Cloud", +) +``` + +### Troubleshooting + +| Error | Solution | +|-------|----------| +| `RefreshError: Reauthentication is needed` | Run `gcloud auth application-default login` | +| Quota/project errors | Run `gcloud config set project YOUR_PROJECT_ID` | + +## Explicit Authentication + +Override environment variables by passing `api_key` directly: + +```python +import celeste + +response = await celeste.text.generate( + model="gpt-4o", + api_key="sk-...", + prompt="Hello", +) +``` + +### Advanced: custom auth headers + +For custom headers, use `create_client` with the `auth` parameter: + +```python +import celeste +from celeste import APIKey + +client = celeste.create_client( + modality="text", + auth=APIKey( + key="sk-...", + header="X-Custom-Header", + ), +) +``` \ No newline at end of file diff --git a/content/docs/guides/error-handling.mdx b/content/docs/guides/error-handling.mdx index 087d345..b06f041 100644 --- a/content/docs/guides/error-handling.mdx +++ b/content/docs/guides/error-handling.mdx @@ -12,10 +12,9 @@ Celeste provides a hierarchy of exceptions to help you handle errors gracefully. - **`Error`**: Base class for all Celeste errors. - **`ModelError`** - **`ModelNotFoundError`**: The requested model (or a default) could not be found. - - **`CapabilityError`** - - **`UnsupportedCapabilityError`**: The model doesn't support the requested capability. - **`ClientError`** - - **`ClientNotFoundError`**: No client implementation exists for the provider/capability. + - **`ClientNotFoundError`**: No client implementation exists for the provider/modality. + - **`ModalityNotFoundError`**: No client registered for the requested modality. - **`CredentialsError`** - **`MissingCredentialsError`**: API key is missing. - **`UnsupportedProviderError`**: Provider is not configured in the credential system. @@ -31,13 +30,15 @@ Celeste provides a hierarchy of exceptions to help you handle errors gracefully. ## Example ```python -from celeste import create_client, Capability, Provider +import celeste from celeste.exceptions import MissingCredentialsError, ModelNotFoundError import httpx try: - client = create_client(Capability.TEXT_GENERATION, Provider.OPENAI) - response = await client.generate(prompt="Hello") + response = await celeste.text.generate( + model="gpt-4o", + prompt="Hello" + ) except MissingCredentialsError: print("Please set your OPENAI_API_KEY.") diff --git a/content/docs/guides/meta.json b/content/docs/guides/meta.json new file mode 100644 index 0000000..826ca9a --- /dev/null +++ b/content/docs/guides/meta.json @@ -0,0 +1,5 @@ +{ + "title": "Guides", + "pages": ["streaming", "authentication", "multi-modal", "error-handling"] +} + diff --git a/content/docs/guides/multi-modal.mdx b/content/docs/guides/multi-modal.mdx index 0b1a6da..b548003 100644 --- a/content/docs/guides/multi-modal.mdx +++ b/content/docs/guides/multi-modal.mdx @@ -1,6 +1,6 @@ --- title: Multi-Modal Workflows -description: Combining capabilities for complex workflows. +description: Combining modalities for complex workflows. --- # Multi-Modal Workflows @@ -12,36 +12,45 @@ One of Celeste's strengths is the ability to combine different modalities using Generate an image based on a detailed description created by an LLM. ```python -from celeste import create_client, Capability, Provider +import celeste -# 1. Create clients -text_client = create_client(Capability.TEXT_GENERATION, Provider.ANTHROPIC) -image_client = create_client(Capability.IMAGE_GENERATION, Provider.OPENAI) - -# 2. Generate prompt -prompt_response = await text_client.generate( - prompt="Describe a surreal landscape with floating islands in 2 sentences." +# 1. Generate prompt (domain: text) +prompt_response = await celeste.text.generate( + model="claude-sonnet-4-5", + prompt="Describe a surreal landscape with floating islands in 2 sentences.", ) image_prompt = prompt_response.content print(f"Generating image for: {image_prompt}") -# 3. Generate image -image_response = await image_client.generate( +# 2. Generate image (domain: images) +image_response = await celeste.images.generate( + model="gpt-image-1", prompt=image_prompt, quality="hd" ) # 4. Save -image_response.content.save("surreal_islands.png") +with open("surreal_islands.png", "wb") as f: + f.write(image_response.content.get_bytes()) ``` ## Image to Text (Vision) -Analyze an image using a vision model. +Analyze an image using a vision model. This uses the **images domain**, but the **output modality is text**. ```python -# Note: Image Intelligence capability implementation details -# would mirror the structure of other capabilities. +from celeste.artifacts import ImageArtifact + +# Load image +image = ImageArtifact(path="surreal_islands.png") + +# Analyze (domain: images, output: text) +description = await celeste.images.analyze( + model="gpt-4o", + prompt="What colors are dominant in this image?", + image=image +) +print(description.content) ``` ## Text to Speech @@ -49,18 +58,18 @@ Analyze an image using a vision model. Read out generated text. ```python -text_client = create_client(Capability.TEXT_GENERATION, Provider.OPENAI) -speech_client = create_client(Capability.SPEECH_GENERATION, Provider.ELEVENLABS) - -# Generate story -story = await text_client.generate(prompt="Tell a very short story.") +story = await celeste.text.generate( + model="gpt-4o", + prompt="Tell a very short story.", +) -# Speak it -audio = await speech_client.generate( - prompt=story.content, +audio = await celeste.audio.speak( + model="eleven_v3", + text=story.content, voice="rachel" ) -audio.content.save("story.mp3") +with open("story.mp3", "wb") as f: + f.write(audio.content.get_bytes()) ``` diff --git a/content/docs/guides/streaming.mdx b/content/docs/guides/streaming.mdx index 1ca4c51..d5c38b0 100644 --- a/content/docs/guides/streaming.mdx +++ b/content/docs/guides/streaming.mdx @@ -9,30 +9,29 @@ Streaming allows you to receive chunks of a response as they are generated, rath ## Basic Usage -Use the `stream` method instead of `generate`. +Use the domain namespace with `.stream` to access streaming operations. ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.OPENAI) - -stream = client.stream( +stream = celeste.text.stream.generate( + model="gpt-4o", prompt="Count from 1 to 10", - max_tokens=50 + max_tokens=50, ) async for chunk in stream: - # chunk is strongly typed based on the capability + # chunk is strongly typed based on the modality print(chunk.content, end="", flush=True) ``` ## Handling Chunks -Different capabilities produce different types of chunks. +Different modalities produce different types of chunks. ### Text Generation -Yields `TextGenerationChunk`. `chunk.content` is a `str`. +Yields `TextChunk`. `chunk.content` is a `str`. ```python async for chunk in stream: @@ -41,7 +40,7 @@ async for chunk in stream: ### Speech Generation -Yields `SpeechGenerationChunk`. `chunk.content` is `bytes` (raw audio data). +Yields `AudioChunk`. `chunk.content` is `bytes` (raw audio data). ```python # Example: Writing to a file stream or audio player From 8383c2fe01b74279338b4ae5815bc13276998290 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:28:31 +0100 Subject: [PATCH 05/13] docs: migrate provider docs to new API pattern --- content/docs/providers/anthropic.mdx | 32 ++++++++-- content/docs/providers/bytedance.mdx | 15 ++--- content/docs/providers/cohere.mdx | 30 ++++++++-- content/docs/providers/elevenlabs.mdx | 30 ++++++++-- content/docs/providers/google.mdx | 81 ++++++++++++++++++++++--- content/docs/providers/mistral.mdx | 40 ++++++++++++- content/docs/providers/openai.mdx | 85 +++++++++++++++++++++++---- 7 files changed, 273 insertions(+), 40 deletions(-) diff --git a/content/docs/providers/anthropic.mdx b/content/docs/providers/anthropic.mdx index ac728cb..41ffa61 100644 --- a/content/docs/providers/anthropic.mdx +++ b/content/docs/providers/anthropic.mdx @@ -27,10 +27,12 @@ export ANTHROPIC_API_KEY="sk-ant-..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.ANTHROPIC, model="claude-3-5-sonnet-20240620") -response = await client.generate(prompt="Hello Claude") +response = await celeste.text.generate( + model="claude-3-5-sonnet-20240620", + prompt="Hello Claude", +) ``` ### Thinking @@ -38,9 +40,31 @@ response = await client.generate(prompt="Hello Claude") Anthropic models support extended thinking parameters. ```python -response = await client.generate( +response = await celeste.text.generate( + model="claude-3-5-sonnet-20240620", prompt="Solve this complex logic puzzle...", thinking_budget=4096 ) ``` +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `claude-haiku-4-5` | Claude Haiku 4.5 | `analyze`, `generate` | Yes | +| `claude-opus-4-20250514` | Claude Opus 4 | `analyze`, `generate` | Yes | +| `claude-opus-4-1` | Claude Opus 4.1 | `analyze`, `generate` | Yes | +| `claude-opus-4-5` | Claude Opus 4.5 | `analyze`, `generate` | Yes | +| `claude-sonnet-4-20250514` | Claude Sonnet 4 | `analyze`, `generate` | Yes | +| `claude-sonnet-4-5` | Claude Sonnet 4.5 | `analyze`, `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} diff --git a/content/docs/providers/bytedance.mdx b/content/docs/providers/bytedance.mdx index 369a769..2c8229d 100644 --- a/content/docs/providers/bytedance.mdx +++ b/content/docs/providers/bytedance.mdx @@ -5,14 +5,14 @@ description: Documentation for the ByteDance provider. ByteDance -Celeste supports ByteDance's models (e.g., via Volcano Engine) primarily for video generation. +Celeste supports ByteDance's models via the BytePlus provider for video generation. ## Credentials -Set the `BYTEDANCE_API_KEY` environment variable. +Set the `BYTEPLUS_API_KEY` environment variable. ```bash -export BYTEDANCE_API_KEY="..." +export BYTEPLUS_API_KEY="..." ``` ## Video Generation @@ -24,12 +24,13 @@ export BYTEDANCE_API_KEY="..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.VIDEO_GENERATION, Provider.BYTEDANCE) -response = await client.generate( +response = await celeste.videos.generate( + model="pixeldance", + provider="byteplus", prompt="A panda eating bamboo", - aspect_ratio="16:9" + aspect_ratio="16:9", ) ``` diff --git a/content/docs/providers/cohere.mdx b/content/docs/providers/cohere.mdx index 049f188..0ef2aa7 100644 --- a/content/docs/providers/cohere.mdx +++ b/content/docs/providers/cohere.mdx @@ -19,15 +19,35 @@ export COHERE_API_KEY="..." ### Models -- `command-r-plus` (Default) -- `command-r` +- `command-a-03-2025` (Default) +- `command-r7b-12-2024` ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.COHERE) -response = await client.generate(prompt="Hello Command R") +response = await celeste.text.generate( + model="command-a-03-2025", + prompt="Hello Command R", +) ``` +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `command-a-03-2025` | Command A 03-2025 | `generate` | Yes | +| `command-a-vision-07-2025` | Command A Vision 07-2025 | `analyze`, `generate` | Yes | +| `command-r7b-12-2024` | Command R7B | `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} diff --git a/content/docs/providers/elevenlabs.mdx b/content/docs/providers/elevenlabs.mdx index 8df4801..aeb26e2 100644 --- a/content/docs/providers/elevenlabs.mdx +++ b/content/docs/providers/elevenlabs.mdx @@ -25,12 +25,34 @@ export ELEVENLABS_API_KEY="..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.SPEECH_GENERATION, Provider.ELEVENLABS) -response = await client.generate( - prompt="This voice is AI generated.", +response = await celeste.audio.speak( + model="eleven_multilingual_v2", + provider="elevenlabs", + text="This voice is AI generated.", voice="Rachel" # Use voice ID or name ) ``` +## Models{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `audio`: `speak` + +### Audio + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `eleven_monolingual_v1` | Eleven English v1 | `speak` | Yes | +| `eleven_flash_v2` | Eleven Flash v2 | `speak` | Yes | +| `eleven_flash_v2_5` | Eleven Flash v2.5 | `speak` | Yes | +| `eleven_multilingual_v1` | Eleven Multilingual v1 | `speak` | Yes | +| `eleven_multilingual_v2` | Eleven Multilingual v2 | `speak` | No | +| `eleven_turbo_v2` | Eleven Turbo v2 | `speak` | Yes | +| `eleven_turbo_v2_5` | Eleven Turbo v2.5 | `speak` | Yes | +| `eleven_v3` | Eleven v3 (Alpha) | `speak` | No | +{/* AUTO-GENERATED:MODELS:END */} diff --git a/content/docs/providers/google.mdx b/content/docs/providers/google.mdx index cf36a65..3a93b49 100644 --- a/content/docs/providers/google.mdx +++ b/content/docs/providers/google.mdx @@ -25,10 +25,13 @@ export GOOGLE_API_KEY="AIza..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.GOOGLE) -response = await client.generate(prompt="Hello Gemini") +response = await celeste.text.generate( + model="gemini-1.5-pro", + provider="google", + prompt="Hello Gemini", +) ``` ## Image Generation @@ -40,8 +43,13 @@ response = await client.generate(prompt="Hello Gemini") ### Usage ```python -client = create_client(Capability.IMAGE_GENERATION, Provider.GOOGLE) -response = await client.generate(prompt="A futuristic landscape") +import celeste + +response = await celeste.images.generate( + model="imagen-3.0-generate-001", + provider="google", + prompt="A futuristic landscape", +) ``` ## Video Generation @@ -49,7 +57,66 @@ response = await client.generate(prompt="A futuristic landscape") Google also supports video generation via specific models. ```python -client = create_client(Capability.VIDEO_GENERATION, Provider.GOOGLE) -# Usage depends on model availability +import celeste + +video = await celeste.videos.generate( + model="veo-3.0-generate-001", + provider="google", + prompt="A sunrise over the mountains", +) ``` +## Models{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `audio`: `speak` +- `embeddings`: `embed` +- `images`: `edit`, `generate` +- `text`: `analyze`, `generate` +- `videos`: `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gemini-2.5-flash` | Gemini 2.5 Flash | `analyze`, `generate` | Yes | +| `gemini-2.5-flash-lite` | Gemini 2.5 Flash Lite | `analyze`, `generate` | Yes | +| `gemini-2.5-pro` | Gemini 2.5 Pro | `analyze`, `generate` | Yes | +| `gemini-3-flash-preview` | Gemini 3 Flash | `analyze`, `generate` | Yes | +| `gemini-3-pro-preview` | Gemini 3 Pro | `analyze`, `generate` | Yes | + +### Images + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gemini-2.5-flash-image` | Gemini 2.5 Flash Image | `edit`, `generate` | No | +| `gemini-3-pro-image-preview` | Gemini 3 Pro Image (Preview) | `edit`, `generate` | No | +| `imagen-4.0-generate-001` | Imagen 4 | `generate` | No | +| `imagen-4.0-fast-generate-001` | Imagen 4 Fast | `generate` | No | +| `imagen-4.0-ultra-generate-001` | Imagen 4 Ultra | `generate` | No | + +### Audio + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gemini-2.5-flash-tts` | Google TTS Gemini 2.5 Flash | `speak` | No | +| `gemini-2.5-pro-tts` | Google TTS Gemini 2.5 Pro | `speak` | No | + +### Videos + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `veo-3.0-generate-001` | Veo 3 | `generate` | No | +| `veo-3.0-fast-generate-001` | Veo 3 Fast | `generate` | No | +| `veo-3.1-generate-preview` | Veo 3.1 (Preview) | `generate` | No | +| `veo-3.1-fast-generate-preview` | Veo 3.1 Fast (Preview) | `generate` | No | + +### Embeddings + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gemini-embedding-001` | Gemini Embedding 001 | `embed` | No | +{/* AUTO-GENERATED:MODELS:END */} diff --git a/content/docs/providers/mistral.mdx b/content/docs/providers/mistral.mdx index a8814f8..f5f64eb 100644 --- a/content/docs/providers/mistral.mdx +++ b/content/docs/providers/mistral.mdx @@ -26,9 +26,43 @@ export MISTRAL_API_KEY="..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.MISTRAL) -response = await client.generate(prompt="Hello Mistral") +response = await celeste.text.generate( + model="mistral-large-latest", + provider="mistral", + prompt="Hello Mistral", +) ``` +## Models{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `codestral-latest` | Codestral | `generate` | Yes | +| `devstral-2512` | Devstral 2 | `generate` | Yes | +| `labs-devstral-small-2512` | Devstral 2 Small | `generate` | Yes | +| `devstral-medium-latest` | Devstral Medium | `generate` | Yes | +| `magistral-medium-latest` | Magistral Medium | `analyze`, `generate` | Yes | +| `magistral-small-latest` | Magistral Small | `analyze`, `generate` | Yes | +| `ministral-14b-latest` | Ministral 14B | `generate` | Yes | +| `ministral-3b-latest` | Ministral 3B | `generate` | Yes | +| `ministral-8b-latest` | Ministral 8B | `generate` | Yes | +| `mistral-large-latest` | Mistral Large | `generate` | Yes | +| `mistral-medium-latest` | Mistral Medium | `analyze`, `generate` | Yes | +| `mistral-small-latest` | Mistral Small | `analyze`, `generate` | Yes | +| `mistral-tiny` | Mistral Tiny | `generate` | Yes | +| `open-mistral-7b` | Open Mistral 7B | `generate` | Yes | +| `pixtral-12b-2409` | Pixtral 12B | `analyze`, `generate` | Yes | +| `pixtral-12b-latest` | Pixtral 12B | `analyze`, `generate` | Yes | +| `pixtral-large-latest` | Pixtral Large | `analyze`, `generate` | Yes | +| `voxtral-mini-2507` | Voxtral Mini | `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} diff --git a/content/docs/providers/openai.mdx b/content/docs/providers/openai.mdx index 6df9c55..20be307 100644 --- a/content/docs/providers/openai.mdx +++ b/content/docs/providers/openai.mdx @@ -27,10 +27,12 @@ export OPENAI_API_KEY="sk-..." ### Usage ```python -from celeste import create_client, Capability, Provider +import celeste -client = create_client(Capability.TEXT_GENERATION, Provider.OPENAI, model="gpt-4o") -response = await client.generate(prompt="Hello GPT-4o") +response = await celeste.text.generate( + model="gpt-4o", + prompt="Hello GPT-4o", +) ``` ## Image Generation @@ -43,10 +45,12 @@ response = await client.generate(prompt="Hello GPT-4o") ### Usage ```python -client = create_client(Capability.IMAGE_GENERATION, Provider.OPENAI) -response = await client.generate( +import celeste + +response = await celeste.images.generate( + model="dall-e-3", prompt="A cute robot", - quality="hd" + quality="hd", ) ``` @@ -60,10 +64,71 @@ response = await client.generate( ### Usage ```python -client = create_client(Capability.SPEECH_GENERATION, Provider.OPENAI) -response = await client.generate( - prompt="Hello world", - voice="alloy" +import celeste + +response = await celeste.audio.speak( + model="tts-1", + text="Hello world", + voice="alloy", ) ``` +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `audio`: `speak` +- `images`: `edit`, `generate` +- `text`: `analyze`, `generate` +- `videos`: `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gpt-3.5-turbo` | GPT-3.5 Turbo | `generate` | Yes | +| `gpt-4` | GPT-4 | `generate` | Yes | +| `gpt-4-turbo` | GPT-4 Turbo | `analyze`, `generate` | Yes | +| `gpt-4.1` | GPT-4.1 | `analyze`, `generate` | Yes | +| `gpt-4o` | GPT-4o | `analyze`, `generate` | Yes | +| `gpt-4o-mini` | GPT-4o Mini | `analyze`, `generate` | Yes | +| `gpt-5` | GPT-5 | `analyze`, `generate` | Yes | +| `gpt-5-mini` | GPT-5 Mini | `analyze`, `generate` | Yes | +| `gpt-5-nano` | GPT-5 Nano | `analyze`, `generate` | Yes | +| `gpt-5.1` | GPT-5.1 | `analyze`, `generate` | Yes | +| `gpt-5.1-codex` | GPT-5.1 Codex | `analyze`, `generate` | Yes | +| `gpt-5.2` | GPT-5.2 | `analyze`, `generate` | Yes | +| `gpt-5.2-codex` | GPT-5.2 Codex | `analyze`, `generate` | Yes | +| `gpt-5.2-chat-latest` | GPT-5.2 Instant | `analyze`, `generate` | Yes | +| `gpt-5.2-pro` | GPT-5.2 Pro | `analyze`, `generate` | Yes | + +### Images + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `dall-e-2` | DALL-E 2 | `edit`, `generate` | No | +| `dall-e-3` | DALL-E 3 | `generate` | No | +| `gpt-image-1` | GPT Image 1 | `edit`, `generate` | Yes | +| `gpt-image-1-mini` | GPT Image 1 Mini | `edit`, `generate` | Yes | +| `gpt-image-1.5` | GPT Image 1.5 | `edit`, `generate` | No | + +### Audio + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `gpt-4o-mini-tts` | GPT-4o Mini TTS | `speak` | No | +| `tts-1` | TTS-1 | `speak` | No | +| `tts-1-hd` | TTS-1 HD | `speak` | No | + +### Videos + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `sora-2` | Sora 2 | `generate` | No | +| `sora-2-2025-12-08` | Sora 2 (December 2025) | `generate` | No | +| `sora-2-pro` | Sora 2 Pro | `generate` | No | +{/* AUTO-GENERATED:MODELS:END */} From c05a2f82ecbc7c62b165ac5e6357190f56737ca7 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:28:40 +0100 Subject: [PATCH 06/13] docs: add new provider pages (bfl, byteplus, deepseek, gradium, groq, moonshot, xai) --- content/docs/providers/bfl.mdx | 39 +++++++++++++++++++++++ content/docs/providers/byteplus.mdx | 49 +++++++++++++++++++++++++++++ content/docs/providers/deepseek.mdx | 38 ++++++++++++++++++++++ content/docs/providers/gradium.mdx | 37 ++++++++++++++++++++++ content/docs/providers/groq.mdx | 49 +++++++++++++++++++++++++++++ content/docs/providers/meta.json | 18 +++++++++++ content/docs/providers/moonshot.mdx | 42 +++++++++++++++++++++++++ content/docs/providers/xai.mdx | 43 +++++++++++++++++++++++++ public/logos/bfl.svg | 1 + public/logos/gradium.svg | 3 ++ public/logos/groq.svg | 1 + 11 files changed, 320 insertions(+) create mode 100644 content/docs/providers/bfl.mdx create mode 100644 content/docs/providers/byteplus.mdx create mode 100644 content/docs/providers/deepseek.mdx create mode 100644 content/docs/providers/gradium.mdx create mode 100644 content/docs/providers/groq.mdx create mode 100644 content/docs/providers/meta.json create mode 100644 content/docs/providers/moonshot.mdx create mode 100644 content/docs/providers/xai.mdx create mode 100644 public/logos/bfl.svg create mode 100644 public/logos/gradium.svg create mode 100644 public/logos/groq.svg diff --git a/content/docs/providers/bfl.mdx b/content/docs/providers/bfl.mdx new file mode 100644 index 0000000..464f384 --- /dev/null +++ b/content/docs/providers/bfl.mdx @@ -0,0 +1,39 @@ +--- +title: Black Forest Labs +description: Documentation for the Black Forest Labs provider. +--- + +Black Forest Labs + +Celeste supports the **Black Forest Labs** provider. + +## Credentials + +Set the `BFL_API_KEY` environment variable. + +```bash +export BFL_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `images`: `edit`, `generate` + +### Images + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `flux-2-flex` | FLUX.2 [flex] | `edit`, `generate` | No | +| `flux-2-max` | FLUX.2 [max] | `edit`, `generate` | No | +| `flux-2-pro` | FLUX.2 [pro] | `edit`, `generate` | No | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/byteplus.mdx b/content/docs/providers/byteplus.mdx new file mode 100644 index 0000000..38ba413 --- /dev/null +++ b/content/docs/providers/byteplus.mdx @@ -0,0 +1,49 @@ +--- +title: BytePlus +description: Documentation for the BytePlus provider. +--- + +BytePlus + +Celeste supports the **BytePlus** provider. + +## Credentials + +Set the `BYTEPLUS_API_KEY` environment variable. + +```bash +export BYTEPLUS_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `images`: `generate` +- `videos`: `generate` + +### Images + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `seedream-4-0-250828` | Seedream 4.0 | `generate` | Yes | +| `seedream-4-5-251128` | Seedream 4.5 | `generate` | Yes | + +### Videos + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `seedance-1-0-lite-i2v-250428` | Seedance 1.0 Lite (Image-to-Video) | `generate` | No | +| `seedance-1-0-lite-t2v-250428` | Seedance 1.0 Lite (Text-to-Video) | `generate` | No | +| `seedance-1-0-pro-250528` | Seedance 1.0 Pro | `generate` | No | +| `seedance-1-0-pro-fast-251015` | Seedance 1.0 Pro Fast | `generate` | No | +| `seedance-1-5-pro-251215` | Seedance 1.5 Pro | `generate` | No | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/deepseek.mdx b/content/docs/providers/deepseek.mdx new file mode 100644 index 0000000..dc1a480 --- /dev/null +++ b/content/docs/providers/deepseek.mdx @@ -0,0 +1,38 @@ +--- +title: DeepSeek +description: Documentation for the DeepSeek provider. +--- + +DeepSeek + +Celeste supports the **DeepSeek** provider. + +## Credentials + +Set the `DEEPSEEK_API_KEY` environment variable. + +```bash +export DEEPSEEK_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `deepseek-chat` | DeepSeek Chat | `generate` | Yes | +| `deepseek-reasoner` | DeepSeek Reasoner | `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/gradium.mdx b/content/docs/providers/gradium.mdx new file mode 100644 index 0000000..c6b4d7f --- /dev/null +++ b/content/docs/providers/gradium.mdx @@ -0,0 +1,37 @@ +--- +title: Gradium +description: Documentation for the Gradium provider. +--- + +Gradium + +Celeste supports the **Gradium** provider. + +## Credentials + +Set the `GRADIUM_API_KEY` environment variable. + +```bash +export GRADIUM_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `audio`: `speak` + +### Audio + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `default` | Gradium Default TTS | `speak` | Yes | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/groq.mdx b/content/docs/providers/groq.mdx new file mode 100644 index 0000000..5e56444 --- /dev/null +++ b/content/docs/providers/groq.mdx @@ -0,0 +1,49 @@ +--- +title: Groq +description: Documentation for the Groq provider. +--- + +Groq + +Celeste supports the **Groq** provider. + +## Credentials + +Set the `GROQ_API_KEY` environment variable. + +```bash +export GROQ_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `allam-2-7b` | Allam 2 7B | `generate` | Yes | +| `openai/gpt-oss-120b` | GPT OSS 120B | `generate` | Yes | +| `openai/gpt-oss-20b` | GPT OSS 20B | `generate` | Yes | +| `openai/gpt-oss-safeguard-20b` | GPT OSS Safeguard 20B | `generate` | Yes | +| `groq/compound` | Groq Compound | `generate` | Yes | +| `groq/compound-mini` | Groq Compound Mini | `generate` | Yes | +| `moonshotai/kimi-k2-instruct` | Kimi K2 Instruct | `generate` | Yes | +| `moonshotai/kimi-k2-instruct-0905` | Kimi K2 Instruct 0905 | `generate` | Yes | +| `llama-3.1-8b-instant` | Llama 3.1 8B Instant | `generate` | Yes | +| `llama-3.3-70b-versatile` | Llama 3.3 70B Versatile | `generate` | Yes | +| `meta-llama/llama-4-maverick-17b-128e-instruct` | Llama 4 Maverick 17B | `analyze`, `generate` | Yes | +| `meta-llama/llama-4-scout-17b-16e-instruct` | Llama 4 Scout 17B | `analyze`, `generate` | Yes | +| `qwen/qwen3-32b` | Qwen 3 32B | `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/meta.json b/content/docs/providers/meta.json new file mode 100644 index 0000000..7c421ed --- /dev/null +++ b/content/docs/providers/meta.json @@ -0,0 +1,18 @@ +{ + "title": "Providers", + "pages": [ + "anthropic", + "bfl", + "byteplus", + "cohere", + "deepseek", + "elevenlabs", + "google", + "gradium", + "groq", + "mistral", + "moonshot", + "openai", + "xai" + ] +} diff --git a/content/docs/providers/moonshot.mdx b/content/docs/providers/moonshot.mdx new file mode 100644 index 0000000..ddfdbf6 --- /dev/null +++ b/content/docs/providers/moonshot.mdx @@ -0,0 +1,42 @@ +--- +title: Moonshot +description: Documentation for the Moonshot provider. +--- + +Moonshot + +Celeste supports the **Moonshot** provider. + +## Credentials + +Set the `MOONSHOT_API_KEY` environment variable. + +```bash +export MOONSHOT_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `kimi-k2-0711-preview` | Kimi K2 (0711 Preview) | `generate` | Yes | +| `kimi-k2-0905-preview` | Kimi K2 (0905 Preview) | `generate` | Yes | +| `kimi-k2-thinking` | Kimi K2 Thinking | `generate` | Yes | +| `kimi-k2-thinking-turbo` | Kimi K2 Thinking Turbo | `generate` | Yes | +| `kimi-k2-turbo-preview` | Kimi K2 Turbo Preview | `generate` | Yes | +| `moonshot-v1-8k-vision-preview` | Moonshot v1 8K Vision (Preview) | `analyze`, `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/content/docs/providers/xai.mdx b/content/docs/providers/xai.mdx new file mode 100644 index 0000000..c1edd55 --- /dev/null +++ b/content/docs/providers/xai.mdx @@ -0,0 +1,43 @@ +--- +title: xAI +description: Documentation for the xAI provider. +--- + +xAI + +Celeste supports the **xAI** provider. + +## Credentials + +Set the `XAI_API_KEY` environment variable. + +```bash +export XAI_API_KEY="..." +``` + +## Models + +{/* AUTO-GENERATED:MODELS:START */} + +This section is auto-generated from the Celeste registry. Do not edit manually. + +Available modalities: + +- `text`: `analyze`, `generate` + +### Text + +| Model ID | Display name | Operations | Streaming | +| :--- | :--- | :--- | :--- | +| `grok-2-vision-1212` | Grok 2 Vision | `analyze`, `generate` | Yes | +| `grok-3-mini` | Grok 3 Mini | `generate` | Yes | +| `grok-4-0709` | Grok 4 | `generate` | Yes | +| `grok-4-fast-non-reasoning` | Grok 4 Fast Non-Reasoning | `generate` | Yes | +| `grok-4-fast-reasoning` | Grok 4 Fast Reasoning | `generate` | Yes | +| `grok-4-1-fast-non-reasoning` | Grok 4.1 Fast Non-Reasoning | `generate` | Yes | +| `grok-4-1-fast-reasoning` | Grok 4.1 Fast Reasoning | `generate` | Yes | +{/* AUTO-GENERATED:MODELS:END */} + +## Notes + +_Add provider-specific tips, caveats, and examples here._ diff --git a/public/logos/bfl.svg b/public/logos/bfl.svg new file mode 100644 index 0000000..743e043 --- /dev/null +++ b/public/logos/bfl.svg @@ -0,0 +1 @@ +Black Forest Labs diff --git a/public/logos/gradium.svg b/public/logos/gradium.svg new file mode 100644 index 0000000..fd4fe89 --- /dev/null +++ b/public/logos/gradium.svg @@ -0,0 +1,3 @@ + + Gr + diff --git a/public/logos/groq.svg b/public/logos/groq.svg new file mode 100644 index 0000000..d2953ee --- /dev/null +++ b/public/logos/groq.svg @@ -0,0 +1 @@ +Groq From 5a407277fba8f398806183476ba9f3331957099b Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:28:49 +0100 Subject: [PATCH 07/13] docs: add contributing documentation --- .../docs/contributing/adding-a-provider.mdx | 78 +++++++++++++++++++ content/docs/contributing/architecture.mdx | 67 ++++++++++++++++ content/docs/contributing/meta.json | 4 + 3 files changed, 149 insertions(+) create mode 100644 content/docs/contributing/adding-a-provider.mdx create mode 100644 content/docs/contributing/architecture.mdx create mode 100644 content/docs/contributing/meta.json diff --git a/content/docs/contributing/adding-a-provider.mdx b/content/docs/contributing/adding-a-provider.mdx new file mode 100644 index 0000000..6a5935d --- /dev/null +++ b/content/docs/contributing/adding-a-provider.mdx @@ -0,0 +1,78 @@ +--- +title: Adding a Provider +description: How to implement a new provider for an existing modality. +--- + +# Adding a Provider + +Celeste makes it easy to add support for new AI providers. This guide outlines the steps to implement a new provider within an existing modality package. + +## Directory Structure + +Providers live under the monolith at `src/celeste/modalities//providers/`. + +For example, to add a provider to the `images` modality: + +``` +src/celeste/modalities/images/providers/ +└── {provider_slug}/ + ├── __init__.py + ├── client.py + ├── models.py + └── parameters.py +``` + +## Implementation Steps + +### 1. Create the Provider Package + +Create a new directory for your provider using the slug (e.g., `midjourney`, `stability`). You can also start from the templates in `templates/providers/` for a full scaffold. + +### 2. Implement the Client (`client.py`) + +The client implementation handles the communication with the provider's API. + +- Inherit from the modality's base client or a specific internal interface. +- Implement the `_make_request` or equivalent method to send data to the API. +- Map the provider's response to the Celeste standard `Output` objects defined in `io.py`. + +### 3. Define Models (`models.py`) + +List the available models supported by this provider for this modality. + +```python +from celeste.models import Model +from celeste.core import Modality, Operation + +MODELS = [ + Model( + id="provider-model-v1", + provider="new_provider", + operations={ + Modality.IMAGES: {Operation.GENERATE} + } + ) +] +``` + +### 4. Map Parameters (`parameters.py`) + +Map Celeste's standard parameters (like `quality`, `size`) to the provider's specific API parameters. + +- Use `ParameterMapper` classes to handle conversions. +- Ensure that provider-specific parameters are handled gracefully. + +### 5. Register the Provider (`__init__.py`) + +Expose the client and models in the provider's `__init__.py` so they can be discovered by the core registry. + +## Testing + +1. **Unit Tests**: Create tests in `tests/unit_tests/` to verify parameter mapping and response parsing without making network calls. +2. **Integration Tests**: Create tests in `tests/integration_tests/` to verify actual API interaction (requires API keys). + +## Best Practices + +- **Type Safety**: Use full type hints for all methods. +- **Error Handling**: Catch provider-specific errors and raise Celeste's standard exceptions where appropriate. +- **Documentation**: Add docstrings to your classes and methods explaining any provider-specific behaviors. diff --git a/content/docs/contributing/architecture.mdx b/content/docs/contributing/architecture.mdx new file mode 100644 index 0000000..bc6babe --- /dev/null +++ b/content/docs/contributing/architecture.mdx @@ -0,0 +1,67 @@ +--- +title: Architecture +description: Understanding the Modality-Centric Architecture of Celeste v1. +--- + +# Architecture + +Celeste v1 is designed around a **modality-centric core** with a **namespace-first public API**. Internally, the system is organized by the *output* type (modality), while the external API starts from the domain you work with. + +## Core Concepts + +The architecture is built on three pillars: + +1. **Modality (Output)**: The output type returned by an operation (e.g., text, images, audio, embeddings). +2. **Domain (What you work with)**: The resource you operate on (e.g., text, image, audio, video). +3. **Operation (Transformation)**: The method you call (e.g., `generate`, `analyze`). + +Rule of thumb: +- **Namespaces use domains**: start from `celeste.images`, `celeste.audio`, etc. +- **Clients use modalities**: use `create_client(modality=...)` when you need explicit control. + +## Package Structure + +The codebase is organized as a monolith, with modalities and providers grouped under `src/celeste`. + +``` +src/celeste/ +├── modalities/ +│ ├── text/ +│ │ ├── client.py # TextClient(ModalityClient) +│ │ ├── io.py # Inputs, Outputs, Chunks +│ │ └── providers/ +│ ├── images/ +│ ├── audio/ +│ ├── videos/ +│ └── embeddings/ +├── providers/ # Provider integrations +└── namespaces/ # Domain-first namespace API +``` + +### Key Components + +* **`ModalityClient`**: The base class for all modality clients (e.g., `ImagesClient`). It handles shared infrastructure like HTTP clients and authentication. +* **Operations as Methods**: Unlike previous versions where operations were separate packages, they are now methods on the client (e.g., `client.generate()`, `client.edit()`). +* **Operation-Scoped Types**: Inputs and Parameters are scoped to specific operations to ensure type safety. + +## Client Design + +The namespace API routes **domain + operation → modality client** under the hood. + +### Execution Modes + +Clients support three execution modes to handle different use cases: + +1. **Async (Default)**: `await client.generate(...)` - Returns typed Output objects. Best for production applications. +2. **Streaming**: `client.stream.generate(...)` - Returns an `AsyncIterator` of Chunks. Best for UIs requiring real-time feedback. +3. **Sync**: `client.sync.generate(...)` - Blocking calls. Best for scripts, notebooks, and testing. + +### Example: Images Domain Namespace + +The `celeste.images` namespace groups operations by the **image domain**, even when the output is text: + +- `celeste.images.generate(...)` → image output. +- `celeste.images.edit(...)` → image output. +- `celeste.images.analyze(...)` → text output. + +This keeps the public API intuitive while maintaining consistent output types via modality clients. diff --git a/content/docs/contributing/meta.json b/content/docs/contributing/meta.json new file mode 100644 index 0000000..1e5dab3 --- /dev/null +++ b/content/docs/contributing/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Contributing", + "pages": ["architecture", "adding-a-provider"] +} \ No newline at end of file From 3c0ef2cd5dc9580af65251b50e15128342949099 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:29:16 +0100 Subject: [PATCH 08/13] docs: update homepage and index for new structure --- content/docs/index.mdx | 90 +++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/content/docs/index.mdx b/content/docs/index.mdx index c70cd05..2cb945f 100644 --- a/content/docs/index.mdx +++ b/content/docs/index.mdx @@ -10,12 +10,16 @@ description: The primitive layer for multi-modal AI. Celeste Logo
The primitive layer for multi-modal AI - All capabilities. All providers. One interface. + All modalities. All providers. One interface.
Celeste is a unified interface for multi-modal AI. It provides a consistent, type-safe API across text, image, video, and audio generation from all major providers. +> Beta: The v1 public beta is available as `0.9`. The docs below reflect the namespace-first API and the domain → modality mental model. +> +> LLM-friendly export: [llms-full.txt](/llms-full.txt) for one-page ingestion. + ## Why Celeste? - **Primitives, not frameworks**: Celeste gives you raw building blocks, not opinionated chains or agents. @@ -25,39 +29,61 @@ Celeste is a unified interface for multi-modal AI. It provides a consistent, typ ## Supported Providers -
-
- Google - Google -
- -And many more including Perplexity, Groq, Replicate, and Stability AI. +{/* AUTO-GENERATED:SUPPORTED_PROVIDERS:END */} From 2c1f6700a1edfab2a30410b56fba031ba3e8aea1 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:29:58 +0100 Subject: [PATCH 09/13] docs: add Mermaid diagrams, provider logos, and page actions --- source.config.ts | 5 +- src/components/Mermaid.tsx | 53 +++++++ src/components/MethodSelector.tsx | 49 +++++++ src/components/page-actions.tsx | 235 ++++++++++++++++++++++++++++++ src/components/ui/button.tsx | 28 ++++ src/components/ui/popover.tsx | 32 ++++ src/lib/cn.ts | 1 + src/lib/provider-logos.ts | 68 +++++++++ src/mdx-components.tsx | 24 ++- 9 files changed, 493 insertions(+), 2 deletions(-) create mode 100644 src/components/Mermaid.tsx create mode 100644 src/components/MethodSelector.tsx create mode 100644 src/components/page-actions.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/popover.tsx create mode 100644 src/lib/cn.ts create mode 100644 src/lib/provider-logos.ts diff --git a/source.config.ts b/source.config.ts index d350251..9d4f3e6 100644 --- a/source.config.ts +++ b/source.config.ts @@ -4,6 +4,7 @@ import { frontmatterSchema, metaSchema, } from "fumadocs-mdx/config"; +import { remarkMdxMermaid } from "fumadocs-core/mdx-plugins"; // You can customise Zod schemas for frontmatter and `meta.json` here // see https://fumadocs.dev/docs/mdx/collections @@ -21,5 +22,7 @@ export const docs = defineDocs({ }); export default defineConfig({ - mdxOptions: {}, + mdxOptions: { + remarkPlugins: [remarkMdxMermaid], + }, }); diff --git a/src/components/Mermaid.tsx b/src/components/Mermaid.tsx new file mode 100644 index 0000000..90291e5 --- /dev/null +++ b/src/components/Mermaid.tsx @@ -0,0 +1,53 @@ +"use client"; + +import mermaid from "mermaid"; +import { useEffect, useState } from "react"; + +mermaid.initialize({ + startOnLoad: false, + theme: "default", + securityLevel: "loose", + fontFamily: "inherit", +}); + +interface MermaidProps { + chart: string; +} + +export function Mermaid({ chart }: MermaidProps) { + const [svg, setSvg] = useState(""); + const [error, setError] = useState(null); + + useEffect(() => { + if (!chart) return; + + const renderChart = async () => { + try { + const { svg } = await mermaid.render(`mermaid-${Date.now()}`, chart); + setSvg(svg); + setError(null); + } catch (err) { + console.error("Mermaid rendering failed:", err); + setError("Failed to render diagram"); + } + }; + + renderChart(); + }, [chart]); + + if (error) { + return ( +
+ {error} +
{chart}
+
+ ); + } + + return ( +
+ ); +} diff --git a/src/components/MethodSelector.tsx b/src/components/MethodSelector.tsx new file mode 100644 index 0000000..74e8cdd --- /dev/null +++ b/src/components/MethodSelector.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { useState, Children, isValidElement, type ReactNode } from "react"; +import { cn } from "@/lib/utils"; + +interface MethodSelectorProps { + items: string[]; + children: ReactNode; +} + +export function MethodSelector({ items, children }: MethodSelectorProps) { + const [selectedIndex, setSelectedIndex] = useState(0); + + // Filter out whitespace/text nodes to get only the element children (the divs) + const validChildren = Children.toArray(children).filter(isValidElement); + + return ( +
+
+ {items.map((item, index) => ( + + ))} +
+ + {validChildren.map((child, index) => ( +
+ {child} +
+ ))} +
+ ); +} diff --git a/src/components/page-actions.tsx b/src/components/page-actions.tsx new file mode 100644 index 0000000..b2c058c --- /dev/null +++ b/src/components/page-actions.tsx @@ -0,0 +1,235 @@ +'use client'; +import { useMemo, useState } from 'react'; +import { Check, ChevronDown, Copy, ExternalLinkIcon, MessageCircleIcon } from 'lucide-react'; +import { cn } from '../lib/cn'; +import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button'; +import { buttonVariants } from './ui/button'; +import { Popover, PopoverContent, PopoverTrigger } from './ui/popover'; +import { cva } from 'class-variance-authority'; + +const cache = new Map(); + +export function LLMCopyButton({ + /** + * A URL to fetch the raw Markdown/MDX content of page + */ + markdownUrl, +}: { + markdownUrl: string; +}) { + const [isLoading, setLoading] = useState(false); + const [checked, onClick] = useCopyButton(async () => { + const cached = cache.get(markdownUrl); + if (cached) return navigator.clipboard.writeText(cached); + + setLoading(true); + + try { + await navigator.clipboard.write([ + new ClipboardItem({ + 'text/plain': fetch(markdownUrl).then(async (res) => { + const content = await res.text(); + cache.set(markdownUrl, content); + + return content; + }), + }), + ]); + } finally { + setLoading(false); + } + }); + + return ( + + ); +} + +const optionVariants = cva( + 'text-sm p-2 rounded-lg inline-flex items-center gap-2 hover:text-fd-accent-foreground hover:bg-fd-accent [&_svg]:size-4', +); + +export function ViewOptions({ + markdownUrl, + githubUrl, +}: { + /** + * A URL to the raw Markdown/MDX content of page + */ + markdownUrl: string; + + /** + * Source file URL on GitHub + */ + githubUrl: string; +}) { + const items = useMemo(() => { + const fullMarkdownUrl = + typeof window !== 'undefined' ? new URL(markdownUrl, window.location.origin) : 'loading'; + const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`; + + return [ + { + title: 'Open in GitHub', + href: githubUrl, + icon: ( + + GitHub + + + ), + }, + { + title: 'Open in Scira AI', + href: `https://scira.ai/?${new URLSearchParams({ + q, + })}`, + icon: ( + + Scira AI + + + + + + + + + ), + }, + { + title: 'Open in ChatGPT', + href: `https://chatgpt.com/?${new URLSearchParams({ + hints: 'search', + q, + })}`, + icon: ( + + OpenAI + + + ), + }, + { + title: 'Open in Claude', + href: `https://claude.ai/new?${new URLSearchParams({ + q, + })}`, + icon: ( + + Anthropic + + + ), + }, + { + title: 'Open in T3 Chat', + href: `https://t3.chat/new?${new URLSearchParams({ + q, + })}`, + icon: , + }, + ]; + }, [githubUrl, markdownUrl]); + + return ( + + + Open + + + + {items.map((item) => ( + + {item.icon} + {item.title} + + + ))} + + + ); +} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..b427d4e --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,28 @@ +import { cva, type VariantProps } from 'class-variance-authority'; + +const variants = { + primary: 'bg-fd-primary text-fd-primary-foreground hover:bg-fd-primary/80', + outline: 'border hover:bg-fd-accent hover:text-fd-accent-foreground', + ghost: 'hover:bg-fd-accent hover:text-fd-accent-foreground', + secondary: + 'border bg-fd-secondary text-fd-secondary-foreground hover:bg-fd-accent hover:text-fd-accent-foreground', +} as const; + +export const buttonVariants = cva( + 'inline-flex items-center justify-center rounded-md p-2 text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fd-ring', + { + variants: { + variant: variants, + // fumadocs use `color` instead of `variant` + color: variants, + size: { + sm: 'gap-1 px-2 py-1.5 text-xs', + icon: 'p-1.5 [&_svg]:size-5', + 'icon-sm': 'p-1.5 [&_svg]:size-4.5', + 'icon-xs': 'p-1 [&_svg]:size-4', + }, + }, + }, +); + +export type ButtonProps = VariantProps; diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx new file mode 100644 index 0000000..c00f495 --- /dev/null +++ b/src/components/ui/popover.tsx @@ -0,0 +1,32 @@ +'use client'; +import * as PopoverPrimitive from '@radix-ui/react-popover'; +import * as React from 'react'; +import { cn } from '../../lib/cn'; + +const Popover = PopoverPrimitive.Root; + +const PopoverTrigger = PopoverPrimitive.Trigger; + +const PopoverContent = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => ( + + + +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; + +const PopoverClose = PopoverPrimitive.PopoverClose; + +export { Popover, PopoverTrigger, PopoverContent, PopoverClose }; diff --git a/src/lib/cn.ts b/src/lib/cn.ts new file mode 100644 index 0000000..ba66fd2 --- /dev/null +++ b/src/lib/cn.ts @@ -0,0 +1 @@ +export { twMerge as cn } from 'tailwind-merge'; diff --git a/src/lib/provider-logos.ts b/src/lib/provider-logos.ts new file mode 100644 index 0000000..e42e1f8 --- /dev/null +++ b/src/lib/provider-logos.ts @@ -0,0 +1,68 @@ +/** + * Provider logo mapping utilities + * Maps provider slugs to their logo paths and determines dark mode inversion needs + */ + +/** + * Maps provider slugs to logo file names. + * Some providers have different slugs than their logo file names. + */ +const logoMap: Record = { + byteplus: 'bytedance', // Special case: byteplus uses bytedance.svg +}; + +/** + * Providers whose logos need dark mode inversion + */ +const logosNeedingInversion = new Set([ + 'openai', + 'anthropic', + 'byteplus', // uses bytedance.svg + 'bfl', + 'xai', + 'elevenlabs', + 'groq', + 'deepseek', + 'moonshot', +]); + +/** + * Get the logo path for a provider slug + * @param slug Provider slug (e.g., 'openai', 'byteplus') + * @returns Logo path (e.g., '/logos/openai.svg') or null if not found + */ +export function getProviderLogoPath(slug: string): string | null { + const logoSlug = logoMap[slug] || slug; + return `/logos/${logoSlug}.svg`; +} + +/** + * Check if a provider logo needs dark mode inversion + * @param slug Provider slug + * @returns true if the logo needs dark:invert class + */ +export function needsDarkModeInversion(slug: string): boolean { + return logosNeedingInversion.has(slug); +} + +/** + * Check if a URL path is a provider page + * @param url Page URL (e.g., '/providers/openai') + * @returns true if the URL is a provider page + */ +export function isProviderPage(url: string): boolean { + return url.startsWith('/providers/'); +} + +/** + * Extract provider slug from a provider page URL + * @param url Provider page URL (e.g., '/providers/openai') + * @returns Provider slug (e.g., 'openai') or null if not a provider page + */ +export function getProviderSlugFromUrl(url: string): string | null { + if (!isProviderPage(url)) { + return null; + } + const parts = url.split('/'); + return parts[2] || null; // ['', 'providers', 'openai'] +} diff --git a/src/mdx-components.tsx b/src/mdx-components.tsx index 9ee2ec5..404959e 100644 --- a/src/mdx-components.tsx +++ b/src/mdx-components.tsx @@ -1,11 +1,33 @@ import defaultMdxComponents from "fumadocs-ui/mdx"; import type { MDXComponents } from "mdx/types"; import { InstallSelector } from "@/components/InstallSelector"; +import { Mermaid } from "@/components/Mermaid"; -export function getMDXComponents(components?: MDXComponents): MDXComponents { +type MDXComponentsOptions = MDXComponents & { + isProviderPage?: boolean; +}; + +export function getMDXComponents( + options?: MDXComponentsOptions, +): MDXComponents { + const { isProviderPage, ...components } = options || {}; return { ...defaultMdxComponents, InstallSelector, + Mermaid, ...components, + // Put img override last to ensure it takes precedence + img: (props) => { + // Don't render provider logo images on provider pages (they're shown inline with the title) + if (isProviderPage && props.src?.startsWith("/logos/")) { + return null; + } + // Use default img component for all other images + const DefaultImg = defaultMdxComponents.img; + if (DefaultImg) { + return ; + } + return ; + }, }; } From 52e44c2801b3a48b73bbcba61aa4931eb6f3354d Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:30:17 +0100 Subject: [PATCH 10/13] docs: enhance page rendering with provider logos and navigation --- src/app/[[...slug]]/page.tsx | 64 +++++++++++++++++++++++++++++++--- src/app/global.css | 6 ++++ src/app/layout.tsx | 41 ++++++++++++++++++++-- src/app/llms-full.txt/route.ts | 10 ++++-- src/lib/layout.shared.tsx | 15 ++------ src/lib/source.ts | 52 ++++++++++++++++++++++++++- 6 files changed, 165 insertions(+), 23 deletions(-) diff --git a/src/app/[[...slug]]/page.tsx b/src/app/[[...slug]]/page.tsx index 07347e7..7e50bd5 100644 --- a/src/app/[[...slug]]/page.tsx +++ b/src/app/[[...slug]]/page.tsx @@ -5,26 +5,82 @@ import { DocsPage, DocsTitle, } from "fumadocs-ui/page"; +import { findNeighbour } from "fumadocs-core/page-tree"; import type { Metadata } from "next"; -import { notFound } from "next/navigation"; +import { notFound, redirect } from "next/navigation"; +import { LLMCopyButton, ViewOptions } from "@/components/page-actions"; +import { + getProviderLogoPath, + getProviderSlugFromUrl, + needsDarkModeInversion, +} from "@/lib/provider-logos"; import { getPageImage, source } from "@/lib/source"; import { getMDXComponents } from "@/mdx-components"; +const DOCS_GITHUB_URL = "https://github.com/withceleste/docs"; + export default async function Page(props: PageProps<"/[[...slug]]">) { const params = await props.params; + + // V1 Redirects (legacy routes) + const redirects: Record = { + "providers/bytedance": "providers/byteplus", + }; + + const slugPath = (params.slug || []).join("/"); + if (redirects[slugPath]) { + redirect(redirects[slugPath]); + } + const page = source.getPage(params.slug); if (!page) notFound(); const MDX = page.data.body; + const neighbours = findNeighbour(source.pageTree, page.url); + const markdownUrl = `${page.url}.mdx`; + const githubUrl = `${DOCS_GITHUB_URL}/blob/main/content/docs/${page.path}`; + + // Check if this is a provider page and get logo info + const providerSlug = getProviderSlugFromUrl(page.url); + const isProviderPage = providerSlug !== null; + const logoPath = isProviderPage ? getProviderLogoPath(providerSlug) : null; + const needsInversion = isProviderPage && needsDarkModeInversion(providerSlug); return ( - - {page.data.title} + + {isProviderPage && logoPath ? ( +
+ {page.data.title} + {page.data.title} +
+ ) : ( + {page.data.title} + )} {page.data.description} - +
+ + +
+ diff --git a/src/app/global.css b/src/app/global.css index 98de65d..3d8304c 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -140,3 +140,9 @@ header nav a { transition-timing-function: ease-out; transition-duration: 0.2s; } + +/* Hide provider logo images in MDX content (they're now shown inline with the title) */ +[data-provider-page="true"] img[src^="/logos/"] { + display: none !important; +} + diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3dca9e6..9c7c46c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,8 +1,9 @@ import { DocsLayout } from "fumadocs-ui/layouts/docs"; import { RootProvider } from "fumadocs-ui/provider/next"; import { Space_Grotesk, Space_Mono } from "next/font/google"; -import { baseOptions } from "@/lib/layout.shared"; +import { baseOptions, GITHUB_URL, WEBSITE_URL } from "@/lib/layout.shared"; import { source } from "@/lib/source"; +import { Github, Globe } from "lucide-react"; import "./global.css"; const spaceGrotesk = Space_Grotesk({ @@ -27,8 +28,42 @@ export default function Layout({ children }: LayoutProps<"/">) { suppressHydrationWarning > - - + + + + + Website + + + + GitHub + +
+ ), + }} + {...baseOptions()} + > {children} diff --git a/src/app/llms-full.txt/route.ts b/src/app/llms-full.txt/route.ts index fcccaee..6f1dae8 100644 --- a/src/app/llms-full.txt/route.ts +++ b/src/app/llms-full.txt/route.ts @@ -1,10 +1,14 @@ -import { getLLMText, source } from "@/lib/source"; +import { getLLMText, getPagesInNavOrder } from "@/lib/source"; export const revalidate = false; export async function GET() { - const scan = source.getPages().map(getLLMText); + const scan = getPagesInNavOrder().map(getLLMText); const scanned = await Promise.all(scan); - return new Response(scanned.join("\n\n")); + return new Response(scanned.join("\n\n"), { + headers: { + "Content-Type": "text/markdown; charset=utf-8", + }, + }); } diff --git a/src/lib/layout.shared.tsx b/src/lib/layout.shared.tsx index c017f04..af12143 100644 --- a/src/lib/layout.shared.tsx +++ b/src/lib/layout.shared.tsx @@ -1,6 +1,9 @@ import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"; import Image from "next/image"; +export const WEBSITE_URL = "https://withceleste.ai"; +export const GITHUB_URL = "https://github.com/withceleste/celeste-python"; + export function baseOptions(): BaseLayoutProps { return { nav: { @@ -25,17 +28,5 @@ export function baseOptions(): BaseLayoutProps { ), url: "/", }, - links: [ - { - text: "Website", - url: "https://withceleste.ai", - external: true, - }, - { - text: "GitHub", - url: "https://github.com/withceleste/celeste-python", - external: true, - }, - ], }; } diff --git a/src/lib/source.ts b/src/lib/source.ts index 482b458..184001b 100644 --- a/src/lib/source.ts +++ b/src/lib/source.ts @@ -1,5 +1,6 @@ import { type InferPageType, loader } from "fumadocs-core/source"; import { lucideIconsPlugin } from "fumadocs-core/source/lucide-icons"; +import type { Item, Node } from "fumadocs-core/page-tree"; import { docs } from "@/.source"; // See https://fumadocs.dev/docs/headless/source-api for more info @@ -9,6 +10,55 @@ export const source = loader({ plugins: [lucideIconsPlugin()], }); +function _scanNavNodes(nodes: Node[]): Item[] { + const out: Item[] = []; + + for (const node of nodes) { + if (node.type === "folder") { + // Include folder index (if any) before its children (matches Fumadocs nav order) + if (node.index && !node.index.external) { + out.push(node.index); + } + out.push(..._scanNavNodes(node.children)); + continue; + } + + if (node.type === "page" && !node.external) { + out.push(node); + } + } + + return out; +} + +export function getPagesInNavOrder( + language?: string, +): InferPageType[] { + const tree = source.getPageTree(language); + + const orderedNodes = _scanNavNodes(tree.children); + if (tree.fallback) { + // Keep fallback (unlisted/isolated) pages last. + orderedNodes.push(..._scanNavNodes(tree.fallback.children)); + } + + const pages: InferPageType[] = []; + const seen = new Set(); + + for (const node of orderedNodes) { + const page = source.getNodePage(node, language); + if (!page) continue; + + // Avoid accidental duplicates from index/child overlap. + if (seen.has(page.url)) continue; + seen.add(page.url); + + pages.push(page); + } + + return pages; +} + export function getPageImage(page: InferPageType) { const segments = [...page.slugs, "image.png"]; @@ -21,7 +71,7 @@ export function getPageImage(page: InferPageType) { export async function getLLMText(page: InferPageType) { const processed = await page.data.getText("processed"); - return `# ${page.data.title} + return `# ${page.data.title} (${page.url}) ${processed}`; } From 34f8d9f67360608add5e281b08e3819ff0c101c0 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sat, 17 Jan 2026 19:30:26 +0100 Subject: [PATCH 11/13] docs: simplify install selector to remove capability selection --- src/components/InstallSelector.tsx | 75 ++---------------------------- 1 file changed, 5 insertions(+), 70 deletions(-) diff --git a/src/components/InstallSelector.tsx b/src/components/InstallSelector.tsx index 6c90d03..ab74ab5 100644 --- a/src/components/InstallSelector.tsx +++ b/src/components/InstallSelector.tsx @@ -10,29 +10,6 @@ function classNames(...classes: (string | undefined | null | false)[]) { } type PackageManager = "uv" | "pip" | "poetry"; -type Capability = - | "all" - | "text-generation" - | "image-generation" - | "video-generation" - | "speech-generation"; - -const CAPABILITIES: { id: Capability; label: string; description?: string }[] = - [ - { id: "all", label: "All Features", description: "Everything included" }, - { id: "text-generation", label: "Text", description: "LLMs & Chat" }, - { - id: "image-generation", - label: "Image", - description: "Generation & Editing", - }, - { - id: "video-generation", - label: "Video", - description: "Creation & Analysis", - }, - { id: "speech-generation", label: "Speech", description: "TTS & Audio" }, - ]; const MANAGERS: { id: PackageManager; label: string }[] = [ { id: "uv", label: "uv" }, @@ -42,21 +19,18 @@ const MANAGERS: { id: PackageManager; label: string }[] = [ export function InstallSelector() { const [manager, setManager] = useState("uv"); - const [capability, setCapability] = useState("all"); const [copied, setCopied] = useState(false); const getCommand = () => { - const packageSpec = `celeste-ai[${capability}]`; - // pip and poetry usually require quotes for brackets in zsh/bash - const quotedSpec = `"${packageSpec}"`; + const packageSpec = "celeste-ai"; switch (manager) { case "uv": - return `uv add ${quotedSpec}`; + return `uv add ${packageSpec}`; case "pip": - return `pip install ${quotedSpec}`; + return `pip install ${packageSpec}`; case "poetry": - return `poetry add ${quotedSpec}`; + return `poetry add ${packageSpec}`; } }; @@ -93,43 +67,6 @@ export function InstallSelector() {
- {/* Capability Selection */} -
-
- Select capabilities -
-
- {CAPABILITIES.map((c) => ( - - ))} -
-
- {/* Command Output */}
@@ -142,9 +79,7 @@ export function InstallSelector() { {manager === "pip" ? "install" : "add"} {" "} - - "{`celeste-ai[${capability}]`}" - + celeste-ai