diff --git a/ingesters/__tests__/AsciiDocIngester.test.ts b/ingesters/__tests__/AsciiDocIngester.test.ts index 15dfb6b..6435e28 100644 --- a/ingesters/__tests__/AsciiDocIngester.test.ts +++ b/ingesters/__tests__/AsciiDocIngester.test.ts @@ -66,7 +66,7 @@ describe('AsciiDocIngester', () => { bookConfig: { repoOwner: 'test-owner', repoName: 'test-repo', - fileExtension: '.adoc', + fileExtensions: ['.adoc'], chunkSize: 1000, chunkOverlap: 200, baseUrl: 'https://example.com', @@ -300,7 +300,7 @@ This is page 2 content.`, bookConfig: { repoOwner: 'test-owner', repoName: 'test-repo', - fileExtension: '.adoc', + fileExtensions: ['.adoc'], chunkSize: 1000, chunkOverlap: 200, baseUrl: '', diff --git a/ingesters/__tests__/DojoDocsIngester.test.ts b/ingesters/__tests__/DojoDocsIngester.test.ts new file mode 100644 index 0000000..1a21d78 --- /dev/null +++ b/ingesters/__tests__/DojoDocsIngester.test.ts @@ -0,0 +1,156 @@ +import { describe, it, expect } from 'bun:test'; +import { DojoDocsIngester } from '../src/ingesters/DojoDocsIngester'; +import { DocumentSource } from '../src/types'; + +describe('DojoDocsIngester', () => { + it('should be configured correctly for Dojo documentation', () => { + const ingester = new DojoDocsIngester(); + + // Check that it has the correct configuration + expect(ingester).toBeDefined(); + // @ts-ignore - accessing config for testing purposes + expect(ingester.config).toEqual({ + repoOwner: 'dojoengine', + repoName: 'book', + fileExtensions: ['.md', '.mdx'], + chunkSize: 4096, + chunkOverlap: 512, + baseUrl: 'https://book.dojoengine.org', + urlSuffix: '', + useUrlMapping: true, + }); + // @ts-ignore - accessing source for testing purposes + expect(ingester.source).toBe(DocumentSource.DOJO_DOCS); + }); + + it('should have correct extract directory', () => { + const ingester = new DojoDocsIngester(); + + // @ts-ignore - accessing private method for testing + const extractDir = ingester.getExtractDir(); + + expect(extractDir).toBeDefined(); + expect(extractDir).toContain('dojo-docs'); + }); + + it('should process markdown content correctly', () => { + const ingester = new DojoDocsIngester(); + + // Test markdown content + const testContent = `## Getting Started + +Dojo is a provable game engine and toolchain for building onchain games. + +\`\`\`bash +$ sozo init my-game +\`\`\` + +This command creates a new Dojo project. + +## Installation + +Install the required dependencies.`; + + // @ts-ignore - accessing private method for testing + const chunks = ingester.createChunkFromPage('getting-started', testContent); + + expect(chunks).toBeDefined(); + expect(chunks.length).toBeGreaterThan(0); + + // Check that chunks have correct metadata + const firstChunk = chunks[0]; + expect(firstChunk).toBeDefined(); + expect(firstChunk!.metadata.name).toBe('getting-started'); + expect(firstChunk!.metadata.source).toBe(DocumentSource.DOJO_DOCS); + expect(firstChunk!.metadata.sourceLink).toContain( + 'https://book.dojoengine.org', + ); + }); + + it('should split content into multiple sections based on headers', () => { + const ingester = new DojoDocsIngester(); + + // Test content with multiple headers + const processedContent = `## Introduction + +Dojo is a provable game engine and toolchain for building onchain games. + +## Installation + +Install Dojo using the following command: + +\`\`\`bash +$ curl -L https://install.dojoengine.org | bash +\`\`\` + +## Configuration + +Configure your Dojo project settings in the Scarb.toml file.`; + + // @ts-ignore - accessing private method for testing + const chunks = ingester.createChunkFromPage( + 'getting-started', + processedContent, + ); + + expect(chunks).toBeDefined(); + expect(chunks.length).toBeGreaterThanOrEqual(3); + + // Check that we have chunks for each section + const titles = chunks.map((chunk) => chunk.metadata.title); + expect(titles).toContain('Introduction'); + expect(titles).toContain('Installation'); + expect(titles).toContain('Configuration'); + }); + + it('should sanitize code blocks correctly', () => { + const ingester = new DojoDocsIngester(); + + // Test content with code blocks + const testContent = `## Example + +Here's an example: + +\`\`\`cairo +# This is a comment in code +fn main() { + println!("Hello"); +} +\`\`\` + +That was the example.`; + + // @ts-ignore - accessing private method for testing + const sanitized = ingester.sanitizeCodeBlocks(testContent); + + expect(sanitized).toBeDefined(); + expect(sanitized).toContain('```cairo'); + expect(sanitized).toContain('fn main()'); + }); + + it('should generate correct URLs with useUrlMapping', () => { + const ingester = new DojoDocsIngester(); + + const testContent = `## Components + +Components are the building blocks of your Dojo entities.`; + + // @ts-ignore - accessing private method for testing + const chunks = ingester.createChunkFromPage( + 'core-concepts/entities', + testContent, + ); + + expect(chunks).toBeDefined(); + expect(chunks.length).toBeGreaterThan(0); + + // All chunks should have the correct source link format + chunks.forEach((chunk) => { + expect(chunk.metadata.sourceLink).toContain( + 'https://book.dojoengine.org', + ); + expect(chunk.metadata.sourceLink).toContain('core-concepts/entities'); + expect(chunk.metadata.source).toBe(DocumentSource.DOJO_DOCS); + }); + }); +}); diff --git a/ingesters/__tests__/IngesterFactory.test.ts b/ingesters/__tests__/IngesterFactory.test.ts index 41ea1c9..9fadc37 100644 --- a/ingesters/__tests__/IngesterFactory.test.ts +++ b/ingesters/__tests__/IngesterFactory.test.ts @@ -76,6 +76,7 @@ describe('IngesterFactory', () => { DocumentSource.SCARB_DOCS, DocumentSource.STARKNET_JS, DocumentSource.STARKNET_BLOG, + DocumentSource.DOJO_DOCS, ]); }); }); diff --git a/ingesters/__tests__/MarkdownIngester.test.ts b/ingesters/__tests__/MarkdownIngester.test.ts index 24a1530..9f22343 100644 --- a/ingesters/__tests__/MarkdownIngester.test.ts +++ b/ingesters/__tests__/MarkdownIngester.test.ts @@ -15,7 +15,7 @@ const markdownIngester = new TestMarkdownIngester( repoOwner: 'test', repoName: 'test', baseUrl: 'https://test.com', - fileExtension: 'md', + fileExtensions: ['md'], urlSuffix: '.html', chunkSize: 1000, chunkOverlap: 100, @@ -311,7 +311,7 @@ describe('URL sourcing and generation', () => { repoOwner: 'test', repoName: 'test', baseUrl: 'https://docs.example.com', - fileExtension: 'md', + fileExtensions: ['md'], urlSuffix: '.html', chunkSize: 1000, chunkOverlap: 100, @@ -342,7 +342,7 @@ describe('URL sourcing and generation', () => { repoOwner: 'test', repoName: 'test', baseUrl: 'https://docs.starknet.io', - fileExtension: 'md', + fileExtensions: ['md'], urlSuffix: '', chunkSize: 1000, chunkOverlap: 100, @@ -379,7 +379,7 @@ describe('URL sourcing and generation', () => { repoOwner: 'test', repoName: 'test', baseUrl: 'https://book.cairo-lang.org', - fileExtension: 'md', + fileExtensions: ['md'], urlSuffix: '.html', chunkSize: 1000, chunkOverlap: 100, diff --git a/ingesters/__tests__/StarknetDocsIngester.test.ts b/ingesters/__tests__/StarknetDocsIngester.test.ts index 72cea61..23edfc4 100644 --- a/ingesters/__tests__/StarknetDocsIngester.test.ts +++ b/ingesters/__tests__/StarknetDocsIngester.test.ts @@ -12,7 +12,7 @@ describe('StarknetDocsIngester', () => { expect(ingester.config).toEqual({ repoOwner: 'starknet-io', repoName: 'starknet-docs', - fileExtension: '.mdx', + fileExtensions: ['.mdx'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://docs.starknet.io', diff --git a/ingesters/pnpm-lock.yaml b/ingesters/pnpm-lock.yaml new file mode 100644 index 0000000..32de825 --- /dev/null +++ b/ingesters/pnpm-lock.yaml @@ -0,0 +1,2120 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@antora/lunr-extension': + specifier: 1.0.0-alpha.10 + version: 1.0.0-alpha.10 + '@asciidoctor/tabs': + specifier: 1.0.0-beta.6 + version: 1.0.0-beta.6 + '@iarna/toml': + specifier: ^2.2.5 + version: 2.2.5 + '@langchain/core': + specifier: ^0.3.78 + version: 0.3.79(openai@4.104.0(zod@3.25.76)) + '@langchain/google-genai': + specifier: ^0.2.18 + version: 0.2.18(@langchain/core@0.3.79(openai@4.104.0(zod@3.25.76))) + '@langchain/openai': + specifier: ^0.0.25 + version: 0.0.25 + '@types/adm-zip': + specifier: ^0.5.7 + version: 0.5.7 + adm-zip: + specifier: ^0.5.16 + version: 0.5.16 + asciidoctor: + specifier: ^3.0.4 + version: 3.0.4 + axios: + specifier: ^1.7.9 + version: 1.13.2 + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + downdoc: + specifier: 1.0.2-stable + version: 1.0.2-stable + lunr: + specifier: ^2.3.9 + version: 2.3.9 + pg: + specifier: ^8.14.1 + version: 8.16.3 + winston: + specifier: ^3.17.0 + version: 3.18.3 + devDependencies: + '@types/bun': + specifier: ^1.2.23 + version: 1.3.3 + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 + '@types/node': + specifier: ^24.6.2 + version: 24.10.1 + '@types/pg': + specifier: ^8.15.5 + version: 8.15.6 + prettier: + specifier: ^3.5.2 + version: 3.6.2 + typescript: + specifier: ^5.7.3 + version: 5.9.3 + +packages: + + '@antora/lunr-extension@1.0.0-alpha.10': + resolution: {integrity: sha512-YunvJ3D/Q/GfIgOvmoFvL6NrKLL3TBN2UiemIDCquvWl6z0Jlonb5w3GkT/CKhtnGWXDPOMOJ7M4fVOKjMOHZw==} + engines: {node: '>=16.0.0'} + + '@asciidoctor/cli@4.0.0': + resolution: {integrity: sha512-x2T9gW42921Zd90juEagtbViPZHNP2MWf0+6rJEkOzW7E9m3TGJtz+Guye9J0gwrpZsTMGCpfYMQy1We3X7osg==} + engines: {node: '>=16', npm: '>=8.0.0'} + hasBin: true + peerDependencies: + '@asciidoctor/core': '>=2 <4' + + '@asciidoctor/core@3.0.4': + resolution: {integrity: sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==} + engines: {node: '>=16', npm: '>=8'} + + '@asciidoctor/opal-runtime@3.0.1': + resolution: {integrity: sha512-iW7ACahOG0zZft4A/4CqDcc7JX+fWRNjV5tFAVkNCzwZD+EnFolPaUOPYt8jzadc0+Bgd80cQTtRMQnaaV1kkg==} + engines: {node: '>=16'} + + '@asciidoctor/tabs@1.0.0-beta.6': + resolution: {integrity: sha512-gGZnW7UfRXnbiyKNd9PpGKtSuD8+DsqaaTSbQ1dHVkZ76NaolLhdQg8RW6/xqN3pX1vWZEcF4e81+Oe9rNRWxg==} + engines: {node: '>=16.0.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.8': + resolution: {integrity: sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==} + + '@google/generative-ai@0.24.1': + resolution: {integrity: sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==} + engines: {node: '>=18.0.0'} + + '@iarna/toml@2.2.5': + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.2.0': + resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@30.2.0': + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@langchain/core@0.1.63': + resolution: {integrity: sha512-+fjyYi8wy6x1P+Ee1RWfIIEyxd9Ee9jksEwvrggPwwI/p45kIDTdYTblXsM13y4mNWTiACyLSdbwnPaxxdoz+w==} + engines: {node: '>=18'} + + '@langchain/core@0.3.79': + resolution: {integrity: sha512-ZLAs5YMM5N2UXN3kExMglltJrKKoW7hs3KMZFlXUnD7a5DFKBYxPFMeXA4rT+uvTxuJRZPCYX0JKI5BhyAWx4A==} + engines: {node: '>=18'} + + '@langchain/google-genai@0.2.18': + resolution: {integrity: sha512-m9EiN3VKC01A7/625YQ6Q1Lqq8zueewADX4W5Tcme4RImN75zkg2Z7FYbD1Fo6Zwolc4wBNO6LUtbg3no4rv1Q==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': '>=0.3.58 <0.4.0' + + '@langchain/openai@0.0.25': + resolution: {integrity: sha512-cD9xPDDXK2Cjs6yYg27BpdzBnQZvBb1yaNgMoGLWIT27UQVRyT96PLC1OVMQOmMmHaKDBCj/1bW4GQQgX7+d2Q==} + engines: {node: '>=18'} + + '@sinclair/typebox@0.34.41': + resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + + '@so-ric/colorspace@1.1.6': + resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==} + + '@types/adm-zip@0.5.7': + resolution: {integrity: sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==} + + '@types/bun@1.3.3': + resolution: {integrity: sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + + '@types/pg@8.15.6': + resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + a-sync-waterfall@1.0.1: + resolution: {integrity: sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + adm-zip@0.5.16: + resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} + engines: {node: '>=12.0'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + asciidoctor@3.0.4: + resolution: {integrity: sha512-hIc0Bx73wePxtic+vWBHOIgMfKSNiCmRz7BBfkyykXATrw20YGd5a3CozCHvqEPH+Wxp5qKD4aBsgtokez8nEA==} + engines: {node: '>=16', npm: '>=8'} + hasBin: true + + assert-never@1.4.0: + resolution: {integrity: sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + babel-walk@3.0.0-canary-5: + resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} + engines: {node: '>= 10.0.0'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + binary-search@1.3.6: + resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bun-types@1.3.3: + resolution: {integrity: sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + character-parser@2.2.0: + resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} + + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-convert@3.1.3: + resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==} + engines: {node: '>=14.6'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-name@2.1.0: + resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==} + engines: {node: '>=12.20'} + + color-string@2.1.4: + resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} + engines: {node: '>=18'} + + color@5.0.3: + resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} + engines: {node: '>=18'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + + console-table-printer@2.15.0: + resolution: {integrity: sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==} + + constantinople@4.0.1: + resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + doctypes@1.1.0: + resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + downdoc@1.0.2-stable: + resolution: {integrity: sha512-eYTOmnYp3a6ibweDWLO72Y2NxWtw5YVA5rpfS4+vjWh6K1F9bD3TrwxYxfjfudqwBtYeeIYkn7b9UXN22NkZSw==} + engines: {node: '>=16.17.0'} + hasBin: true + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + expect@30.2.0: + resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-any-array@2.0.1: + resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-expression@4.0.0: + resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + jest-diff@30.2.0: + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.2.0: + resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@30.2.0: + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.2.0: + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.2.0: + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + js-stringify@1.0.2: + resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} + + js-tiktoken@1.0.21: + resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jstransformer@1.0.0: + resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==} + + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + + langsmith@0.1.68: + resolution: {integrity: sha512-otmiysWtVAqzMx3CJ4PrtUBhWRG5Co8Z4o7hSZENPjlit9/j3/vm3TSvbaxpDYakZxtMjhkcJTqrdYFipISEiQ==} + peerDependencies: + openai: '*' + peerDependenciesMeta: + openai: + optional: true + + langsmith@0.3.81: + resolution: {integrity: sha512-NFmp7TDrrbCE6TIfHqutN9xhdgvx0EOhULVo8bDW+ib5idprwjMTvmS0S1n9uVFwjN03zU2zVEWViXnwy5XPrw==} + peerDependencies: + '@opentelemetry/api': '*' + '@opentelemetry/exporter-trace-otlp-proto': '*' + '@opentelemetry/sdk-trace-base': '*' + openai: '*' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/exporter-trace-otlp-proto': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + openai: + optional: true + + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + + lunr-languages@1.10.0: + resolution: {integrity: sha512-BBjKKcwrieJlzwwc9M5H/MRXGJ2qyOSDx/NXYiwkuKjiLOOoouh0WsDzeqcLoUWcX31y7i8sb8IgsZKObdUCkw==} + + lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ml-array-mean@1.1.6: + resolution: {integrity: sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ==} + + ml-array-sum@1.1.6: + resolution: {integrity: sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw==} + + ml-distance-euclidean@2.0.0: + resolution: {integrity: sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q==} + + ml-distance@4.0.1: + resolution: {integrity: sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw==} + + ml-tree-similarity@1.0.0: + resolution: {integrity: sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + num-sort@2.1.0: + resolution: {integrity: sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg==} + engines: {node: '>=8'} + + nunjucks@3.2.4: + resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==} + engines: {node: '>= 6.9.0'} + hasBin: true + peerDependencies: + chokidar: ^3.3.0 + peerDependenciesMeta: + chokidar: + optional: true + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + + openai@4.104.0: + resolution: {integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + pg-cloudflare@1.2.7: + resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} + + pg-connection-string@2.9.1: + resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-pool@3.10.1: + resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==} + peerDependencies: + pg: '>=8.0' + + pg-protocol@1.10.3: + resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + pg@8.16.3: + resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==} + engines: {node: '>= 16.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pug-attrs@3.0.0: + resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} + + pug-code-gen@3.0.3: + resolution: {integrity: sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==} + + pug-error@2.1.0: + resolution: {integrity: sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==} + + pug-filters@4.0.0: + resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==} + + pug-lexer@5.0.1: + resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==} + + pug-linker@4.0.0: + resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==} + + pug-load@3.0.0: + resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==} + + pug-parser@6.0.0: + resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==} + + pug-runtime@3.0.1: + resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==} + + pug-strip-comments@2.0.0: + resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==} + + pug-walk@2.0.0: + resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==} + + pug@3.0.3: + resolution: {integrity: sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + simple-wcswidth@1.1.2: + resolution: {integrity: sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + token-stream@1.0.0: + resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unxhr@1.2.0: + resolution: {integrity: sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==} + engines: {node: '>=8.11'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.18.3: + resolution: {integrity: sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==} + engines: {node: '>= 12.0.0'} + + with@7.0.2: + resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} + engines: {node: '>= 10.0.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.3.1: + resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==} + engines: {node: '>=12'} + + zod-to-json-schema@3.25.0: + resolution: {integrity: sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==} + peerDependencies: + zod: ^3.25 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@antora/lunr-extension@1.0.0-alpha.10': + dependencies: + htmlparser2: 9.1.0 + lunr: 2.3.9 + lunr-languages: 1.10.0 + + '@asciidoctor/cli@4.0.0(@asciidoctor/core@3.0.4)': + dependencies: + '@asciidoctor/core': 3.0.4 + yargs: 17.3.1 + + '@asciidoctor/core@3.0.4': + dependencies: + '@asciidoctor/opal-runtime': 3.0.1 + unxhr: 1.2.0 + + '@asciidoctor/opal-runtime@3.0.1': + dependencies: + glob: 8.1.0 + unxhr: 1.2.0 + + '@asciidoctor/tabs@1.0.0-beta.6': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@cfworker/json-schema@4.1.1': {} + + '@colors/colors@1.6.0': {} + + '@dabh/diagnostics@2.0.8': + dependencies: + '@so-ric/colorspace': 1.1.6 + enabled: 2.0.0 + kuler: 2.0.0 + + '@google/generative-ai@0.24.1': {} + + '@iarna/toml@2.2.5': {} + + '@jest/diff-sequences@30.0.1': {} + + '@jest/expect-utils@30.2.0': + dependencies: + '@jest/get-type': 30.1.0 + + '@jest/get-type@30.1.0': {} + + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 24.10.1 + jest-regex-util: 30.0.1 + + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.41 + + '@jest/types@30.2.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.10.1 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@langchain/core@0.1.63(openai@4.104.0(zod@3.25.76))': + dependencies: + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.21 + langsmith: 0.1.68(openai@4.104.0(zod@3.25.76)) + ml-distance: 4.0.1 + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 9.0.1 + zod: 3.25.76 + zod-to-json-schema: 3.25.0(zod@3.25.76) + transitivePeerDependencies: + - openai + + '@langchain/core@0.3.79(openai@4.104.0(zod@3.25.76))': + dependencies: + '@cfworker/json-schema': 4.1.1 + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.21 + langsmith: 0.3.81(openai@4.104.0(zod@3.25.76)) + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 10.0.0 + zod: 3.25.76 + zod-to-json-schema: 3.25.0(zod@3.25.76) + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + + '@langchain/google-genai@0.2.18(@langchain/core@0.3.79(openai@4.104.0(zod@3.25.76)))': + dependencies: + '@google/generative-ai': 0.24.1 + '@langchain/core': 0.3.79(openai@4.104.0(zod@3.25.76)) + uuid: 11.1.0 + + '@langchain/openai@0.0.25': + dependencies: + '@langchain/core': 0.1.63(openai@4.104.0(zod@3.25.76)) + js-tiktoken: 1.0.21 + openai: 4.104.0(zod@3.25.76) + zod: 3.25.76 + zod-to-json-schema: 3.25.0(zod@3.25.76) + transitivePeerDependencies: + - encoding + - ws + + '@sinclair/typebox@0.34.41': {} + + '@so-ric/colorspace@1.1.6': + dependencies: + color: 5.0.3 + text-hex: 1.0.0 + + '@types/adm-zip@0.5.7': + dependencies: + '@types/node': 24.10.1 + + '@types/bun@1.3.3': + dependencies: + bun-types: 1.3.3 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.2.0 + pretty-format: 30.2.0 + + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 24.10.1 + form-data: 4.0.5 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@types/node@24.10.1': + dependencies: + undici-types: 7.16.0 + + '@types/pg@8.15.6': + dependencies: + '@types/node': 24.10.1 + pg-protocol: 1.10.3 + pg-types: 2.2.0 + + '@types/retry@0.12.0': {} + + '@types/stack-utils@2.0.3': {} + + '@types/triple-beam@1.3.5': {} + + '@types/uuid@10.0.0': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + a-sync-waterfall@1.0.1: {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + acorn@7.4.1: {} + + adm-zip@0.5.16: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + asap@2.0.6: {} + + asciidoctor@3.0.4: + dependencies: + '@asciidoctor/cli': 4.0.0(@asciidoctor/core@3.0.4) + '@asciidoctor/core': 3.0.4 + ejs: 3.1.10 + handlebars: 4.7.8 + nunjucks: 3.2.4 + pug: 3.0.3 + transitivePeerDependencies: + - chokidar + + assert-never@1.4.0: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-walk@3.0.0-canary-5: + dependencies: + '@babel/types': 7.28.5 + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + binary-search@1.3.6: {} + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + bun-types@1.3.3: + dependencies: + '@types/node': 24.10.1 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + camelcase@6.3.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + character-parser@2.2.0: + dependencies: + is-regex: 1.2.1 + + ci-info@4.3.1: {} + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-convert@3.1.3: + dependencies: + color-name: 2.1.0 + + color-name@1.1.4: {} + + color-name@2.1.0: {} + + color-string@2.1.4: + dependencies: + color-name: 2.1.0 + + color@5.0.3: + dependencies: + color-convert: 3.1.3 + color-string: 2.1.4 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@5.1.0: {} + + console-table-printer@2.15.0: + dependencies: + simple-wcswidth: 1.1.2 + + constantinople@4.0.1: + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + + decamelize@1.2.0: {} + + delayed-stream@1.0.0: {} + + doctypes@1.1.0: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dotenv@16.6.1: {} + + downdoc@1.0.2-stable: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + emoji-regex@8.0.0: {} + + enabled@2.0.0: {} + + entities@4.5.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + escalade@3.2.0: {} + + escape-string-regexp@2.0.0: {} + + event-target-shim@5.0.1: {} + + eventemitter3@4.0.7: {} + + expect@30.2.0: + dependencies: + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 + + fecha@4.2.3: {} + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + fn.name@1.1.0: {} + + follow-redirects@1.15.11: {} + + form-data-encoder@1.7.2: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + fs.realpath@1.0.0: {} + + function-bind@1.1.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-any-array@2.0.1: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-expression@4.0.0: + dependencies: + acorn: 7.4.1 + object-assign: 4.1.1 + + is-fullwidth-code-point@3.0.0: {} + + is-number@7.0.0: {} + + is-promise@2.2.2: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-stream@2.0.1: {} + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 + + jest-diff@30.2.0: + dependencies: + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.2.0 + + jest-matcher-utils@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + jest-diff: 30.2.0 + pretty-format: 30.2.0 + + jest-message-util@30.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 30.2.0 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 30.2.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 24.10.1 + jest-util: 30.2.0 + + jest-regex-util@30.0.1: {} + + jest-util@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 24.10.1 + chalk: 4.1.2 + ci-info: 4.3.1 + graceful-fs: 4.2.11 + picomatch: 4.0.3 + + js-stringify@1.0.2: {} + + js-tiktoken@1.0.21: + dependencies: + base64-js: 1.5.1 + + js-tokens@4.0.0: {} + + jstransformer@1.0.0: + dependencies: + is-promise: 2.2.2 + promise: 7.3.1 + + kuler@2.0.0: {} + + langsmith@0.1.68(openai@4.104.0(zod@3.25.76)): + dependencies: + '@types/uuid': 10.0.0 + commander: 10.0.1 + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.7.3 + uuid: 10.0.0 + optionalDependencies: + openai: 4.104.0(zod@3.25.76) + + langsmith@0.3.81(openai@4.104.0(zod@3.25.76)): + dependencies: + '@types/uuid': 10.0.0 + chalk: 4.1.2 + console-table-printer: 2.15.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.7.3 + uuid: 10.0.0 + optionalDependencies: + openai: 4.104.0(zod@3.25.76) + + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + + lunr-languages@1.10.0: {} + + lunr@2.3.9: {} + + math-intrinsics@1.1.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + ml-array-mean@1.1.6: + dependencies: + ml-array-sum: 1.1.6 + + ml-array-sum@1.1.6: + dependencies: + is-any-array: 2.0.1 + + ml-distance-euclidean@2.0.0: {} + + ml-distance@4.0.1: + dependencies: + ml-array-mean: 1.1.6 + ml-distance-euclidean: 2.0.0 + ml-tree-similarity: 1.0.0 + + ml-tree-similarity@1.0.0: + dependencies: + binary-search: 1.3.6 + num-sort: 2.1.0 + + ms@2.1.3: {} + + mustache@4.2.0: {} + + neo-async@2.6.2: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + num-sort@2.1.0: {} + + nunjucks@3.2.4: + dependencies: + a-sync-waterfall: 1.0.1 + asap: 2.0.6 + commander: 5.1.0 + + object-assign@4.1.1: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + + openai@4.104.0(zod@3.25.76): + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + zod: 3.25.76 + transitivePeerDependencies: + - encoding + + p-finally@1.0.0: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + path-parse@1.0.7: {} + + pg-cloudflare@1.2.7: + optional: true + + pg-connection-string@2.9.1: {} + + pg-int8@1.0.1: {} + + pg-pool@3.10.1(pg@8.16.3): + dependencies: + pg: 8.16.3 + + pg-protocol@1.10.3: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg@8.16.3: + dependencies: + pg-connection-string: 2.9.1 + pg-pool: 3.10.1(pg@8.16.3) + pg-protocol: 1.10.3 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.2.7 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + postgres-array@2.0.0: {} + + postgres-bytea@1.0.0: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + prettier@3.6.2: {} + + pretty-format@30.2.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + promise@7.3.1: + dependencies: + asap: 2.0.6 + + proxy-from-env@1.1.0: {} + + pug-attrs@3.0.0: + dependencies: + constantinople: 4.0.1 + js-stringify: 1.0.2 + pug-runtime: 3.0.1 + + pug-code-gen@3.0.3: + dependencies: + constantinople: 4.0.1 + doctypes: 1.1.0 + js-stringify: 1.0.2 + pug-attrs: 3.0.0 + pug-error: 2.1.0 + pug-runtime: 3.0.1 + void-elements: 3.1.0 + with: 7.0.2 + + pug-error@2.1.0: {} + + pug-filters@4.0.0: + dependencies: + constantinople: 4.0.1 + jstransformer: 1.0.0 + pug-error: 2.1.0 + pug-walk: 2.0.0 + resolve: 1.22.11 + + pug-lexer@5.0.1: + dependencies: + character-parser: 2.2.0 + is-expression: 4.0.0 + pug-error: 2.1.0 + + pug-linker@4.0.0: + dependencies: + pug-error: 2.1.0 + pug-walk: 2.0.0 + + pug-load@3.0.0: + dependencies: + object-assign: 4.1.1 + pug-walk: 2.0.0 + + pug-parser@6.0.0: + dependencies: + pug-error: 2.1.0 + token-stream: 1.0.0 + + pug-runtime@3.0.1: {} + + pug-strip-comments@2.0.0: + dependencies: + pug-error: 2.1.0 + + pug-walk@2.0.0: {} + + pug@3.0.3: + dependencies: + pug-code-gen: 3.0.3 + pug-filters: 4.0.0 + pug-lexer: 5.0.1 + pug-linker: 4.0.0 + pug-load: 3.0.0 + pug-parser: 6.0.0 + pug-runtime: 3.0.1 + pug-strip-comments: 2.0.0 + + react-is@18.3.1: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + require-directory@2.1.1: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: {} + + semver@7.7.3: {} + + simple-wcswidth@1.1.2: {} + + slash@3.0.0: {} + + source-map@0.6.1: {} + + split2@4.2.0: {} + + stack-trace@0.0.10: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + text-hex@1.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + token-stream@1.0.0: {} + + tr46@0.0.3: {} + + triple-beam@1.4.1: {} + + typescript@5.9.3: {} + + uglify-js@3.19.3: + optional: true + + undici-types@5.26.5: {} + + undici-types@7.16.0: {} + + unxhr@1.2.0: {} + + util-deprecate@1.0.2: {} + + uuid@10.0.0: {} + + uuid@11.1.0: {} + + uuid@9.0.1: {} + + void-elements@3.1.0: {} + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.18.3: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.8 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + + with@7.0.2: + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + assert-never: 1.4.0 + babel-walk: 3.0.0-canary-5 + + wordwrap@1.0.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yargs-parser@21.1.1: {} + + yargs@17.3.1: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + zod-to-json-schema@3.25.0(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} diff --git a/ingesters/src/IngesterFactory.ts b/ingesters/src/IngesterFactory.ts index f3802c2..cdcf32b 100644 --- a/ingesters/src/IngesterFactory.ts +++ b/ingesters/src/IngesterFactory.ts @@ -9,6 +9,7 @@ import { CoreLibDocsIngester } from './ingesters/CoreLibDocsIngester'; import { ScarbDocsIngester } from './ingesters/ScarbDocsIngester'; import { StarknetJSIngester } from './ingesters/StarknetJSIngester'; import { StarknetBlogIngester } from './ingesters/StarknetBlogIngester'; +import { DojoDocsIngester } from './ingesters/DojoDocsIngester'; /** * Factory class for creating ingesters @@ -54,6 +55,9 @@ export class IngesterFactory { case 'starknet_blog': return new StarknetBlogIngester(); + case 'dojo_docs': + return new DojoDocsIngester(); + default: throw new Error(`Unsupported source: ${source}`); } diff --git a/ingesters/src/ingesters/CairoBookIngester.ts b/ingesters/src/ingesters/CairoBookIngester.ts index 5de9b9e..2a2e037 100644 --- a/ingesters/src/ingesters/CairoBookIngester.ts +++ b/ingesters/src/ingesters/CairoBookIngester.ts @@ -29,7 +29,7 @@ export class CairoBookIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'cairo-book', repoName: 'cairo-book', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://book.cairo-lang.org', diff --git a/ingesters/src/ingesters/CairoByExampleIngester.ts b/ingesters/src/ingesters/CairoByExampleIngester.ts index fe05534..204b3c5 100644 --- a/ingesters/src/ingesters/CairoByExampleIngester.ts +++ b/ingesters/src/ingesters/CairoByExampleIngester.ts @@ -17,7 +17,7 @@ export class CairoByExampleIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'enitrat', repoName: 'cairo-by-example', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://enitrat.github.io/cairo-by-example', diff --git a/ingesters/src/ingesters/CoreLibDocsIngester.ts b/ingesters/src/ingesters/CoreLibDocsIngester.ts index 648cfcd..aa27846 100644 --- a/ingesters/src/ingesters/CoreLibDocsIngester.ts +++ b/ingesters/src/ingesters/CoreLibDocsIngester.ts @@ -29,7 +29,7 @@ export class CoreLibDocsIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'enitrat', repoName: 'cairo-docs', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://docs.starknet.io/build/corelib/intro', diff --git a/ingesters/src/ingesters/DojoDocsIngester.ts b/ingesters/src/ingesters/DojoDocsIngester.ts new file mode 100644 index 0000000..06c664a --- /dev/null +++ b/ingesters/src/ingesters/DojoDocsIngester.ts @@ -0,0 +1,85 @@ +import { DocumentSource } from '../types'; +import type { BookConfig, BookPageDto } from '../utils/types'; +import { logger } from '../utils/logger'; +import { promisify } from 'util'; +import * as fs from 'fs/promises'; +import * as path from 'path'; +import { exec as execCallback } from 'child_process'; +import { MarkdownIngester } from './MarkdownIngester'; +import { processDocFiles } from '../utils/fileUtils'; + +/** + * Ingester for Dojo documentation + * + * This ingester downloads the Dojo Book repository and processes all markdown + * documentation files from the docs directory. + */ +export class DojoDocsIngester extends MarkdownIngester { + private static readonly BASE_URL = 'https://book.dojoengine.org'; + + constructor() { + const config: BookConfig = { + repoName: 'book', + repoOwner: 'dojoengine', + fileExtensions: ['.md', '.mdx'], + chunkSize: 4096, + chunkOverlap: 512, + baseUrl: DojoDocsIngester.BASE_URL, + urlSuffix: '', + useUrlMapping: true, + }; + super(config, DocumentSource.DOJO_DOCS); + } + + /** + * Get the directory path for extracting files + * + * @returns string - Path to the extract directory + */ + protected getExtractDir(): string { + const { getTempDir } = require('../utils/paths'); + return getTempDir('dojo-docs'); + } + + /** + * Download and extract the Dojo Book repository + * + * @returns Promise - Array of book pages + */ + protected override async downloadAndExtractDocs(): Promise { + const extractDir = this.getExtractDir(); + const repoUrl = `https://github.com/${this.config.repoOwner}/${this.config.repoName}.git`; + + logger.info(`Cloning Dojo Book repository from ${repoUrl}`); + + // Clone the repository + const exec = promisify(execCallback); + try { + await fs.rm(extractDir, { recursive: true, force: true }); + await exec(`git clone ${repoUrl} ${extractDir}`); + } catch (error) { + logger.error('Error cloning Dojo repository:', error); + throw new Error('Failed to clone Dojo repository'); + } + + logger.info('Dojo repository cloned successfully.'); + + // Process all markdown files from the docs directory + const docsDir = path.join(extractDir, 'docs'); + + logger.info(`Processing documentation files in ${docsDir}`); + const pages = await processDocFiles(this.config, docsDir); + + for (const page of pages) { + // Remove "pages/" prefix if present + page.name = page.name.replace(/^pages\//, ''); + + // Remove "/index" suffix if present + page.name = page.name.replace(/\/index$/, ''); + } + + logger.info(`Processed ${pages.length} documentation pages from Dojo Book`); + + return pages; + } +} diff --git a/ingesters/src/ingesters/OpenZeppelinDocsIngester.ts b/ingesters/src/ingesters/OpenZeppelinDocsIngester.ts index 75184f3..c45d998 100644 --- a/ingesters/src/ingesters/OpenZeppelinDocsIngester.ts +++ b/ingesters/src/ingesters/OpenZeppelinDocsIngester.ts @@ -2,7 +2,6 @@ import * as fsPromises from 'fs/promises'; import * as path from 'path'; import { Document } from '@langchain/core/documents'; import { type BookChunk, DocumentSource } from '../types'; -import { VectorStore } from '../db/postgresVectorStore'; import { type BookConfig, type BookPageDto } from '../utils/types'; import { logger } from '../utils/logger'; import { @@ -28,7 +27,7 @@ export class OpenZeppelinDocsIngester extends AsciiDocIngester { const config: BookConfig = { repoOwner: 'OpenZeppelin', repoName: 'cairo-contracts', - fileExtension: '.adoc', + fileExtensions: ['.adoc'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://docs.openzeppelin.com', @@ -75,7 +74,9 @@ export class OpenZeppelinDocsIngester extends AsciiDocIngester { await processDirectory(fullPath); } else if ( entry.isFile() && - path.extname(entry.name).toLowerCase() === config.fileExtension + config.fileExtensions.includes( + path.extname(entry.name).toLowerCase(), + ) ) { // Process AsciiDoc files const content = await fsPromises.readFile(fullPath, 'utf8'); @@ -83,11 +84,14 @@ export class OpenZeppelinDocsIngester extends AsciiDocIngester { // Get the relative path of the file from the base directory - which reflects the online website directory structure const relativePath = path.relative(directory, fullPath); + // Get the file extension to remove it from the final page name + const fileExtension = path.extname(entry.name).toLowerCase(); + // Inject cairo-contracts/2.0.0 in the fullPath to reflect online website directory structure // This is the special handling for OpenZeppelin docs const adaptedFullPageName = path .join('contracts-cairo', OZ_DOCS_VERSION, relativePath) - .replace(config.fileExtension, ''); + .replace(fileExtension, ''); pages.push({ name: adaptedFullPageName, diff --git a/ingesters/src/ingesters/ScarbDocsIngester.ts b/ingesters/src/ingesters/ScarbDocsIngester.ts index c6a1092..a3f63a5 100644 --- a/ingesters/src/ingesters/ScarbDocsIngester.ts +++ b/ingesters/src/ingesters/ScarbDocsIngester.ts @@ -23,7 +23,7 @@ export class ScarbDocsIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'software-mansion', repoName: 'scarb', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://docs.swmansion.com/scarb/docs', diff --git a/ingesters/src/ingesters/StarknetBlogIngester.ts b/ingesters/src/ingesters/StarknetBlogIngester.ts index 3c2dc7e..d5671d2 100644 --- a/ingesters/src/ingesters/StarknetBlogIngester.ts +++ b/ingesters/src/ingesters/StarknetBlogIngester.ts @@ -30,7 +30,7 @@ export class StarknetBlogIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'starknet', repoName: 'starknet-blog', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://www.starknet.io/blog', diff --git a/ingesters/src/ingesters/StarknetDocsIngester.ts b/ingesters/src/ingesters/StarknetDocsIngester.ts index 96ae654..5779eb9 100644 --- a/ingesters/src/ingesters/StarknetDocsIngester.ts +++ b/ingesters/src/ingesters/StarknetDocsIngester.ts @@ -33,7 +33,7 @@ export class StarknetDocsIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'starknet-io', repoName: 'starknet-docs', - fileExtension: '.mdx', + fileExtensions: ['.mdx'], chunkSize: 4096, chunkOverlap: 512, baseUrl: StarknetDocsIngester.BASE_URL, @@ -119,7 +119,9 @@ export class StarknetDocsIngester extends MarkdownIngester { await processDirectory(fullPath); } else if ( entry.isFile() && - path.extname(entry.name).toLowerCase() === this.config.fileExtension + this.config.fileExtensions.includes( + path.extname(entry.name).toLowerCase(), + ) ) { // Process MDX files const content = await fs.readFile(fullPath, 'utf8'); diff --git a/ingesters/src/ingesters/StarknetFoundryIngester.ts b/ingesters/src/ingesters/StarknetFoundryIngester.ts index 0370a7a..8976346 100644 --- a/ingesters/src/ingesters/StarknetFoundryIngester.ts +++ b/ingesters/src/ingesters/StarknetFoundryIngester.ts @@ -27,7 +27,7 @@ export class StarknetFoundryIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'foundry-rs', repoName: 'starknet-foundry', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://foundry-rs.github.io/starknet-foundry', diff --git a/ingesters/src/ingesters/StarknetJSIngester.ts b/ingesters/src/ingesters/StarknetJSIngester.ts index 2f1ea79..1f89b88 100644 --- a/ingesters/src/ingesters/StarknetJSIngester.ts +++ b/ingesters/src/ingesters/StarknetJSIngester.ts @@ -18,7 +18,7 @@ export class StarknetJSIngester extends MarkdownIngester { const config: BookConfig = { repoOwner: 'starknet-io', repoName: 'starknet.js', - fileExtension: '.md', + fileExtensions: ['.md'], chunkSize: 4096, chunkOverlap: 512, baseUrl: 'https://starknetjs.com/docs/next/guides', diff --git a/ingesters/src/shared.ts b/ingesters/src/shared.ts index adbd446..e092933 100644 --- a/ingesters/src/shared.ts +++ b/ingesters/src/shared.ts @@ -10,7 +10,7 @@ export interface BookPageDto { export type BookConfig = { repoOwner: string; repoName: string; - fileExtension: string; + fileExtensions: string; chunkSize: number; chunkOverlap: number; }; diff --git a/ingesters/src/types/index.ts b/ingesters/src/types/index.ts index b3f36e6..016e5aa 100644 --- a/ingesters/src/types/index.ts +++ b/ingesters/src/types/index.ts @@ -17,6 +17,7 @@ export enum DocumentSource { SCARB_DOCS = 'scarb_docs', STARKNET_JS = 'starknet_js', STARKNET_BLOG = 'starknet_blog', + DOJO_DOCS = 'dojo_docs', } export type BookChunk = { diff --git a/ingesters/src/utils/fileUtils.ts b/ingesters/src/utils/fileUtils.ts index 478eb3b..0bbc70e 100644 --- a/ingesters/src/utils/fileUtils.ts +++ b/ingesters/src/utils/fileUtils.ts @@ -30,19 +30,24 @@ export async function processDocFiles( if (entry.isDirectory()) { // Recursively process subdirectories await processDirectory(fullPath); - } else if ( - entry.isFile() && - path.extname(entry.name).toLowerCase() === config.fileExtension - ) { - // Process documentation files - const content = await fs.readFile(fullPath, 'utf8'); + } else if (entry.isFile()) { + // Check if the file matches any of the configured extensions + const fileExt = path.extname(entry.name).toLowerCase(); + if (config.fileExtensions.includes(fileExt)) { + // Process documentation files + const content = await fs.readFile(fullPath, 'utf8'); - pages.push({ - name: path - .relative(directory, fullPath) - .replace(config.fileExtension, ''), - content, - }); + // Skip empty files + if (content.trim().length === 0) { + logger.warn(`Skipping empty file: ${fullPath}`); + continue; + } + + pages.push({ + name: path.relative(directory, fullPath).replace(fileExt, ''), + content, + }); + } } } } diff --git a/ingesters/src/utils/types.ts b/ingesters/src/utils/types.ts index d99fefc..aac27a4 100644 --- a/ingesters/src/utils/types.ts +++ b/ingesters/src/utils/types.ts @@ -31,7 +31,7 @@ export type BookConfig = { repoName: string; /** The file extension of the documentation files */ - fileExtension: string; + fileExtensions: Array; /** The size of each chunk in characters */ chunkSize: number; diff --git a/python/optimizers/datasets/dojo_dataset.json b/python/optimizers/datasets/dojo_dataset.json new file mode 100644 index 0000000..c9ed47f --- /dev/null +++ b/python/optimizers/datasets/dojo_dataset.json @@ -0,0 +1,79 @@ +{ + "examples": [ + { + "query": "Write a simple example of Dojo frontend bindings with wallet integration", + "chat_history": [], + "mcp_mode": false + }, + { + "query": "How does DojoProvider execute transactions with an account? Does it use the account's provider or the dojoConfig RPC URL?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I upgrade a Dojo contract that's already deployed when the class hash has changed? The contract code was updated but migration fails with class hash mismatch.", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I upgrade a Dojo contract when sozo migrate fails with class hash mismatch? The contract code was updated but the class is already declared on-chain.\n\nCode snippets for context:\nsozo migrate fails with class hash mismatch", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I configure the writers section in dojo.toml for a system contract? What should the tag be - namespace::contract_name or just contract_name?\n\nCode snippets for context:\n[writers]\n\"clickergame\" = [\"gg-clicker\"]", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I handle class hash mismatch errors when deploying Dojo contracts? The error says \"Mismatch compiled class hash\" - should I modify the code or is there a flag to skip declaration?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I resolve \"Mismatch compiled class hash\" errors when deploying Dojo contracts? The classes seem to be already declared on-chain with different compiled class hashes. Can I skip declaration or force new class hashes?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How can I manually register already-declared contract classes to a Dojo world? The classes are already declared on-chain but sozo migration fails due to compiled class hash mismatch. Can I use sozo or sncast to register existing class declarations to the world?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "How do I set up an account for Dojo sozo migrate on devnet/katana? The account doesn't exist error keeps appearing. What's the correct way to create and configure an account for devnet deployment?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "Compiling dojo_macros v1.7.0-alpha.2 (git+https://github.com/dojoengine/dojo?tag=v1.7.0-alpha.2#a064752fff355f325cf0b00828d236b399333432)\n Finished `release` profile [optimized] target(s) in 0.16s\n Compiling ponzi_land v1.4.0 (/Users/gianfranco/PonziLand/contracts/Scarb.toml)\nwarn[E0001]: Unused variable. Consider ignoring by prefixing with `_`.\n --> /Users/gianfranco/PonziLand/contracts/src/systems/actions.cairo:807:17\n let nuked_land_owner = land.owner;\n ^^^^^^^^^^^^^^^^\n\nwarn: Usage of deprecated feature `\"deprecated-starknet-consts\"` with no `#[feature(\"deprecated-starknet-consts\")]` attribute. Note: \"Use `TryInto::try_into` in const context instead.\"\n --> /Users/gianfranco/PonziLand/contracts/src/interfaces/systems.cairo:17:42\n Option::None => { (starknet::contract_address_const::<0x0>()) },\n ^^^^^^^^^^^^^^^^^^^^^^\n\nwarn: Usage of deprecated feature `\"deprecated-starknet-consts\"` with no `#[feature(\"deprecated-starknet-consts\")]` attribute. Note: \"Use `TryInto::try_into` in const context instead.\"\n --> /Users/gianfranco/PonziLand/contracts/src/models/land.cairo:6:33\nuse starknet::{ContractAddress, contract_address_const};\n ^^^^^^^^^^^^^^^^^^^^^^\n\nwarn: Usage of deprecated feature `\"starknet-storage-deprecation\"` with no `#[feature(\"starknet-storage-deprecation\")]` attribute. Note: \"Use `starknet::storage::MutableVecTrait::push` or `starknet::storage::MutableVecTrait::allocate` instead.\"\n --> /Users/gianfranco/PonziLand/contracts/src/components/auction.cairo:171:64\n self.used_lands_in_circle.entry((circle, section)).append().write(random_index);\n ^^^^^^\n\nwarn: Plugin diagnostic: Missing `ValidStorageTypeTrait` for member type. Inference failed with: `Trait has no implementation in context: core::starknet::storage::ValidStorageTypeTrait::>.`. Possible solutions: implement `Store`, mark type with `#[storage_node]`, or use valid args for `Vec` or `Map` library types. To suppress this warning, use `#[allow(starknet::invalid_storage_member_types)]`.\n --> /Users/gianfranco/PonziLand/contracts/src/components/taxes.cairo:73:19\n tax_edge: Map<(u16, u16), TaxEdge>,\n ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0002]: Method `read` could not be called on type `core::starknet::storage::storage_base::StorageBase::>`.\nCandidate `core::starknet::storage::map::StorageMapReadAccess::read` inference failed with: Trait has no implementation in context: core::starknet::storage::map::StorageMapReadAccess::>>.\nCandidate `core::starknet::storage::StoragePointerReadAccess::read` inference failed with: Trait has no implementation in context: core::starknet::storage::StoragePointerReadAccess::>>.\nCandidate `core::starknet::storage::map::StorageMapReadAccess::read` inference failed with: Trait has no implementation in context: core::starknet::storage::map::StorageMapReadAccess::>>.\nCandidate `core::starknet::storage::StoragePointerReadAccess::read` inference failed with: Trait has no implementation in context: core::starknet::storage::StoragePointerReadAccess::>>.\n --> /Users/gianfranco/PonziLand/contracts/src/components/taxes.cairo:131:27\n self.tax_edge.read((payer_location, claimer_location))\n ^^^^\n\nerror[E0002]: Method `write` could not be called on type `core::starknet::storage::storage_base::StorageBase::>>`.\nCandidate `core::starknet::storage::map::StorageMapWriteAccess::write` inference failed with: Trait has no implementation in context: core::starknet::storage::map::StorageMapWriteAccess::>>>.\nCandidate `core::starknet::storage::StoragePointerWriteAccess::write` inference failed with: Trait has no implementation in context: core::starknet::storage::StoragePointerWriteAccess::>>>.\nCandidate `core::starknet::storage::map::StorageMapWriteAccess::write` inference failed with: Trait has no implementation in context: core::starknet::storage::map::StorageMapWriteAccess::>>>.\nCandidate `core::starknet::storage::StoragePointerWriteAccess::write` inference failed with: Trait has no implementation in context: core::starknet::storage::StoragePointerWriteAccess::>>>.\n --> /Users/gianfranco/PonziLand/contracts/src/components/taxes.cairo:143:27\n self.tax_edge.write((payer_location, claimer_location), edge);\n ^^^^^\n\nerror: could not compile `ponzi_land` due to previous error\nerror: Scarb command failed with exit code: exit status: 1\ngianfranco@gianfrancos-MacBook-Air contracts % \n", + "chat_history": [], + "mcp_mode": false + }, + { + "query": "What are the best practices for creating template examples for Dojo models and systems? How should I structure template code with clear examples?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "What Dojo version tag is compatible with Scarb 2.9.1 and Cairo 2.9.1? I need the correct git tag for Scarb.toml dependencies.", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "As a Starknet ecosystem expert, answer the following question about Starknet concepts, or general knowledge:\n\nWhat are best practices for keeping Dojo runtime namespaces and selector strings consistent between deployed worlds and client/session configurations in Starknet apps?", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "What are the correct patterns for Dojo ECS models, systems, and entity deletion? Specifically: 1) How to properly define Dojo models with #[dojo::model], 2) How to use get! and set! macros correctly, 3) How to delete entities in Dojo, 4) How to handle Option types in Cairo, 5) Correct syntax for arrays and spans in Cairo", + "chat_history": [], + "mcp_mode": true + }, + { + "query": "In Dojo framework, how do you delete entities/models? What is the correct syntax? Does Dojo have a delete! macro like set! and get!? Also, what is the correct way to handle for loops and while loops in Cairo - can you use mutable loop variables with let mut inside loops?", + "chat_history": [], + "mcp_mode": true + } + ] +} diff --git a/python/optimizers/results/optimized_retrieval_program.json b/python/optimizers/results/optimized_retrieval_program.json index ee58a8d..27cfe93 100644 --- a/python/optimizers/results/optimized_retrieval_program.json +++ b/python/optimizers/results/optimized_retrieval_program.json @@ -3,7 +3,7 @@ "train": [], "demos": [], "signature": { - "instructions": "You are an assistant specialized in analyzing queries related to the Cairo programming language, Starknet blockchain protocol, and associated tools including development environments, testing frameworks, and standard libraries like OpenZeppelin for Cairo. Your core task is to process a given query (and optional chat history) to determine if it pertains to Cairo/Starknet topics. Relevant topics include: contract development and lifecycle (e.g., declaration via DECLARE transaction to submit contract classes and generate class hash; deployment via DEPLOY to instantiate contracts on-chain; invocation via INVOKE to interact with external functions; account deployment via DEPLOY_ACCOUNT for account contracts); transaction types and protocol aspects; data structures (e.g., 1D arrays, spans, fixed-size arrays from corelib; Cairo supports basic arrays via corelib, but 2D or nested arrays like Array> are not explicitly covered in standard docs and may require searching for collections or practical examples); type conversions (e.g., ContractAddress is a felt252-based type convertible to u256 via TryInto or Into traits, as felt252 fits within u256; general scalar conversions like felt252 to u256); token operations in contracts (e.g., ERC20-like transfers, debits via transfer_from with approvals, charges potentially via minting, though implementations draw from standard patterns without external libs; for ERC1155 tokens, include minting with acceptance checks, URI setting, and role-based access like MINTER_ROLE, DEFAULT_ADMIN_ROLE using OpenZeppelin patterns); access control and roles (e.g., granting roles like MINTER_ROLE, URI_SETTER_ROLE, UPGRADER_ROLE in constructors; asserting roles in functions like mint_to_winner or role_provision); account abstraction features (e.g., session keys for authentication in smart contracts, often implemented in OpenZeppelin account contracts); testing with frameworks (e.g., snforge from Starknet-foundry for security-focused test cases, modular setups with reusable deployment and role assignment helpers, role encoding, error handling for assertion failures, unauthorized access, successful minting/role provisioning); project setup and tooling (e.g., initializing projects with Scarb for Cairo contract structure, environment setup for Starknet development); and related ecosystem elements like fees, accounts, corelib traits (e.g., integer conversions, array construction), and standard implementations (e.g., OpenZeppelin Cairo contracts for ERC20/ERC1155 traits, access control initialization and granting).\n\nStarknet contract lifecycle typically includes declaration, deployment, invocation, and account deployment, but does not involve steps like IPFS publishing. Focus on factual domain elements: Cairo language basics (syntax, data structures, traits), Starknet protocol (transactions, addresses, fees), practical examples (e.g., code snippets for session key authentication, ERC1155 minting with data spans, role provisioning), testing practices (e.g., snforge test cases for access control enforcement, edge conditions like invalid roles or amounts; use modular coding with setup functions for contract deployment, role assignment, and helpers for address management/role encoding; include demos for role assertion failures, successful operations, unauthorized attempts), project initialization (e.g., Scarb commands for new projects, dependency management for OpenZeppelin or corelib). If the query is unrelated (e.g., general OS troubleshooting like WSL networking issues, non-Cairo programming, or meta-questions like \"What can you do?\" without Cairo/Starknet context), do not generate search queries or resources—instead, output empty lists and include a brief note in the analysis section stating it's off-topic and unrelated to Cairo/Starknet.\n\nFor relevant Cairo/Starknet queries, follow this process:\n1. Analyze the query: Break it down into 1-2 sentences summarizing key components (e.g., specific concepts like transaction types, steps in contract lifecycle, functions, errors, data structures, testing scenarios, or project setup). Identify why the query fits the domain (e.g., involves Starknet transactions, Cairo type conversions, OpenZeppelin ERC1155 testing with snforge, session key implementations in account contracts, or Scarb project initialization). Note how selected resources logically cover the topics (e.g., 'starknet_docs' for protocol-level transactions like DECLARE/DEPLOY; 'cairo_book' and 'corelib_docs' for language features like arrays or conversions; 'cairo_by_example' for practical code snippets; 'openzeppelin_docs' for ERC1155/ERC20 trait implementations, access control roles (e.g., MINTER_ROLE granting, mint_with_acceptance_check), and standard contract patterns; 'starknet_foundry' for snforge testing basics including modular setups, role helpers, and security test cases like assertion failures or unauthorized access; 'scarb_docs' for project initialization, Cairo structure, and tooling). Highlight any limitations, such as lack of direct ERC20/ERC1155 implementations in core resources (focus on OpenZeppelin patterns instead) or need for targeted searches on nested arrays/session keys.\n2. Extract search terms: Generate exactly 4-8 precise, targeted search queries in English (even if the original query is in another language). Prioritize specificity to retrieve relevant documentation sections—combine \"Cairo\" or \"Starknet\" with core query elements (e.g., for contract lifecycle: \"Starknet contract lifecycle\", \"Starknet declare transaction class hash\", \"Starknet deploy transaction steps\", \"Starknet invoke external function\"; for arrays: \"Cairo array construction corelib\", \"Cairo nested arrays examples\", \"Cairo array of arrays\", \"Cairo multidimensional arrays collections\"; for type conversions: \"Cairo ContractAddress to u256 TryInto\", \"Starknet ContractAddress into felt252\", \"Cairo felt252 to u256 conversion example\", \"Corelib u256 from ContractAddress\"; for token operations: \"OpenZeppelin Cairo ERC1155 mint example\", \"Starknet ERC1155 transfer from with approval\", \"Cairo ERC20 approve and transfer_from pattern\", \"OpenZeppelin access control role granting\"; for session keys: \"Starknet OpenZeppelin account session key implementation\", \"Cairo session key authentication contract example\", \"Starknet account abstraction session keys\"; for testing: \"snforge ERC1155 testing OpenZeppelin\", \"snforge access control role assertion failures\", \"Starknet-foundry modular test setup for roles\", \"snforge unauthorized mint access test\"; for project setup: \"Scarb Starknet project initialization\", \"Cairo project structure with Scarb\", \"Starknet development environment setup\"). Avoid broad or generic terms; aim for combinations that probe exact doc sections or examples (e.g., target traits like TryInto/Into, corelib details, protocol flows, OpenZeppelin role constants like DEFAULT_ADMIN_ROLE/MINTER_ROLE, snforge syntax for deployment helpers/error handling). If the query involves syntax, examples, or testing, include \"example\", \"implementation\", \"test\", or \"snforge\" in queries to fetch from 'cairo_by_example', 'openzeppelin_docs', or 'starknet_foundry'.\n3. Identify relevant documentation sources: Select only from this expanded predefined list: ['cairo_book' (Cairo language basics, including data structures like arrays and scalar types), 'starknet_docs' (protocol aspects like transactions, deployment lifecycle, addresses, and fees), 'cairo_by_example' (practical code examples for features like conversions, arrays, contract interactions, or session keys), 'corelib_docs' (standard library details, e.g., array types, traits like TryInto/Into for conversions, collections), 'openzeppelin_docs' (Starknet Cairo implementations for ERC20/ERC1155 tokens, access control with roles like MINTER_ROLE/DEFAULT_ADMIN_ROLE, account contracts including session key patterns, minting with data/acceptance checks, URI setters, upgraders), 'starknet_foundry' (snforge testing framework for Starknet contracts, including security test cases for access control, modular setups with reusable functions for deployment/role assignment, helpers for role encoding/address management, examples of assertion failures, successful minting/provisioning, unauthorized attempts, error handling), 'scarb_docs' (project management tool for Cairo/Starknet, initialization commands, dependency handling for OpenZeppelin/corelib, contract structure and environment setup), 'starknet_js' (StarknetJS library for front-end interactions, contract calls and transactions, deployment, JavaScript/TypeScript integration), 'starknet_blog' (latest Starknet updates, announcements, feature releases, ecosystem developments, integration guides, community updates, recent innovations, new tools, partnerships, protocol enhancements)]. Choose 1-4 resources that directly cover the query's topics—e.g., 'starknet_docs' and 'openzeppelin_docs' for transaction types, ERC1155 lifecycle, and role-based functions; 'corelib_docs', 'cairo_book', and 'openzeppelin_docs' for type conversions or token patterns; 'cairo_by_example' and 'starknet_foundry' for testing snippets or session key examples; 'scarb_docs' and 'cairo_book' for project setup; 'starknet_blog' for recent ecosystem updates or new features, starknet apps and protocols. Prioritize 'openzeppelin_docs' for standard contract traits/testing patterns, 'starknet_foundry' for snforge-specific testing (e.g., ERC1155 access control), and 'scarb_docs' for initialization. Do not include or invent any other resources (e.g., no external web guides or general libs beyond this list). If no resources fit perfectly, select the closest matches or use an empty list only for off-topic queries.\n\nGeneral strategy: Infer answers from core resources where possible (e.g., ContractAddress to u256 via felt252 wrapping and TryInto trait in corelib_docs/openzeppelin_docs; basic array support in cairo_book but probe for nesting via examples in cairo_by_example; ERC1155 minting/role assertion in openzeppelin_docs; snforge modular tests with helpers for roles in starknet_foundry; session keys via account abstraction in openzeppelin_docs/starknet_docs; Scarb init for projects in scarb_docs). For token-related or testing queries, target OpenZeppelin patterns (e.g., constructor role granting, mint_to_winner logic with assert_only_role) and snforge specifics (e.g., reusable setup for deployment, compact comments in tests). Ensure searches enable retrieving context like trait implementations (e.g., GameERC1155Impl), code snippets (e.g., role_provision granting arbitrary roles), protocol steps, or testing demos to support full query resolution, including edge cases like invalid inputs or access denials.\n\nProcess inputs in this format:\n- ### query: The main user query string (may be a complex prompt with sections like , <context>, <objective>, <requirements>, <deliverable> for tasks like generating test cases or examples).\n- ### chat_history: Optional prior conversation (e.g., \"None\" or a string of history); incorporate if it provides Cairo/Starknet context, but prioritize the current query.\n\nOutput strictly in the following structured format, with no code, no additional explanations, no deviations, and no references to this instruction. Keep the analysis to 1-2 sentences. For off-topic queries, include a brief note under ### query_analysis explaining the irrelevance (e.g., \"This query is unrelated to Cairo or Starknet topics.\").\n\n### query_analysis\n[1-2 sentences summarizing the query breakdown (including chat_history if relevant), key components, domain fit, resource selection rationale, and how search queries target specific doc sections (e.g., transaction types, array examples, conversion traits, ERC1155 testing with snforge, session key implementations, or Scarb setup). For off-topic: Brief note on irrelevance.]\n\n### search_queries\n['query1', 'query2', ..., ] # Exactly 4-8 strings for relevant; empty list [] if off-topic\n\n### resources\n['resource1', 'resource2', ...] # 1-4 from predefined list for relevant; empty list [] if off-topic", + "instructions": "You are an assistant specialized in analyzing queries related to the Cairo programming language, Starknet blockchain protocol, and associated tools including development environments, testing frameworks, and standard libraries like OpenZeppelin for Cairo. Your core task is to process a given query (and optional chat history) to determine if it pertains to Cairo/Starknet topics. Relevant topics include: contract development and lifecycle (e.g., declaration via DECLARE transaction to submit contract classes and generate class hash; deployment via DEPLOY to instantiate contracts on-chain; invocation via INVOKE to interact with external functions; account deployment via DEPLOY_ACCOUNT for account contracts); transaction types and protocol aspects; data structures (e.g., 1D arrays, spans, fixed-size arrays from corelib; Cairo supports basic arrays via corelib, but 2D or nested arrays like Array<Array<T>> are not explicitly covered in standard docs and may require searching for collections or practical examples); type conversions (e.g., ContractAddress is a felt252-based type convertible to u256 via TryInto or Into traits, as felt252 fits within u256; general scalar conversions like felt252 to u256); token operations in contracts (e.g., ERC20-like transfers, debits via transfer_from with approvals, charges potentially via minting, though implementations draw from standard patterns without external libs; for ERC1155 tokens, include minting with acceptance checks, URI setting, and role-based access like MINTER_ROLE, DEFAULT_ADMIN_ROLE using OpenZeppelin patterns); access control and roles (e.g., granting roles like MINTER_ROLE, URI_SETTER_ROLE, UPGRADER_ROLE in constructors; asserting roles in functions like mint_to_winner or role_provision); account abstraction features (e.g., session keys for authentication in smart contracts, often implemented in OpenZeppelin account contracts); testing with frameworks (e.g., snforge from Starknet-foundry for security-focused test cases, modular setups with reusable deployment and role assignment helpers, role encoding, error handling for assertion failures, unauthorized access, successful minting/role provisioning); project setup and tooling (e.g., initializing projects with Scarb for Cairo contract structure, environment setup for Starknet development); and related ecosystem elements like fees, accounts, corelib traits (e.g., integer conversions, array construction), and standard implementations (e.g., OpenZeppelin Cairo contracts for ERC20/ERC1155 traits, access control initialization and granting).\n\nStarknet contract lifecycle typically includes declaration, deployment, invocation, and account deployment, but does not involve steps like IPFS publishing. Focus on factual domain elements: Cairo language basics (syntax, data structures, traits), Starknet protocol (transactions, addresses, fees), practical examples (e.g., code snippets for session key authentication, ERC1155 minting with data spans, role provisioning), testing practices (e.g., snforge test cases for access control enforcement, edge conditions like invalid roles or amounts; use modular coding with setup functions for contract deployment, role assignment, and helpers for address management/role encoding; include demos for role assertion failures, successful operations, unauthorized attempts), project initialization (e.g., Scarb commands for new projects, dependency management for OpenZeppelin or corelib). If the query is unrelated (e.g., general OS troubleshooting like WSL networking issues, non-Cairo programming, or meta-questions like \"What can you do?\" without Cairo/Starknet context), do not generate search queries or resources—instead, output empty lists and include a brief note in the analysis section stating it's off-topic and unrelated to Cairo/Starknet.\n\nFor relevant Cairo/Starknet queries, follow this process:\n1. Analyze the query: Break it down into 1-2 sentences summarizing key components (e.g., specific concepts like transaction types, steps in contract lifecycle, functions, errors, data structures, testing scenarios, or project setup). Identify why the query fits the domain (e.g., involves Starknet transactions, Cairo type conversions, OpenZeppelin ERC1155 testing with snforge, session key implementations in account contracts, or Scarb project initialization). Note how selected resources logically cover the topics (e.g., 'starknet_docs' for protocol-level transactions like DECLARE/DEPLOY; 'cairo_book' and 'corelib_docs' for language features like arrays or conversions; 'cairo_by_example' for practical code snippets; 'openzeppelin_docs' for ERC1155/ERC20 trait implementations, access control roles (e.g., MINTER_ROLE granting, mint_with_acceptance_check), and standard contract patterns; 'starknet_foundry' for snforge testing basics including modular setups, role helpers, and security test cases like assertion failures or unauthorized access; 'scarb_docs' for project initialization, Cairo structure, and tooling). Highlight any limitations, such as lack of direct ERC20/ERC1155 implementations in core resources (focus on OpenZeppelin patterns instead) or need for targeted searches on nested arrays/session keys.\n2. Extract search terms: Generate exactly 4-8 precise, targeted search queries in English (even if the original query is in another language). Prioritize specificity to retrieve relevant documentation sections—combine \"Cairo\" or \"Starknet\" with core query elements (e.g., for contract lifecycle: \"Starknet contract lifecycle\", \"Starknet declare transaction class hash\", \"Starknet deploy transaction steps\", \"Starknet invoke external function\"; for arrays: \"Cairo array construction corelib\", \"Cairo nested arrays examples\", \"Cairo array of arrays\", \"Cairo multidimensional arrays collections\"; for type conversions: \"Cairo ContractAddress to u256 TryInto\", \"Starknet ContractAddress into felt252\", \"Cairo felt252 to u256 conversion example\", \"Corelib u256 from ContractAddress\"; for token operations: \"OpenZeppelin Cairo ERC1155 mint example\", \"Starknet ERC1155 transfer from with approval\", \"Cairo ERC20 approve and transfer_from pattern\", \"OpenZeppelin access control role granting\"; for session keys: \"Starknet OpenZeppelin account session key implementation\", \"Cairo session key authentication contract example\", \"Starknet account abstraction session keys\"; for testing: \"snforge ERC1155 testing OpenZeppelin\", \"snforge access control role assertion failures\", \"Starknet-foundry modular test setup for roles\", \"snforge unauthorized mint access test\"; for project setup: \"Scarb Starknet project initialization\", \"Cairo project structure with Scarb\", \"Starknet development environment setup\"). Avoid broad or generic terms; aim for combinations that probe exact doc sections or examples (e.g., target traits like TryInto/Into, corelib details, protocol flows, OpenZeppelin role constants like DEFAULT_ADMIN_ROLE/MINTER_ROLE, snforge syntax for deployment helpers/error handling). If the query involves syntax, examples, or testing, include \"example\", \"implementation\", \"test\", or \"snforge\" in queries to fetch from 'cairo_by_example', 'openzeppelin_docs', or 'starknet_foundry'.\n3. Identify relevant documentation sources: Select only from this expanded predefined list: ['cairo_book' (Cairo language basics, including data structures like arrays and scalar types), 'starknet_docs' (protocol aspects like transactions, deployment lifecycle, addresses, and fees), 'cairo_by_example' (practical code examples for features like conversions, arrays, contract interactions, or session keys), 'corelib_docs' (standard library details, e.g., array types, traits like TryInto/Into for conversions, collections), 'openzeppelin_docs' (Starknet Cairo implementations for ERC20/ERC1155 tokens, access control with roles like MINTER_ROLE/DEFAULT_ADMIN_ROLE, account contracts including session key patterns, minting with data/acceptance checks, URI setters, upgraders), 'starknet_foundry' (snforge testing framework for Starknet contracts, including security test cases for access control, modular setups with reusable functions for deployment/role assignment, helpers for role encoding/address management, examples of assertion failures, successful minting/provisioning, unauthorized attempts, error handling), 'scarb_docs' (project management tool for Cairo/Starknet, initialization commands, dependency handling for OpenZeppelin/corelib, contract structure and environment setup), 'starknet_js' (StarknetJS library for front-end interactions, contract calls and transactions, deployment, JavaScript/TypeScript integration), 'starknet_blog' (latest Starknet updates, announcements, feature releases, ecosystem developments, integration guides, community updates, recent innovations, new tools, partnerships, protocol enhancements), 'dojo_docs' (Dojo framework for building onchain games and autonomous worlds on Starknet, including ECS patterns, world contracts, models, systems, events, Torii indexing with GraphQL API and real-time state synchronization, SDKs for TypeScript/JavaScript, Rust, C, Unity, Godot, Telegram bots, Unreal Engine, Sozo CLI tool, Katana devnet, game development patterns)]. Choose 1-4 resources that directly cover the query's topics—e.g., 'starknet_docs' and 'openzeppelin_docs' for transaction types, ERC1155 lifecycle, and role-based functions; 'corelib_docs', 'cairo_book', and 'openzeppelin_docs' for type conversions or token patterns; 'cairo_by_example' and 'starknet_foundry' for testing snippets or session key examples; 'scarb_docs' and 'cairo_book' for project setup; 'starknet_blog' for recent ecosystem updates or new features, starknet apps and protocols; 'dojo_docs' for onchain game development, ECS architecture, Torii indexing, or game-specific SDKs and tooling. Prioritize 'openzeppelin_docs' for standard contract traits/testing patterns, 'starknet_foundry' for snforge-specific testing (e.g., ERC1155 access control), 'scarb_docs' for initialization, and 'dojo_docs' for game development frameworks. Do not include or invent any other resources (e.g., no external web guides or general libs beyond this list). If no resources fit perfectly, select the closest matches or use an empty list only for off-topic queries.\n\nGeneral strategy: Infer answers from core resources where possible (e.g., ContractAddress to u256 via felt252 wrapping and TryInto trait in corelib_docs/openzeppelin_docs; basic array support in cairo_book but probe for nesting via examples in cairo_by_example; ERC1155 minting/role assertion in openzeppelin_docs; snforge modular tests with helpers for roles in starknet_foundry; session keys via account abstraction in openzeppelin_docs/starknet_docs; Scarb init for projects in scarb_docs). For token-related or testing queries, target OpenZeppelin patterns (e.g., constructor role granting, mint_to_winner logic with assert_only_role) and snforge specifics (e.g., reusable setup for deployment, compact comments in tests). Ensure searches enable retrieving context like trait implementations (e.g., GameERC1155Impl), code snippets (e.g., role_provision granting arbitrary roles), protocol steps, or testing demos to support full query resolution, including edge cases like invalid inputs or access denials.\n\nProcess inputs in this format:\n- ### query: The main user query string (may be a complex prompt with sections like <title>, <context>, <objective>, <requirements>, <deliverable> for tasks like generating test cases or examples).\n- ### chat_history: Optional prior conversation (e.g., \"None\" or a string of history); incorporate if it provides Cairo/Starknet context, but prioritize the current query.\n\nOutput strictly in the following structured format, with no code, no additional explanations, no deviations, and no references to this instruction. Keep the analysis to 1-2 sentences. For off-topic queries, include a brief note under ### query_analysis explaining the irrelevance (e.g., \"This query is unrelated to Cairo or Starknet topics.\").\n\n### query_analysis\n[1-2 sentences summarizing the query breakdown (including chat_history if relevant), key components, domain fit, resource selection rationale, and how search queries target specific doc sections (e.g., transaction types, array examples, conversion traits, ERC1155 testing with snforge, session key implementations, or Scarb setup). For off-topic: Brief note on irrelevance.]\n\n### search_queries\n['query1', 'query2', ..., ] # Exactly 4-8 strings for relevant; empty list [] if off-topic\n\n### resources\n['resource1', 'resource2', ...] # 1-4 from predefined list for relevant; empty list [] if off-topic", "fields": [ { "prefix": "Chat History:", @@ -19,7 +19,7 @@ }, { "prefix": "Resources:", - "description": "List of documentation sources. If unsure what to use or if the query is not clear, use all of the available sources. Available sources: cairo_book: The Cairo Programming Language Book. Essential for core language syntax, semantics, types (felt252, structs, enums, Vec), traits, generics, control flow, memory management, writing tests, organizing a project, standard library usage, starknet interactions. Crucial for smart contract structure, storage, events, ABI, syscalls, contract deployment, interaction, L1<>L2 messaging, Starknet-specific attributes. Very important for interactions with the Starknet state and context (e.g. block, transaction) through syscalls., starknet_docs: The Starknet Documentation. For the Starknet protocol, the STWO prover, architecture, APIs, syscalls, network interaction, deployment, ecosystem tools (Starkli, indexers, StarknetJS, wallets), general Starknet knowledge. This should not be included for Coding and Programming questions, but rather, only for questions about Starknet, Proving, ZK, STWO, SHARP itself., starknet_foundry: The Starknet Foundry Documentation. For using the Foundry toolchain: `snforge` for writing, compiling, testing (unit tests, integration tests), and debugging Starknet contracts. `sncast` for deploying and interacting with contracts to Starknet., cairo_by_example: Cairo by Example Documentation. Provides practical Cairo code snippets for specific language features or common patterns. Useful for how-to syntax questions. This should not be included for Smart Contract questions, but for all other Cairo programming questions., openzeppelin_docs: OpenZeppelin Cairo Contracts Documentation. For using the OZ library: standard implementations (ERC20, ERC721), access control, security patterns, contract upgradeability. Crucial for building standard-compliant contracts., corelib_docs: Cairo Core Library Documentation. For using the Cairo core library: basic types, stdlib functions, stdlib structs, macros, and other core concepts. Essential for Cairo programming questions., scarb_docs: Scarb Documentation. For using the Scarb package manager: building, compiling, generating compilation artifacts, managing dependencies, configuration of Scarb.toml., starknet_js: StarknetJS Documentation. For using the StarknetJS library: interacting with Starknet contracts, (calls and transactions), deploying Starknet contracts, front-end APIs, javascript integration examples, guides, tutorials and general JS/TS documentation for starknet., starknet_blog: Starknet Blog Documentation. For latest Starknet updates, announcements, feature releases, ecosystem developments, integration guides, and community updates. Useful for understanding recent Starknet innovations, new tools and applications on starknet, partnerships, and protocol enhancements." + "description": "List of documentation sources. If unsure what to use or if the query is not clear, use all of the available sources. Available sources: cairo_book: The Cairo Programming Language Book. Essential for core language syntax, semantics, types (felt252, structs, enums, Vec), traits, generics, control flow, memory management, writing tests, organizing a project, standard library usage, starknet interactions. Crucial for smart contract structure, storage, events, ABI, syscalls, contract deployment, interaction, L1<>L2 messaging, Starknet-specific attributes. Very important for interactions with the Starknet state and context (e.g. block, transaction) through syscalls., starknet_docs: The Starknet Documentation. For the Starknet protocol, the STWO prover, architecture, APIs, syscalls, network interaction, deployment, ecosystem tools (Starkli, indexers, StarknetJS, wallets), general Starknet knowledge. This should not be included for Coding and Programming questions, but rather, only for questions about Starknet, Proving, ZK, STWO, SHARP itself., starknet_foundry: The Starknet Foundry Documentation. For using the Foundry toolchain: `snforge` for writing, compiling, testing (unit tests, integration tests), and debugging Starknet contracts. `sncast` for deploying and interacting with contracts to Starknet., cairo_by_example: Cairo by Example Documentation. Provides practical Cairo code snippets for specific language features or common patterns. Useful for how-to syntax questions. This should not be included for Smart Contract questions, but for all other Cairo programming questions., openzeppelin_docs: OpenZeppelin Cairo Contracts Documentation. For using the OZ library: standard implementations (ERC20, ERC721), access control, security patterns, contract upgradeability. Crucial for building standard-compliant contracts., corelib_docs: Cairo Core Library Documentation. For using the Cairo core library: basic types, stdlib functions, stdlib structs, macros, and other core concepts. Essential for Cairo programming questions., scarb_docs: Scarb Documentation. For using the Scarb package manager: building, compiling, generating compilation artifacts, managing dependencies, configuration of Scarb.toml., starknet_js: StarknetJS Documentation. For using the StarknetJS library: interacting with Starknet contracts, (calls and transactions), deploying Starknet contracts, front-end APIs, javascript integration examples, guides, tutorials and general JS/TS documentation for starknet., starknet_blog: Starknet Blog Documentation. For latest Starknet updates, announcements, feature releases, ecosystem developments, integration guides, and community updates. Useful for understanding recent Starknet innovations, new tools and applications on starknet, partnerships, and protocol enhancements., dojo_docs: Dojo Documentation. For building onchain games and autonomous worlds using the Dojo framework: entity component system (ECS) patterns, world contracts, models, systems, events, indexing with Torii (GraphQL API, entity subscriptions, real-time state synchronization), SDKs and client libraries including dojo.js (TypeScript/JavaScript integration, entity queries, world interactions), Rust SDK (torii-client, world state queries, account management, transaction execution, real-time subscriptions), dojo.c (C bindings for native integrations, WASM32 support), dojo.unity (Unity C# SDK with codegen plugin, World Manager), dojo.godot (Godot integration with live testnet demos), Telegram bot SDK (@dojoengine packages), support for Unreal Engine modules, Sozo CLI tool (build, migration, deployment), Katana devnet, game development patterns on Starknet." } ] }, diff --git a/python/src/cairo_coder/agents/registry.py b/python/src/cairo_coder/agents/registry.py index e6e7b55..4dd1df7 100644 --- a/python/src/cairo_coder/agents/registry.py +++ b/python/src/cairo_coder/agents/registry.py @@ -89,7 +89,7 @@ def build(self, vector_db: SourceFilteredPgVectorRM, vector_store_config: Vector }, max_source_count=5, similarity_threshold=0.4, - ), + ) } diff --git a/python/src/cairo_coder/core/types.py b/python/src/cairo_coder/core/types.py index 8486f50..536274b 100644 --- a/python/src/cairo_coder/core/types.py +++ b/python/src/cairo_coder/core/types.py @@ -39,6 +39,7 @@ class DocumentSource(str, Enum): SCARB_DOCS = "scarb_docs" STARKNET_JS = "starknet_js" STARKNET_BLOG = "starknet_blog" + DOJO_DOCS = "dojo_docs" class DocumentMetadata(TypedDict, total=False): diff --git a/python/src/cairo_coder/dspy/generation_program.py b/python/src/cairo_coder/dspy/generation_program.py index e93eb19..0b410b6 100644 --- a/python/src/cairo_coder/dspy/generation_program.py +++ b/python/src/cairo_coder/dspy/generation_program.py @@ -88,7 +88,7 @@ class StarknetEcosystemGeneration(Signature): * **Never use markdown link syntax without a URL** (e.g., never write `[text]` or `[text]()`). Either include a full URL or use plain text. * Place citations naturally within sentences for readability. - 4. **Mathematical Formulas:** Use LaTeX for math formulas. Use block format `$$\nLaTeX code\n$$\` + 4. **Mathematical Formulas:** Use LaTeX for math formulas. Use block format `$$\\nLaTeX code\\n$$\\` (with newlines) or inline format `$ LaTeX code $`. 5. **Cairo Code Generation:** @@ -106,7 +106,7 @@ class StarknetEcosystemGeneration(Signature): 5.bis: **LaTeX Generation:** * If providing LaTeX code, never cite sources using `[number]` notation or include HTML tags inside the LaTeX block. - * If providing LaTeX code, for big blocks, always use the block format `$$\nLaTeX code\n$$\` (with newlines). + * If providing LaTeX code, for big blocks, always use the block format `$$\\nLaTeX code\\n$$\\` (with newlines). * If providing LaTeX code, for inlined content always use the inline format `$ LaTeX code $`. * If the context contains latex blocks in places where inlined formulas are used, try to * convert the latex blocks to inline formulas with a single $ sign, e.g. "The presence of @@ -152,6 +152,8 @@ class StarknetEcosystemGeneration(Signature): ) + + class GenerationProgram(dspy.Module): """ DSPy module for generating Cairo code responses from retrieved context. diff --git a/python/src/cairo_coder/dspy/query_processor.py b/python/src/cairo_coder/dspy/query_processor.py index c0d8447..51f490d 100644 --- a/python/src/cairo_coder/dspy/query_processor.py +++ b/python/src/cairo_coder/dspy/query_processor.py @@ -9,10 +9,10 @@ import os from typing import Optional +import dspy import structlog from langsmith import traceable -import dspy from cairo_coder.core.types import DocumentSource, ProcessedQuery logger = structlog.get_logger(__name__) @@ -27,6 +27,7 @@ DocumentSource.SCARB_DOCS: "Scarb Documentation. For using the Scarb package manager: building, compiling, generating compilation artifacts, managing dependencies, configuration of Scarb.toml.", DocumentSource.STARKNET_JS: "StarknetJS Documentation. For using the StarknetJS library: interacting with Starknet contracts, (calls and transactions), deploying Starknet contracts, front-end APIs, javascript integration examples, guides, tutorials and general JS/TS documentation for starknet.", DocumentSource.STARKNET_BLOG: "Starknet Blog Documentation. For latest Starknet updates, announcements, feature releases, ecosystem developments, integration guides, and community updates. Useful for understanding recent Starknet innovations, new tools, partnerships, and protocol enhancements.", + DocumentSource.DOJO_DOCS: "Dojo Documentation. For building onchain games and autonomous worlds using the Dojo framework: entity component system (ECS) patterns, world contracts, models, systems, events, indexing with Torii (GraphQL API, entity subscriptions, real-time state synchronization), SDKs and client libraries including dojo.js (TypeScript/JavaScript integration, entity queries, world interactions), Rust SDK (torii-client, world state queries, account management, transaction execution, real-time subscriptions), dojo.c (C bindings for native integrations, WASM32 support), dojo.unity (Unity C# SDK with codegen plugin, World Manager), dojo.godot (Godot integration with live testnet demos), Telegram bot SDK (@dojoengine packages), support for Unreal Engine modules, Sozo CLI tool (build, migration, deployment), Katana devnet, game development patterns on Starknet.", } # Ensure all DocumentSource variants are covered