kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: WIP add openapi-to-ts-client generator to automate the creation of agentic TS clients
rodzic
23221d3bf4
commit
c2ef2271d8
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "tsx",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
|
||||
// Debug current file in VSCode
|
||||
"program": "${file}",
|
||||
|
||||
/*
|
||||
* Path to tsx binary
|
||||
* Assuming locally installed
|
||||
*/
|
||||
"runtimeExecutable": "tsx",
|
||||
|
||||
/*
|
||||
* Open terminal when debugging starts (Optional)
|
||||
* Useful to see console.logs
|
||||
*/
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
|
||||
// Files to exclude from debugger (e.g. call stack)
|
||||
"skipFiles": [
|
||||
// Node.js internal core modules
|
||||
"<node_internals>/**",
|
||||
|
||||
// Ignore all dependencies (optional)
|
||||
"${workspaceFolder}/node_modules/**"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,603 @@
|
|||
/**
|
||||
* This file was auto-generated from an OpenAPI spec.
|
||||
*/
|
||||
|
||||
import { aiFunction, AIFunctionsProvider, assert, getEnv } from '@agentic/core'
|
||||
import defaultKy, { type KyInstance } from 'ky'
|
||||
import { z } from 'zod'
|
||||
|
||||
export namespace firecrawl {
|
||||
export const apiBaseUrl = 'https://api.firecrawl.dev/v0'
|
||||
|
||||
export const ScrapeResponseSchema = z.object({
|
||||
success: z.boolean().optional(),
|
||||
/** Warning message to let you know of any issues. */
|
||||
warning: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('Warning message to let you know of any issues.')
|
||||
.optional(),
|
||||
data: z
|
||||
.object({
|
||||
/** Markdown content of the page if the `markdown` format was specified (default) */
|
||||
markdown: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'Markdown content of the page if the `markdown` format was specified (default)'
|
||||
)
|
||||
.optional(),
|
||||
/** HTML version of the content on page if the `html` format was specified */
|
||||
html: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'HTML version of the content on page if the `html` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
/** Raw HTML content of the page if the `rawHtml` format was specified */
|
||||
rawHtml: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'Raw HTML content of the page if the `rawHtml` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
/** Links on the page if the `links` format was specified */
|
||||
links: z
|
||||
.array(z.string().url())
|
||||
.nullable()
|
||||
.describe('Links on the page if the `links` format was specified')
|
||||
.optional(),
|
||||
/** URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified */
|
||||
screenshot: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
metadata: z
|
||||
.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
language: z.string().nullable().optional(),
|
||||
sourceURL: z.string().url().optional(),
|
||||
'<any other metadata> ': z.string().optional(),
|
||||
/** The status code of the page */
|
||||
statusCode: z
|
||||
.number()
|
||||
.int()
|
||||
.describe('The status code of the page')
|
||||
.optional(),
|
||||
/** The error message of the page */
|
||||
error: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The error message of the page')
|
||||
.optional()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
export type ScrapeResponse = z.infer<typeof ScrapeResponseSchema>
|
||||
|
||||
export const CrawlResponseSchema = z.object({
|
||||
success: z.boolean().optional(),
|
||||
id: z.string().optional(),
|
||||
url: z.string().url().optional()
|
||||
})
|
||||
export type CrawlResponse = z.infer<typeof CrawlResponseSchema>
|
||||
|
||||
export const SearchResponseSchema = z.object({
|
||||
success: z.boolean().optional(),
|
||||
data: z.array(z.any()).optional()
|
||||
})
|
||||
export type SearchResponse = z.infer<typeof SearchResponseSchema>
|
||||
|
||||
export const CrawlStatusResponseObjSchema = z.object({
|
||||
/** Markdown content of the page if the `markdown` format was specified (default) */
|
||||
markdown: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'Markdown content of the page if the `markdown` format was specified (default)'
|
||||
)
|
||||
.optional(),
|
||||
/** HTML version of the content on page if the `html` format was specified */
|
||||
html: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'HTML version of the content on page if the `html` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
/** Raw HTML content of the page if the `rawHtml` format was specified */
|
||||
rawHtml: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'Raw HTML content of the page if the `rawHtml` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
/** Links on the page if the `links` format was specified */
|
||||
links: z
|
||||
.array(z.string().url())
|
||||
.nullable()
|
||||
.describe('Links on the page if the `links` format was specified')
|
||||
.optional(),
|
||||
/** URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified */
|
||||
screenshot: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe(
|
||||
'URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified'
|
||||
)
|
||||
.optional(),
|
||||
metadata: z
|
||||
.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
language: z.string().nullable().optional(),
|
||||
sourceURL: z.string().url().optional(),
|
||||
'<any other metadata> ': z.string().optional(),
|
||||
/** The status code of the page */
|
||||
statusCode: z
|
||||
.number()
|
||||
.int()
|
||||
.describe('The status code of the page')
|
||||
.optional(),
|
||||
/** The error message of the page */
|
||||
error: z
|
||||
.string()
|
||||
.nullable()
|
||||
.describe('The error message of the page')
|
||||
.optional()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
export type CrawlStatusResponseObj = z.infer<
|
||||
typeof CrawlStatusResponseObjSchema
|
||||
>
|
||||
|
||||
export const ScrapeParamsSchema = z.object({
|
||||
/** The URL to scrape */
|
||||
url: z.string().url().describe('The URL to scrape'),
|
||||
/**
|
||||
* Specific formats to return.
|
||||
*
|
||||
* - markdown: The page in Markdown format.
|
||||
* - html: The page's HTML, trimmed to include only meaningful content.
|
||||
* - rawHtml: The page's original HTML.
|
||||
* - links: The links on the page.
|
||||
* - screenshot: A screenshot of the top of the page.
|
||||
* - screenshot@fullPage: A screenshot of the full page. (overridden by screenshot if present)
|
||||
*/
|
||||
formats: z
|
||||
.array(
|
||||
z.enum([
|
||||
'markdown',
|
||||
'html',
|
||||
'rawHtml',
|
||||
'links',
|
||||
'screenshot',
|
||||
'screenshot@fullPage'
|
||||
])
|
||||
)
|
||||
.describe(
|
||||
"Specific formats to return.\n\n - markdown: The page in Markdown format.\n - html: The page's HTML, trimmed to include only meaningful content.\n - rawHtml: The page's original HTML.\n - links: The links on the page.\n - screenshot: A screenshot of the top of the page.\n - screenshot@fullPage: A screenshot of the full page. (overridden by screenshot if present)"
|
||||
)
|
||||
.default(['markdown']),
|
||||
/** Headers to send with the request. Can be used to send cookies, user-agent, etc. */
|
||||
headers: z
|
||||
.record(z.any())
|
||||
.describe(
|
||||
'Headers to send with the request. Can be used to send cookies, user-agent, etc.'
|
||||
)
|
||||
.optional(),
|
||||
/** Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer' */
|
||||
includeTags: z
|
||||
.array(z.string())
|
||||
.describe(
|
||||
"Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
)
|
||||
.optional(),
|
||||
/** Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer' */
|
||||
excludeTags: z
|
||||
.array(z.string())
|
||||
.describe(
|
||||
"Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
)
|
||||
.optional(),
|
||||
/** Only return the main content of the page excluding headers, navs, footers, etc. */
|
||||
onlyMainContent: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Only return the main content of the page excluding headers, navs, footers, etc.'
|
||||
)
|
||||
.default(true),
|
||||
/** Timeout in milliseconds for the request */
|
||||
timeout: z
|
||||
.number()
|
||||
.int()
|
||||
.describe('Timeout in milliseconds for the request')
|
||||
.default(30_000),
|
||||
/** Wait x amount of milliseconds for the page to load to fetch content */
|
||||
waitFor: z
|
||||
.number()
|
||||
.int()
|
||||
.describe(
|
||||
'Wait x amount of milliseconds for the page to load to fetch content'
|
||||
)
|
||||
.default(0)
|
||||
})
|
||||
export type ScrapeParams = z.infer<typeof ScrapeParamsSchema>
|
||||
|
||||
export const CrawlUrlsParamsSchema = z.object({
|
||||
/** The base URL to start crawling from */
|
||||
url: z.string().url().describe('The base URL to start crawling from'),
|
||||
crawlerOptions: z
|
||||
.object({
|
||||
/** URL patterns to include */
|
||||
includes: z
|
||||
.array(z.string())
|
||||
.describe('URL patterns to include')
|
||||
.optional(),
|
||||
/** URL patterns to exclude */
|
||||
excludes: z
|
||||
.array(z.string())
|
||||
.describe('URL patterns to exclude')
|
||||
.optional(),
|
||||
/** Generate alt text for images using LLMs (must have a paid plan) */
|
||||
generateImgAltText: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Generate alt text for images using LLMs (must have a paid plan)'
|
||||
)
|
||||
.default(false),
|
||||
/** If true, returns only the URLs as a list on the crawl status. Attention: the return response will be a list of URLs inside the data, not a list of documents. */
|
||||
returnOnlyUrls: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'If true, returns only the URLs as a list on the crawl status. Attention: the return response will be a list of URLs inside the data, not a list of documents.'
|
||||
)
|
||||
.default(false),
|
||||
/** Maximum depth to crawl relative to the entered URL. A maxDepth of 0 scrapes only the entered URL. A maxDepth of 1 scrapes the entered URL and all pages one level deep. A maxDepth of 2 scrapes the entered URL and all pages up to two levels deep. Higher values follow the same pattern. */
|
||||
maxDepth: z
|
||||
.number()
|
||||
.int()
|
||||
.describe(
|
||||
'Maximum depth to crawl relative to the entered URL. A maxDepth of 0 scrapes only the entered URL. A maxDepth of 1 scrapes the entered URL and all pages one level deep. A maxDepth of 2 scrapes the entered URL and all pages up to two levels deep. Higher values follow the same pattern.'
|
||||
)
|
||||
.optional(),
|
||||
/** The crawling mode to use. Fast mode crawls 4x faster websites without sitemap, but may not be as accurate and shouldn't be used in heavy js-rendered websites. */
|
||||
mode: z
|
||||
.enum(['default', 'fast'])
|
||||
.describe(
|
||||
"The crawling mode to use. Fast mode crawls 4x faster websites without sitemap, but may not be as accurate and shouldn't be used in heavy js-rendered websites."
|
||||
)
|
||||
.default('default'),
|
||||
/** Ignore the website sitemap when crawling */
|
||||
ignoreSitemap: z
|
||||
.boolean()
|
||||
.describe('Ignore the website sitemap when crawling')
|
||||
.default(false),
|
||||
/** Maximum number of pages to crawl */
|
||||
limit: z
|
||||
.number()
|
||||
.int()
|
||||
.describe('Maximum number of pages to crawl')
|
||||
.default(10_000),
|
||||
/** Enables the crawler to navigate from a specific URL to previously linked pages. For instance, from 'example.com/product/123' back to 'example.com/product' */
|
||||
allowBackwardCrawling: z
|
||||
.boolean()
|
||||
.describe(
|
||||
"Enables the crawler to navigate from a specific URL to previously linked pages. For instance, from 'example.com/product/123' back to 'example.com/product'"
|
||||
)
|
||||
.default(false),
|
||||
/** Allows the crawler to follow links to external websites. */
|
||||
allowExternalContentLinks: z
|
||||
.boolean()
|
||||
.describe('Allows the crawler to follow links to external websites.')
|
||||
.default(false)
|
||||
})
|
||||
.optional(),
|
||||
pageOptions: z
|
||||
.object({
|
||||
/** Headers to send with the request. Can be used to send cookies, user-agent, etc. */
|
||||
headers: z
|
||||
.record(z.any())
|
||||
.describe(
|
||||
'Headers to send with the request. Can be used to send cookies, user-agent, etc.'
|
||||
)
|
||||
.optional(),
|
||||
/** Include the HTML version of the content on page. Will output a html key in the response. */
|
||||
includeHtml: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include the HTML version of the content on page. Will output a html key in the response.'
|
||||
)
|
||||
.default(false),
|
||||
/** Include the raw HTML content of the page. Will output a rawHtml key in the response. */
|
||||
includeRawHtml: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include the raw HTML content of the page. Will output a rawHtml key in the response.'
|
||||
)
|
||||
.default(false),
|
||||
/** Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer' */
|
||||
onlyIncludeTags: z
|
||||
.array(z.string())
|
||||
.describe(
|
||||
"Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
)
|
||||
.optional(),
|
||||
/** Only return the main content of the page excluding headers, navs, footers, etc. */
|
||||
onlyMainContent: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Only return the main content of the page excluding headers, navs, footers, etc.'
|
||||
)
|
||||
.default(false),
|
||||
/** Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer' */
|
||||
removeTags: z
|
||||
.array(z.string())
|
||||
.describe(
|
||||
"Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
)
|
||||
.optional(),
|
||||
/** Replace all relative paths with absolute paths for images and links */
|
||||
replaceAllPathsWithAbsolutePaths: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Replace all relative paths with absolute paths for images and links'
|
||||
)
|
||||
.default(false),
|
||||
/** Include a screenshot of the top of the page that you are scraping. */
|
||||
screenshot: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include a screenshot of the top of the page that you are scraping.'
|
||||
)
|
||||
.default(false),
|
||||
/** Include a full page screenshot of the page that you are scraping. */
|
||||
fullPageScreenshot: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include a full page screenshot of the page that you are scraping.'
|
||||
)
|
||||
.default(false),
|
||||
/** Wait x amount of milliseconds for the page to load to fetch content */
|
||||
waitFor: z
|
||||
.number()
|
||||
.int()
|
||||
.describe(
|
||||
'Wait x amount of milliseconds for the page to load to fetch content'
|
||||
)
|
||||
.default(0)
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
export type CrawlUrlsParams = z.infer<typeof CrawlUrlsParamsSchema>
|
||||
|
||||
export const CrawlUrlsResponseSchema = CrawlResponseSchema
|
||||
export type CrawlUrlsResponse = z.infer<typeof CrawlUrlsResponseSchema>
|
||||
|
||||
export const SearchGoogleParamsSchema = z.object({
|
||||
/** The query to search for */
|
||||
query: z.string().url().describe('The query to search for'),
|
||||
pageOptions: z
|
||||
.object({
|
||||
/** Only return the main content of the page excluding headers, navs, footers, etc. */
|
||||
onlyMainContent: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Only return the main content of the page excluding headers, navs, footers, etc.'
|
||||
)
|
||||
.default(false),
|
||||
/** Fetch the content of each page. If false, defaults to a basic fast serp API. */
|
||||
fetchPageContent: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Fetch the content of each page. If false, defaults to a basic fast serp API.'
|
||||
)
|
||||
.default(true),
|
||||
/** Include the HTML version of the content on page. Will output a html key in the response. */
|
||||
includeHtml: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include the HTML version of the content on page. Will output a html key in the response.'
|
||||
)
|
||||
.default(false),
|
||||
/** Include the raw HTML content of the page. Will output a rawHtml key in the response. */
|
||||
includeRawHtml: z
|
||||
.boolean()
|
||||
.describe(
|
||||
'Include the raw HTML content of the page. Will output a rawHtml key in the response.'
|
||||
)
|
||||
.default(false)
|
||||
})
|
||||
.optional(),
|
||||
searchOptions: z
|
||||
.object({
|
||||
/** Maximum number of results. Max is 20 during beta. */
|
||||
limit: z
|
||||
.number()
|
||||
.int()
|
||||
.describe('Maximum number of results. Max is 20 during beta.')
|
||||
.optional()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
export type SearchGoogleParams = z.infer<typeof SearchGoogleParamsSchema>
|
||||
|
||||
export const SearchGoogleResponseSchema = SearchResponseSchema
|
||||
export type SearchGoogleResponse = z.infer<typeof SearchGoogleResponseSchema>
|
||||
|
||||
export const GetCrawlStatusParamsSchema = z.object({
|
||||
/** ID of the crawl job */
|
||||
jobId: z.string().describe('ID of the crawl job')
|
||||
})
|
||||
export type GetCrawlStatusParams = z.infer<typeof GetCrawlStatusParamsSchema>
|
||||
|
||||
export const GetCrawlStatusResponseSchema = z.object({
|
||||
/** Status of the job (completed, active, failed, paused) */
|
||||
status: z
|
||||
.string()
|
||||
.describe('Status of the job (completed, active, failed, paused)')
|
||||
.optional(),
|
||||
/** Current page number */
|
||||
current: z.number().int().describe('Current page number').optional(),
|
||||
/** Total number of pages */
|
||||
total: z.number().int().describe('Total number of pages').optional(),
|
||||
/** Data returned from the job (null when it is in progress) */
|
||||
data: z
|
||||
.array(CrawlStatusResponseObjSchema)
|
||||
.describe('Data returned from the job (null when it is in progress)')
|
||||
.optional(),
|
||||
/** Partial documents returned as it is being crawled (streaming). **This feature is currently in alpha - expect breaking changes** When a page is ready, it will append to the partial_data array, so there is no need to wait for the entire website to be crawled. When the crawl is done, partial_data will become empty and the result will be available in `data`. There is a max of 50 items in the array response. The oldest item (top of the array) will be removed when the new item is added to the array. */
|
||||
partial_data: z
|
||||
.array(CrawlStatusResponseObjSchema)
|
||||
.describe(
|
||||
'Partial documents returned as it is being crawled (streaming). **This feature is currently in alpha - expect breaking changes** When a page is ready, it will append to the partial_data array, so there is no need to wait for the entire website to be crawled. When the crawl is done, partial_data will become empty and the result will be available in `data`. There is a max of 50 items in the array response. The oldest item (top of the array) will be removed when the new item is added to the array.'
|
||||
)
|
||||
.optional()
|
||||
})
|
||||
export type GetCrawlStatusResponse = z.infer<
|
||||
typeof GetCrawlStatusResponseSchema
|
||||
>
|
||||
|
||||
export const CancelCrawlJobParamsSchema = z.object({
|
||||
/** ID of the crawl job */
|
||||
jobId: z.string().describe('ID of the crawl job')
|
||||
})
|
||||
export type CancelCrawlJobParams = z.infer<typeof CancelCrawlJobParamsSchema>
|
||||
|
||||
export const CancelCrawlJobResponseSchema = z.object({
|
||||
/** Returns cancelled. */
|
||||
status: z.string().describe('Returns cancelled.').optional()
|
||||
})
|
||||
export type CancelCrawlJobResponse = z.infer<
|
||||
typeof CancelCrawlJobResponseSchema
|
||||
>
|
||||
}
|
||||
|
||||
export class FirecrawlClient extends AIFunctionsProvider {
|
||||
protected readonly ky: KyInstance
|
||||
protected readonly apiKey: string
|
||||
protected readonly apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiKey = getEnv('FIRECRAWL_API_KEY'),
|
||||
apiBaseUrl = firecrawl.apiBaseUrl,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
apiKey?: string
|
||||
apiBaseUrl?: string
|
||||
ky?: KyInstance
|
||||
} = {}) {
|
||||
assert(
|
||||
apiKey,
|
||||
'FirecrawlClient missing required "apiKey" (defaults to "FIRECRAWL_API_KEY")'
|
||||
)
|
||||
super()
|
||||
|
||||
this.apiKey = apiKey
|
||||
this.apiBaseUrl = apiBaseUrl
|
||||
|
||||
this.ky = ky.extend({
|
||||
prefixUrl: apiBaseUrl,
|
||||
headers: {
|
||||
Authorization: apiKey
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrape a single URL.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'scrape',
|
||||
description: 'Scrape a single URL.',
|
||||
inputSchema: firecrawl.ScrapeParamsSchema
|
||||
})
|
||||
async scrape(
|
||||
params: firecrawl.ScrapeParams
|
||||
): Promise<firecrawl.ScrapeResponse> {
|
||||
return this.ky
|
||||
.post('/scrape', {
|
||||
json: params
|
||||
})
|
||||
.json<firecrawl.ScrapeResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl multiple URLs based on options.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'crawl_urls',
|
||||
description: 'Crawl multiple URLs based on options.',
|
||||
inputSchema: firecrawl.CrawlUrlsParamsSchema
|
||||
})
|
||||
async crawlUrls(
|
||||
params: firecrawl.CrawlUrlsParams
|
||||
): Promise<firecrawl.CrawlUrlsResponse> {
|
||||
return this.ky
|
||||
.post('/crawl', {
|
||||
json: params
|
||||
})
|
||||
.json<firecrawl.CrawlUrlsResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a keyword in Google, returns top page results with markdown content for each page.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'search_google',
|
||||
description:
|
||||
'Search for a keyword in Google, returns top page results with markdown content for each page.',
|
||||
inputSchema: firecrawl.SearchGoogleParamsSchema
|
||||
})
|
||||
async searchGoogle(
|
||||
params: firecrawl.SearchGoogleParams
|
||||
): Promise<firecrawl.SearchGoogleResponse> {
|
||||
return this.ky
|
||||
.post('/search', {
|
||||
json: params
|
||||
})
|
||||
.json<firecrawl.SearchGoogleResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status of a crawl job.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'get_crawl_status',
|
||||
description: 'Get the status of a crawl job.',
|
||||
inputSchema: firecrawl.GetCrawlStatusParamsSchema
|
||||
})
|
||||
async getCrawlStatus(
|
||||
params: firecrawl.GetCrawlStatusParams
|
||||
): Promise<firecrawl.GetCrawlStatusResponse> {
|
||||
return this.ky
|
||||
.get(`/crawl/status/${params.jobId}`)
|
||||
.json<firecrawl.GetCrawlStatusResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a crawl job.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'cancel_crawl_job',
|
||||
description: 'Cancel a crawl job.',
|
||||
inputSchema: firecrawl.CancelCrawlJobParamsSchema
|
||||
})
|
||||
async cancelCrawlJob(
|
||||
params: firecrawl.CancelCrawlJobParams
|
||||
): Promise<firecrawl.CancelCrawlJobResponse> {
|
||||
return this.ky
|
||||
.delete(`/crawl/cancel/${params.jobId}`)
|
||||
.json<firecrawl.CancelCrawlJobResponse>()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* This file was auto-generated from an OpenAPI spec.
|
||||
*/
|
||||
|
||||
import {
|
||||
aiFunction,
|
||||
AIFunctionsProvider,
|
||||
sanitizeSearchParams
|
||||
} from '@agentic/core'
|
||||
import defaultKy, { type KyInstance } from 'ky'
|
||||
import { z } from 'zod'
|
||||
|
||||
export namespace petstore {
|
||||
export const apiBaseUrl = 'http://petstore.swagger.io/v1'
|
||||
|
||||
export const PetSchema = z.object({
|
||||
id: z.number().int(),
|
||||
name: z.string(),
|
||||
tag: z.string().optional()
|
||||
})
|
||||
export type Pet = z.infer<typeof PetSchema>
|
||||
|
||||
export const PetsSchema = z.array(PetSchema).max(100)
|
||||
export type Pets = z.infer<typeof PetsSchema>
|
||||
|
||||
export const ListPetsParamsSchema = z.object({
|
||||
/** How many items to return at one time (max 100) */
|
||||
limit: z
|
||||
.number()
|
||||
.int()
|
||||
.lte(100)
|
||||
.describe('How many items to return at one time (max 100)')
|
||||
.optional()
|
||||
})
|
||||
export type ListPetsParams = z.infer<typeof ListPetsParamsSchema>
|
||||
|
||||
export const ListPetsResponseSchema = PetsSchema
|
||||
export type ListPetsResponse = z.infer<typeof ListPetsResponseSchema>
|
||||
|
||||
export const CreatePetsParamsSchema = PetSchema
|
||||
export type CreatePetsParams = z.infer<typeof CreatePetsParamsSchema>
|
||||
|
||||
export type CreatePetsResponse = undefined
|
||||
|
||||
export const ShowPetByIdParamsSchema = z.object({
|
||||
/** The id of the pet to retrieve */
|
||||
petId: z.string().describe('The id of the pet to retrieve')
|
||||
})
|
||||
export type ShowPetByIdParams = z.infer<typeof ShowPetByIdParamsSchema>
|
||||
|
||||
export const ShowPetByIdResponseSchema = PetSchema
|
||||
export type ShowPetByIdResponse = z.infer<typeof ShowPetByIdResponseSchema>
|
||||
}
|
||||
|
||||
export class PetStoreClient extends AIFunctionsProvider {
|
||||
protected readonly ky: KyInstance
|
||||
|
||||
protected readonly apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
apiBaseUrl = petstore.apiBaseUrl,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
apiKey?: string
|
||||
apiBaseUrl?: string
|
||||
ky?: KyInstance
|
||||
} = {}) {
|
||||
super()
|
||||
|
||||
this.apiBaseUrl = apiBaseUrl
|
||||
|
||||
this.ky = ky.extend({
|
||||
prefixUrl: apiBaseUrl
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* List all pets.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'list_pets',
|
||||
description: 'List all pets.',
|
||||
inputSchema: petstore.ListPetsParamsSchema
|
||||
})
|
||||
async listPets(
|
||||
params: petstore.ListPetsParams
|
||||
): Promise<petstore.ListPetsResponse> {
|
||||
return this.ky
|
||||
.get('/pets', {
|
||||
searchParams: sanitizeSearchParams(params)
|
||||
})
|
||||
.json<petstore.ListPetsResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pet.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'create_pets',
|
||||
description: 'Create a pet.',
|
||||
inputSchema: petstore.CreatePetsParamsSchema
|
||||
})
|
||||
async createPets(
|
||||
params: petstore.CreatePetsParams
|
||||
): Promise<petstore.CreatePetsResponse> {
|
||||
return this.ky
|
||||
.post('/pets', {
|
||||
json: params
|
||||
})
|
||||
.json<petstore.CreatePetsResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Info for a specific pet.
|
||||
*/
|
||||
@aiFunction({
|
||||
name: 'show_pet_by_id',
|
||||
description: 'Info for a specific pet.',
|
||||
inputSchema: petstore.ShowPetByIdParamsSchema
|
||||
})
|
||||
async showPetById(
|
||||
params: petstore.ShowPetByIdParams
|
||||
): Promise<petstore.ShowPetByIdResponse> {
|
||||
return this.ky
|
||||
.get(`/pets/${params.petId}`)
|
||||
.json<petstore.ShowPetByIdResponse>()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,936 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Firecrawl API",
|
||||
"version": "1.0.0",
|
||||
"description": "API for interacting with Firecrawl services to perform web scraping and crawling tasks.",
|
||||
"contact": {
|
||||
"name": "Firecrawl Support",
|
||||
"url": "https://firecrawl.dev/support",
|
||||
"email": "support@firecrawl.dev"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://api.firecrawl.dev/v0"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/scrape": {
|
||||
"post": {
|
||||
"summary": "Scrape a single URL",
|
||||
"operationId": "scrape",
|
||||
"tags": ["Scraping"],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "The URL to scrape"
|
||||
},
|
||||
"formats": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"markdown",
|
||||
"html",
|
||||
"rawHtml",
|
||||
"links",
|
||||
"screenshot",
|
||||
"screenshot@fullPage"
|
||||
]
|
||||
},
|
||||
"description": "Specific formats to return.\n\n - markdown: The page in Markdown format.\n - html: The page's HTML, trimmed to include only meaningful content.\n - rawHtml: The page's original HTML.\n - links: The links on the page.\n - screenshot: A screenshot of the top of the page.\n - screenshot@fullPage: A screenshot of the full page. (overridden by screenshot if present)",
|
||||
"default": ["markdown"]
|
||||
},
|
||||
"headers": {
|
||||
"type": "object",
|
||||
"description": "Headers to send with the request. Can be used to send cookies, user-agent, etc."
|
||||
},
|
||||
"includeTags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
},
|
||||
"excludeTags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
},
|
||||
"onlyMainContent": {
|
||||
"type": "boolean",
|
||||
"description": "Only return the main content of the page excluding headers, navs, footers, etc.",
|
||||
"default": true
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer",
|
||||
"description": "Timeout in milliseconds for the request",
|
||||
"default": 30000
|
||||
},
|
||||
"waitFor": {
|
||||
"type": "integer",
|
||||
"description": "Wait x amount of milliseconds for the page to load to fetch content",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"required": ["url"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ScrapeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"402": {
|
||||
"description": "Payment required",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Payment required to access this resource."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many requests",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Request rate limit exceeded. Please wait and try again later."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "An unexpected error occurred on the server."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/crawl": {
|
||||
"post": {
|
||||
"summary": "Crawl multiple URLs based on options",
|
||||
"operationId": "crawlUrls",
|
||||
"tags": ["Crawling"],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "The base URL to start crawling from"
|
||||
},
|
||||
"crawlerOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"includes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "URL patterns to include"
|
||||
},
|
||||
"excludes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "URL patterns to exclude"
|
||||
},
|
||||
"generateImgAltText": {
|
||||
"type": "boolean",
|
||||
"description": "Generate alt text for images using LLMs (must have a paid plan)",
|
||||
"default": false
|
||||
},
|
||||
"returnOnlyUrls": {
|
||||
"type": "boolean",
|
||||
"description": "If true, returns only the URLs as a list on the crawl status. Attention: the return response will be a list of URLs inside the data, not a list of documents.",
|
||||
"default": false
|
||||
},
|
||||
"maxDepth": {
|
||||
"type": "integer",
|
||||
"description": "Maximum depth to crawl relative to the entered URL. A maxDepth of 0 scrapes only the entered URL. A maxDepth of 1 scrapes the entered URL and all pages one level deep. A maxDepth of 2 scrapes the entered URL and all pages up to two levels deep. Higher values follow the same pattern."
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["default", "fast"],
|
||||
"description": "The crawling mode to use. Fast mode crawls 4x faster websites without sitemap, but may not be as accurate and shouldn't be used in heavy js-rendered websites.",
|
||||
"default": "default"
|
||||
},
|
||||
"ignoreSitemap": {
|
||||
"type": "boolean",
|
||||
"description": "Ignore the website sitemap when crawling",
|
||||
"default": false
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of pages to crawl",
|
||||
"default": 10000
|
||||
},
|
||||
"allowBackwardCrawling": {
|
||||
"type": "boolean",
|
||||
"description": "Enables the crawler to navigate from a specific URL to previously linked pages. For instance, from 'example.com/product/123' back to 'example.com/product'",
|
||||
"default": false
|
||||
},
|
||||
"allowExternalContentLinks": {
|
||||
"type": "boolean",
|
||||
"description": "Allows the crawler to follow links to external websites.",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"pageOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"headers": {
|
||||
"type": "object",
|
||||
"description": "Headers to send with the request. Can be used to send cookies, user-agent, etc."
|
||||
},
|
||||
"includeHtml": {
|
||||
"type": "boolean",
|
||||
"description": "Include the HTML version of the content on page. Will output a html key in the response.",
|
||||
"default": false
|
||||
},
|
||||
"includeRawHtml": {
|
||||
"type": "boolean",
|
||||
"description": "Include the raw HTML content of the page. Will output a rawHtml key in the response.",
|
||||
"default": false
|
||||
},
|
||||
"onlyIncludeTags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Only include tags, classes and ids from the page in the final output. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
},
|
||||
"onlyMainContent": {
|
||||
"type": "boolean",
|
||||
"description": "Only return the main content of the page excluding headers, navs, footers, etc.",
|
||||
"default": false
|
||||
},
|
||||
"removeTags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Tags, classes and ids to remove from the page. Use comma separated values. Example: 'script, .ad, #footer'"
|
||||
},
|
||||
"replaceAllPathsWithAbsolutePaths": {
|
||||
"type": "boolean",
|
||||
"description": "Replace all relative paths with absolute paths for images and links",
|
||||
"default": false
|
||||
},
|
||||
"screenshot": {
|
||||
"type": "boolean",
|
||||
"description": "Include a screenshot of the top of the page that you are scraping.",
|
||||
"default": false
|
||||
},
|
||||
"fullPageScreenshot": {
|
||||
"type": "boolean",
|
||||
"description": "Include a full page screenshot of the page that you are scraping.",
|
||||
"default": false
|
||||
},
|
||||
"waitFor": {
|
||||
"type": "integer",
|
||||
"description": "Wait x amount of milliseconds for the page to load to fetch content",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["url"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CrawlResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"402": {
|
||||
"description": "Payment required",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Payment required to access this resource."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many requests",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Request rate limit exceeded. Please wait and try again later."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "An unexpected error occurred on the server."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/search": {
|
||||
"post": {
|
||||
"summary": "Search for a keyword in Google, returns top page results with markdown content for each page",
|
||||
"operationId": "searchGoogle",
|
||||
"tags": ["Search"],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "The query to search for"
|
||||
},
|
||||
"pageOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"onlyMainContent": {
|
||||
"type": "boolean",
|
||||
"description": "Only return the main content of the page excluding headers, navs, footers, etc.",
|
||||
"default": false
|
||||
},
|
||||
"fetchPageContent": {
|
||||
"type": "boolean",
|
||||
"description": "Fetch the content of each page. If false, defaults to a basic fast serp API.",
|
||||
"default": true
|
||||
},
|
||||
"includeHtml": {
|
||||
"type": "boolean",
|
||||
"description": "Include the HTML version of the content on page. Will output a html key in the response.",
|
||||
"default": false
|
||||
},
|
||||
"includeRawHtml": {
|
||||
"type": "boolean",
|
||||
"description": "Include the raw HTML content of the page. Will output a rawHtml key in the response.",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"searchOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of results. Max is 20 during beta."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["query"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SearchResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"402": {
|
||||
"description": "Payment required",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Payment required to access this resource."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many requests",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Request rate limit exceeded. Please wait and try again later."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "An unexpected error occurred on the server."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/crawl/status/{jobId}": {
|
||||
"get": {
|
||||
"tags": ["Crawl"],
|
||||
"summary": "Get the status of a crawl job",
|
||||
"operationId": "getCrawlStatus",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "jobId",
|
||||
"in": "path",
|
||||
"description": "ID of the crawl job",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Status of the job (completed, active, failed, paused)"
|
||||
},
|
||||
"current": {
|
||||
"type": "integer",
|
||||
"description": "Current page number"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total number of pages"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/CrawlStatusResponseObj"
|
||||
},
|
||||
"description": "Data returned from the job (null when it is in progress)"
|
||||
},
|
||||
"partial_data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/CrawlStatusResponseObj"
|
||||
},
|
||||
"description": "Partial documents returned as it is being crawled (streaming). **This feature is currently in alpha - expect breaking changes** When a page is ready, it will append to the partial_data array, so there is no need to wait for the entire website to be crawled. When the crawl is done, partial_data will become empty and the result will be available in `data`. There is a max of 50 items in the array response. The oldest item (top of the array) will be removed when the new item is added to the array."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"402": {
|
||||
"description": "Payment required",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Payment required to access this resource."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many requests",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Request rate limit exceeded. Please wait and try again later."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "An unexpected error occurred on the server."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/crawl/cancel/{jobId}": {
|
||||
"delete": {
|
||||
"tags": ["Crawl"],
|
||||
"summary": "Cancel a crawl job",
|
||||
"operationId": "cancelCrawlJob",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "jobId",
|
||||
"in": "path",
|
||||
"description": "ID of the crawl job",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Returns cancelled."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"402": {
|
||||
"description": "Payment required",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Payment required to access this resource."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many requests",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "Request rate limit exceeded. Please wait and try again later."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string",
|
||||
"example": "An unexpected error occurred on the server."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"bearerAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer"
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"ScrapeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"warning": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Warning message to let you know of any issues."
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"markdown": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Markdown content of the page if the `markdown` format was specified (default)"
|
||||
},
|
||||
"html": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "HTML version of the content on page if the `html` format was specified"
|
||||
},
|
||||
"rawHtml": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Raw HTML content of the page if the `rawHtml` format was specified"
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"nullable": true,
|
||||
"description": "Links on the page if the `links` format was specified"
|
||||
},
|
||||
"screenshot": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"sourceURL": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"<any other metadata> ": {
|
||||
"type": "string"
|
||||
},
|
||||
"statusCode": {
|
||||
"type": "integer",
|
||||
"description": "The status code of the page"
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The error message of the page"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CrawlStatusResponseObj": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"markdown": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Markdown content of the page if the `markdown` format was specified (default)"
|
||||
},
|
||||
"html": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "HTML version of the content on page if the `html` format was specified"
|
||||
},
|
||||
"rawHtml": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Raw HTML content of the page if the `rawHtml` format was specified"
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"nullable": true,
|
||||
"description": "Links on the page if the `links` format was specified"
|
||||
},
|
||||
"screenshot": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"sourceURL": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"<any other metadata> ": {
|
||||
"type": "string"
|
||||
},
|
||||
"statusCode": {
|
||||
"type": "integer",
|
||||
"description": "The status code of the page"
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The error message of the page"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SearchResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"markdown": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Markdown content of the page if the `markdown` format was specified (default)"
|
||||
},
|
||||
"html": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "HTML version of the content on page if the `html` format was specified"
|
||||
},
|
||||
"rawHtml": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Raw HTML content of the page if the `rawHtml` format was specified"
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"nullable": true,
|
||||
"description": "Links on the page if the `links` format was specified"
|
||||
},
|
||||
"screenshot": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "URL of the screenshot of the page if the `screenshot` or `screenshot@fullSize` format was specified"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"sourceURL": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"<any other metadata> ": {
|
||||
"type": "string"
|
||||
},
|
||||
"statusCode": {
|
||||
"type": "integer",
|
||||
"description": "The status code of the page"
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The error message of the page"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CrawlResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,177 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"license": {
|
||||
"name": "MIT"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://petstore.swagger.io/v1"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"summary": "List all pets",
|
||||
"operationId": "listPets",
|
||||
"tags": ["pets"],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "How many items to return at one time (max 100)",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"maximum": 100,
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paged array of pets",
|
||||
"headers": {
|
||||
"x-next": {
|
||||
"description": "A link to the next page of responses",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pets"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create a pet",
|
||||
"operationId": "createPets",
|
||||
"tags": ["pets"],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Null response"
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/pets/{petId}": {
|
||||
"get": {
|
||||
"summary": "Info for a specific pet",
|
||||
"operationId": "showPetById",
|
||||
"tags": ["pets"],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "petId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The id of the pet to retrieve",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Expected response to a valid request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Pet": {
|
||||
"type": "object",
|
||||
"required": ["id", "name"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pets": {
|
||||
"type": "array",
|
||||
"maxItems": 100,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"type": "object",
|
||||
"required": ["code", "message"],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "Tic Tac Toe",
|
||||
"description": "This API allows writing down marks on a Tic Tac Toe board\nand requesting the state of the board or of individual squares.\n",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "Gameplay"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/board": {
|
||||
"get": {
|
||||
"summary": "Get the whole board",
|
||||
"description": "Retrieves the current state of the board and the winner.",
|
||||
"tags": ["Gameplay"],
|
||||
"operationId": "get-board",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/status"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"defaultApiKey": []
|
||||
},
|
||||
{
|
||||
"app2AppOauth": ["board:read"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/board/{row}/{column}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/rowParam"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/columnParam"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"summary": "Get a single board square",
|
||||
"description": "Retrieves the requested square.",
|
||||
"tags": ["Gameplay"],
|
||||
"operationId": "get-square",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/mark"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "The provided parameters are incorrect",
|
||||
"content": {
|
||||
"text/html": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/errorMessage"
|
||||
},
|
||||
"example": "Illegal coordinates"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerHttpAuthentication": []
|
||||
},
|
||||
{
|
||||
"user2AppOauth": ["board:read"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"summary": "Set a single board square",
|
||||
"description": "Places a mark on the board and retrieves the whole board and the winner (if any).",
|
||||
"tags": ["Gameplay"],
|
||||
"operationId": "put-square",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/mark"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/status"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "The provided parameters are incorrect",
|
||||
"content": {
|
||||
"text/html": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/errorMessage"
|
||||
},
|
||||
"examples": {
|
||||
"illegalCoordinates": {
|
||||
"value": "Illegal coordinates."
|
||||
},
|
||||
"notEmpty": {
|
||||
"value": "Square is not empty."
|
||||
},
|
||||
"invalidMark": {
|
||||
"value": "Invalid Mark (X or O)."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearerHttpAuthentication": []
|
||||
},
|
||||
{
|
||||
"user2AppOauth": ["board:write"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"parameters": {
|
||||
"rowParam": {
|
||||
"description": "Board row (vertical coordinate)",
|
||||
"name": "row",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/coordinate"
|
||||
}
|
||||
},
|
||||
"columnParam": {
|
||||
"description": "Board column (horizontal coordinate)",
|
||||
"name": "column",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/coordinate"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"errorMessage": {
|
||||
"type": "string",
|
||||
"maxLength": 256,
|
||||
"description": "A text message describing an error"
|
||||
},
|
||||
"coordinate": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 3,
|
||||
"example": 1
|
||||
},
|
||||
"mark": {
|
||||
"type": "string",
|
||||
"enum": [".", "X", "O"],
|
||||
"description": "Possible values for a board square. `.` means empty square.",
|
||||
"example": "."
|
||||
},
|
||||
"board": {
|
||||
"type": "array",
|
||||
"maxItems": 3,
|
||||
"minItems": 3,
|
||||
"items": {
|
||||
"type": "array",
|
||||
"maxItems": 3,
|
||||
"minItems": 3,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/mark"
|
||||
}
|
||||
}
|
||||
},
|
||||
"winner": {
|
||||
"type": "string",
|
||||
"enum": [".", "X", "O"],
|
||||
"description": "Winner of the game. `.` means nobody has won yet.",
|
||||
"example": "."
|
||||
},
|
||||
"status": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"winner": {
|
||||
"$ref": "#/components/schemas/winner"
|
||||
},
|
||||
"board": {
|
||||
"$ref": "#/components/schemas/board"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"defaultApiKey": {
|
||||
"description": "API key provided in console",
|
||||
"type": "apiKey",
|
||||
"name": "api-key",
|
||||
"in": "header"
|
||||
},
|
||||
"basicHttpAuthentication": {
|
||||
"description": "Basic HTTP Authentication",
|
||||
"type": "http",
|
||||
"scheme": "Basic"
|
||||
},
|
||||
"bearerHttpAuthentication": {
|
||||
"description": "Bearer token using a JWT",
|
||||
"type": "http",
|
||||
"scheme": "Bearer",
|
||||
"bearerFormat": "JWT"
|
||||
},
|
||||
"app2AppOauth": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"clientCredentials": {
|
||||
"tokenUrl": "https://learn.openapis.org/oauth/2.0/token",
|
||||
"scopes": {
|
||||
"board:read": "Read the board"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"user2AppOauth": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"authorizationCode": {
|
||||
"authorizationUrl": "https://learn.openapis.org/oauth/2.0/auth",
|
||||
"tokenUrl": "https://learn.openapis.org/oauth/2.0/token",
|
||||
"scopes": {
|
||||
"board:read": "Read the board",
|
||||
"board:write": "Write to the board"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"name": "@agentic/openapi-to-ts-client",
|
||||
"version": "0.1.0",
|
||||
"description": "TODO",
|
||||
"author": "Travis Fischer <travis@transitivebullsh.it>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/transitive-bullshit/agentic.git"
|
||||
},
|
||||
"type": "module",
|
||||
"source": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"clean": "del dist",
|
||||
"test": "run-s test:*",
|
||||
"test:lint": "eslint .",
|
||||
"test:typecheck": "tsc --noEmit",
|
||||
"test:unit": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentic/core": "workspace:*",
|
||||
"@apidevtools/swagger-parser": "^10.1.1",
|
||||
"camelcase": "^8.0.0",
|
||||
"decamelize": "^6.0.0",
|
||||
"execa": "^9.5.2",
|
||||
"json-schema-to-zod": "^2.6.0",
|
||||
"openapi-types": "^12.1.3",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@agentic/tsconfig": "workspace:*",
|
||||
"ky": "catalog:"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<p align="center">
|
||||
<a href="https://agentic.so">
|
||||
<img alt="Agentic" src="https://raw.githubusercontent.com/transitive-bullshit/agentic/main/docs/media/agentic-header.jpg" width="308">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<em>TODO.</em>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml"><img alt="Build Status" src="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml/badge.svg" /></a>
|
||||
<a href="https://www.npmjs.com/package/@agentic/stdlib"><img alt="NPM" src="https://img.shields.io/npm/v/@agentic/stdlib.svg" /></a>
|
||||
<a href="https://github.com/transitive-bullshit/agentic/blob/main/license"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue" /></a>
|
||||
<a href="https://prettier.io"><img alt="Prettier Code Formatting" src="https://img.shields.io/badge/code_style-prettier-brightgreen.svg" /></a>
|
||||
</p>
|
||||
|
||||
# Agentic
|
||||
|
||||
**See the [github repo](https://github.com/transitive-bullshit/agentic) or [docs](https://agentic.so) for more info.**
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Travis Fischer](https://x.com/transitive_bs)
|
|
@ -0,0 +1,614 @@
|
|||
/* eslint-disable no-template-curly-in-string */
|
||||
import * as fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import type { IJsonSchema, OpenAPIV3 } from 'openapi-types'
|
||||
import { assert } from '@agentic/core'
|
||||
import SwaggerParser from '@apidevtools/swagger-parser'
|
||||
import camelCase from 'camelcase'
|
||||
import decamelize from 'decamelize'
|
||||
import { execa } from 'execa'
|
||||
|
||||
import { convertParametersToJSONSchema } from './openapi-parameters-to-json-schema'
|
||||
import {
|
||||
dereference,
|
||||
dereferenceFull,
|
||||
getAndResolve,
|
||||
getComponentName,
|
||||
getOperationParamsName,
|
||||
getOperationResponseName,
|
||||
jsonSchemaToZod,
|
||||
prettify
|
||||
} from './utils'
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const jsonContentType = 'application/json'
|
||||
const multipartFormData = 'multipart/form-data'
|
||||
|
||||
const httpMethods = [
|
||||
'get',
|
||||
'post',
|
||||
'put',
|
||||
'delete',
|
||||
'options',
|
||||
'head',
|
||||
'patch',
|
||||
'trace'
|
||||
] as const
|
||||
|
||||
async function main() {
|
||||
const pathToOpenApiSpec = process.argv[2]
|
||||
assert(pathToOpenApiSpec, 'Missing path to OpenAPI spec')
|
||||
|
||||
const parser = new SwaggerParser()
|
||||
const spec = (await parser.bundle(pathToOpenApiSpec)) as OpenAPIV3.Document
|
||||
// | OpenAPIV3_1.Document
|
||||
|
||||
if (
|
||||
// TODO: make this less brittle
|
||||
spec.openapi !== '3.0.0' &&
|
||||
spec.openapi !== '3.1.0' &&
|
||||
spec.openapi !== '3.1.1'
|
||||
) {
|
||||
throw new Error(`Unexpected OpenAPI version "${spec.openapi}"`)
|
||||
}
|
||||
|
||||
const openapiSpecName = path.basename(pathToOpenApiSpec, '.json')
|
||||
assert(
|
||||
openapiSpecName.toLowerCase() === openapiSpecName,
|
||||
`OpenAPI spec name "${openapiSpecName}" must be in kebab case`
|
||||
)
|
||||
const name = camelCase(openapiSpecName, { pascalCase: true })
|
||||
const nameLowerCase = name.toLowerCase()
|
||||
const nameSnakeCase = decamelize(name)
|
||||
const nameKebabCase = decamelize(name, { separator: '-' })
|
||||
const nameUpperCase = nameSnakeCase.toUpperCase()
|
||||
const clientName = `${name}Client`
|
||||
const namespaceName = nameLowerCase
|
||||
// const destFolder = path.join('packages', nameKebabCase)
|
||||
// const destFolderSrc = path.join(destFolder, 'src')
|
||||
|
||||
const destFolder = path.join(dirname, '..', 'fixtures', 'generated')
|
||||
const destFileClient = path.join(destFolder, `${nameKebabCase}-client.ts`)
|
||||
|
||||
const apiBaseUrl = spec.servers?.[0]?.url
|
||||
|
||||
const securitySchemes = spec.components?.securitySchemes
|
||||
const resolvedSecuritySchemes: Record<
|
||||
string,
|
||||
OpenAPIV3.SecuritySchemeObject
|
||||
> = {}
|
||||
const apiKeyHeaderNames: string[] = []
|
||||
|
||||
if (securitySchemes) {
|
||||
for (const [securitySchemaName, maybeSecuritySchema] of Object.entries(
|
||||
securitySchemes
|
||||
)) {
|
||||
const securitySchema = dereferenceFull(maybeSecuritySchema, parser.$refs)
|
||||
if (!securitySchema) continue
|
||||
|
||||
resolvedSecuritySchemes[securitySchemaName] = securitySchema
|
||||
|
||||
switch (securitySchema.type) {
|
||||
case 'apiKey':
|
||||
apiKeyHeaderNames.push(securitySchemaName)
|
||||
break
|
||||
|
||||
case 'http':
|
||||
if (securitySchema.scheme === 'bearer') {
|
||||
apiKeyHeaderNames.push(securitySchemaName)
|
||||
}
|
||||
break
|
||||
|
||||
case 'oauth2':
|
||||
apiKeyHeaderNames.push(securitySchemaName)
|
||||
break
|
||||
|
||||
default:
|
||||
console.log(
|
||||
'unsupported security schema',
|
||||
securitySchemaName,
|
||||
securitySchema
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hasGlobalApiKeyInHeader = apiKeyHeaderNames.length === 1
|
||||
const componentsToProcess = new Set<string>()
|
||||
|
||||
const requestBodyJSONSchemaPaths = [
|
||||
'requestBody',
|
||||
'content',
|
||||
jsonContentType,
|
||||
'schema'
|
||||
]
|
||||
|
||||
const requestBodyFormDataJSONSchemaPaths = [
|
||||
'requestBody',
|
||||
'content',
|
||||
multipartFormData,
|
||||
'schema'
|
||||
]
|
||||
|
||||
const operationResponsePaths = [
|
||||
['responses', '200', 'content', jsonContentType, 'schema'],
|
||||
['responses', '201', 'content', jsonContentType, 'schema']
|
||||
// ['responses', 'default', 'content', jsonContentType, 'schema']
|
||||
]
|
||||
|
||||
const operationRequestPaths = [
|
||||
requestBodyJSONSchemaPaths,
|
||||
requestBodyFormDataJSONSchemaPaths
|
||||
]
|
||||
|
||||
const operationIds = new Set<string>()
|
||||
const operationSchemas: Record<string, string> = {}
|
||||
const componentSchemas: Record<string, string> = {}
|
||||
const aiClientMethods: string[] = []
|
||||
|
||||
for (const path in spec.paths) {
|
||||
const pathItem = spec.paths[path]
|
||||
assert(pathItem)
|
||||
// console.log(JSON.stringify(pathItem, null, 2))
|
||||
|
||||
for (const method of httpMethods) {
|
||||
const operation = pathItem[method]
|
||||
if (!operation) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (method === 'trace' || method === 'options') {
|
||||
continue
|
||||
}
|
||||
|
||||
const operationName =
|
||||
// TODO: better camelCase fallback
|
||||
operation.operationId || `${method}${path.replaceAll(/\W+/g, '_')}`
|
||||
assert(
|
||||
operationName,
|
||||
`Invalid operation name ${operationName} for path "${method} ${path}"`
|
||||
)
|
||||
assert(
|
||||
!operationIds.has(operationName),
|
||||
`Duplicate operation name "${operationName}"`
|
||||
)
|
||||
operationIds.add(operationName)
|
||||
const operationNameSnakeCase = decamelize(operationName)
|
||||
|
||||
// if (path !== '/crawl/status/{jobId}') continue
|
||||
// if (path !== '/pets' || method !== 'post') continue
|
||||
// console.log(method, path, operationName)
|
||||
|
||||
const operationParamsJSONSchema = {
|
||||
type: 'object',
|
||||
properties: {} as Record<string, any>,
|
||||
required: [] as string[],
|
||||
$refs: [] as string[]
|
||||
}
|
||||
|
||||
const operationResponseJSONSchemas: Record<string, IJsonSchema> = {}
|
||||
|
||||
const operationParamsSources: Record<string, string> = {}
|
||||
|
||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||
function addJSONSchemaParams(schema: IJsonSchema, source: string) {
|
||||
dereferenceFull(schema, parser.$refs, componentsToProcess)
|
||||
|
||||
if (schema.$ref) {
|
||||
operationParamsJSONSchema.$refs.push(schema.$ref)
|
||||
|
||||
const derefed = dereference(schema, parser.$refs, componentsToProcess)
|
||||
if (derefed?.properties) {
|
||||
for (const key of Object.keys(derefed.properties)) {
|
||||
assert(
|
||||
!operationParamsSources[key],
|
||||
`Duplicate params key ${key} for operation ${operationName} from ${operationParamsSources[key]} and ${source}`
|
||||
)
|
||||
operationParamsSources[key] = source
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(schema.type === 'object')
|
||||
|
||||
if (schema.properties) {
|
||||
operationParamsJSONSchema.properties = {
|
||||
...operationParamsJSONSchema.properties,
|
||||
...schema.properties
|
||||
}
|
||||
|
||||
for (const key of Object.keys(schema.properties)) {
|
||||
assert(
|
||||
!operationParamsSources[key],
|
||||
`Duplicate params key ${key} for operation ${operationName} from ${operationParamsSources[key]} and ${source}`
|
||||
)
|
||||
operationParamsSources[key] = source
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.required) {
|
||||
operationParamsJSONSchema.required = [
|
||||
...operationParamsJSONSchema.required,
|
||||
...schema.required
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||
function addJSONSchemaResponse(schema: IJsonSchema, status: string) {
|
||||
dereferenceFull(schema, parser.$refs, componentsToProcess)
|
||||
operationResponseJSONSchemas[status] = schema
|
||||
}
|
||||
|
||||
for (const schemaPath of operationRequestPaths) {
|
||||
const res = getAndResolve(
|
||||
operation,
|
||||
schemaPath,
|
||||
parser.$refs,
|
||||
componentsToProcess
|
||||
)
|
||||
|
||||
if (res) {
|
||||
addJSONSchemaParams(
|
||||
res,
|
||||
schemaPath[2] === jsonContentType ? 'body' : 'formData'
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (const schemaPath of operationResponsePaths) {
|
||||
const res = getAndResolve(
|
||||
operation,
|
||||
schemaPath,
|
||||
parser.$refs,
|
||||
componentsToProcess
|
||||
)
|
||||
|
||||
if (res) {
|
||||
const status = schemaPath[1]!
|
||||
assert(
|
||||
status,
|
||||
`Invalid status ${status} for operation ${operationName}`
|
||||
)
|
||||
|
||||
addJSONSchemaResponse(res, status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (operation.parameters) {
|
||||
const params = convertParametersToJSONSchema(operation.parameters)
|
||||
|
||||
if (params.body) {
|
||||
addJSONSchemaParams(params.body, 'body')
|
||||
}
|
||||
|
||||
if (params.formData) {
|
||||
addJSONSchemaParams(params.formData, 'formData')
|
||||
}
|
||||
|
||||
if (params.headers) {
|
||||
addJSONSchemaParams(params.headers, 'formData')
|
||||
}
|
||||
|
||||
if (params.path) {
|
||||
addJSONSchemaParams(params.path, 'path')
|
||||
}
|
||||
|
||||
if (params.query) {
|
||||
addJSONSchemaParams(params.query, 'query')
|
||||
}
|
||||
}
|
||||
|
||||
const operationParamsName = getOperationParamsName(
|
||||
operationName,
|
||||
componentSchemas
|
||||
)
|
||||
const operationResponseName = getOperationResponseName(operationName)
|
||||
|
||||
{
|
||||
// Merge all operations params into one schema declaration
|
||||
let operationsParamsSchema = jsonSchemaToZod(
|
||||
operationParamsJSONSchema,
|
||||
{ name: `${operationParamsName}Schema`, type: operationParamsName }
|
||||
)
|
||||
|
||||
if (operationParamsJSONSchema.$refs.length) {
|
||||
const refSchemas = operationParamsJSONSchema.$refs.map(
|
||||
(ref) => `${getComponentName(ref)!}Schema`
|
||||
)
|
||||
|
||||
operationsParamsSchema = operationsParamsSchema.replace(
|
||||
// eslint-disable-next-line security/detect-non-literal-regexp
|
||||
new RegExp(`(${operationParamsName}Schema = .*)$`, 'm'),
|
||||
// eslint-disable-next-line unicorn/no-array-reduce
|
||||
refSchemas.reduce(
|
||||
(acc, refSchema) => `${acc}.merge(${refSchema})`,
|
||||
'$1'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
assert(
|
||||
!componentSchemas[operationParamsName],
|
||||
`Operation params name "${operationParamsName}" conflicts with component name`
|
||||
)
|
||||
operationSchemas[operationParamsName] = operationsParamsSchema
|
||||
}
|
||||
|
||||
const operationResponseJSONSchema = operationResponseJSONSchemas['200']
|
||||
if (operationResponseJSONSchema) {
|
||||
let isDuplicateDefinition = false
|
||||
|
||||
if (operationResponseJSONSchema.$ref) {
|
||||
const componentName = getComponentName(
|
||||
operationResponseJSONSchema.$ref
|
||||
)
|
||||
if (componentName === operationResponseName) {
|
||||
isDuplicateDefinition = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDuplicateDefinition) {
|
||||
const operationResponseSchema = jsonSchemaToZod(
|
||||
operationResponseJSONSchema,
|
||||
{
|
||||
name: `${operationResponseName}Schema`,
|
||||
type: operationResponseName
|
||||
}
|
||||
)
|
||||
|
||||
assert(
|
||||
!componentSchemas[operationResponseName],
|
||||
`Operation response name "${operationResponseName}" conflicts with component name`
|
||||
)
|
||||
operationSchemas[operationResponseName] = operationResponseSchema
|
||||
}
|
||||
} else {
|
||||
assert(
|
||||
!componentSchemas[operationResponseName],
|
||||
`Operation response name "${operationResponseName}" conflicts with component name`
|
||||
)
|
||||
operationSchemas[operationResponseName] =
|
||||
`export type ${operationResponseName} = undefined\n`
|
||||
}
|
||||
|
||||
// console.log(
|
||||
// JSON.stringify(
|
||||
// {
|
||||
// operationName,
|
||||
// operationParamsSources,
|
||||
// operationParamsJSONSchema
|
||||
// },
|
||||
// null,
|
||||
// 2
|
||||
// )
|
||||
// )
|
||||
|
||||
const queryParams = Object.keys(operationParamsSources).filter(
|
||||
(key) => operationParamsSources[key] === 'query'
|
||||
)
|
||||
const hasQueryParams = queryParams.length > 0
|
||||
|
||||
const bodyParams = Object.keys(operationParamsSources).filter(
|
||||
(key) => operationParamsSources[key] === 'body'
|
||||
)
|
||||
const hasBodyParams = bodyParams.length > 0
|
||||
|
||||
const formDataParams = Object.keys(operationParamsSources).filter(
|
||||
(key) => operationParamsSources[key] === 'formData'
|
||||
)
|
||||
const hasFormDataParams = formDataParams.length > 0
|
||||
|
||||
const pathParams = Object.keys(operationParamsSources).filter(
|
||||
(key) => operationParamsSources[key] === 'path'
|
||||
)
|
||||
const hasPathParams = pathParams.length > 0
|
||||
|
||||
const headersParams = Object.keys(operationParamsSources).filter(
|
||||
(key) => operationParamsSources[key] === 'headers'
|
||||
)
|
||||
const hasHeadersParams = headersParams.length > 0
|
||||
|
||||
const onlyHasOneParamsSource =
|
||||
new Set(Object.values(operationParamsSources)).size === 1
|
||||
const onlyHasPathParams = hasPathParams && onlyHasOneParamsSource
|
||||
|
||||
const pathTemplate = hasPathParams
|
||||
? '`' + path.replaceAll(/{([^}]+)}/g, '${params["$1"]}') + '`'
|
||||
: `'${path}'`
|
||||
|
||||
let description = operation.description || operation.summary
|
||||
if (description && !/[!.?]$/.test(description)) {
|
||||
description += '.'
|
||||
}
|
||||
|
||||
const aiClientMethod = `
|
||||
${description ? `/**\n * ${description}\n */` : ''}
|
||||
@aiFunction({
|
||||
name: '${operationNameSnakeCase}',
|
||||
${description ? `description: '${description}',` : ''}
|
||||
inputSchema: ${namespaceName}.${operationParamsName}Schema,
|
||||
})
|
||||
async ${operationName}(params: ${namespaceName}.${operationParamsName}): Promise<${namespaceName}.${operationResponseName}> {
|
||||
return this.ky.${method}(${pathTemplate}${
|
||||
onlyHasPathParams
|
||||
? ''
|
||||
: `, {
|
||||
${hasQueryParams ? (onlyHasOneParamsSource ? `searchParams: sanitizeSearchParams(params),` : `searchParams: sanitizeSearchParams(pick(params, '${queryParams.join("', '")}')),`) : ''}
|
||||
${hasBodyParams ? (onlyHasOneParamsSource ? `json: params,` : `json: pick(params, '${bodyParams.join("', '")}'),`) : ''}
|
||||
${hasFormDataParams ? (onlyHasOneParamsSource ? `form: params,` : `form: pick(params, '${formDataParams.join("', '")}'),`) : ''}
|
||||
${hasHeadersParams ? (onlyHasOneParamsSource ? `headers: params,` : `headers: pick(params, '${headersParams.join("', '")}'),`) : ''}
|
||||
}`
|
||||
}).json<${namespaceName}.${operationResponseName}>()
|
||||
}
|
||||
`
|
||||
|
||||
aiClientMethods.push(aiClientMethod)
|
||||
}
|
||||
}
|
||||
|
||||
const processedComponents = new Set<string>()
|
||||
const componentToRefs: Record<
|
||||
string,
|
||||
{ dereferenced: any; refs: Set<string> }
|
||||
> = {}
|
||||
|
||||
for (const ref of componentsToProcess) {
|
||||
const component = parser.$refs.get(ref)
|
||||
assert(component)
|
||||
|
||||
const resolved = new Set<string>()
|
||||
const dereferenced = dereference(component, parser.$refs)
|
||||
dereference(component, parser.$refs, resolved, 0, Number.POSITIVE_INFINITY)
|
||||
assert(dereferenced)
|
||||
|
||||
for (const ref of resolved) {
|
||||
assert(componentsToProcess.has(ref))
|
||||
}
|
||||
|
||||
componentToRefs[ref] = { dereferenced, refs: resolved }
|
||||
}
|
||||
|
||||
const sortedComponents = Object.keys(componentToRefs).sort(
|
||||
(a, b) => componentToRefs[a]!.refs.size - componentToRefs[b]!.refs.size
|
||||
)
|
||||
|
||||
for (const ref of sortedComponents) {
|
||||
const type = getComponentName(ref)
|
||||
assert(type, `Invalid ref name ${ref}`)
|
||||
|
||||
const name = `${type}Schema`
|
||||
|
||||
const { dereferenced, refs } = componentToRefs[ref]!
|
||||
if (processedComponents.has(ref)) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (const r of refs) {
|
||||
if (processedComponents.has(r)) {
|
||||
continue
|
||||
}
|
||||
|
||||
processedComponents.add(r)
|
||||
}
|
||||
|
||||
processedComponents.add(ref)
|
||||
|
||||
const schema = jsonSchemaToZod(dereferenced, { name, type })
|
||||
componentSchemas[type] = schema
|
||||
|
||||
// console.log(ref, name, dereferenced)
|
||||
}
|
||||
|
||||
// console.log(
|
||||
// '\ncomponents',
|
||||
// Array.from(componentsToProcess)
|
||||
// .map((ref) => getComponentName(ref))
|
||||
// .sort()
|
||||
// )
|
||||
|
||||
// console.log(
|
||||
// '\nmodels',
|
||||
// Object.fromEntries(
|
||||
// await Promise.all(
|
||||
// Object.entries(schemaInput).map(async ([key, value]) => {
|
||||
// return [key, await prettify(value)]
|
||||
// })
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
|
||||
const aiClientMethodsString = aiClientMethods.join('\n\n')
|
||||
|
||||
const header = `
|
||||
/**
|
||||
* This file was auto-generated from an OpenAPI spec.
|
||||
*/
|
||||
|
||||
import {
|
||||
AIFunctionsProvider,
|
||||
${aiClientMethods.length > 0 ? 'aiFunction,' : ''}
|
||||
${hasGlobalApiKeyInHeader ? 'assert,' : ''}
|
||||
${hasGlobalApiKeyInHeader ? 'getEnv,' : ''}
|
||||
${aiClientMethodsString.includes('pick(') ? 'pick,' : ''}
|
||||
${aiClientMethodsString.includes('sanitizeSearchParams(') ? 'sanitizeSearchParams,' : ''}
|
||||
} from '@agentic/core'
|
||||
import defaultKy, { type KyInstance } from 'ky'
|
||||
import { z } from 'zod'`.trim()
|
||||
|
||||
const outputTypes = (
|
||||
await prettify(
|
||||
[
|
||||
header,
|
||||
`export namespace ${namespaceName} {`,
|
||||
apiBaseUrl ? `export const apiBaseUrl = '${apiBaseUrl}'` : undefined,
|
||||
...Object.values(componentSchemas),
|
||||
...Object.values(operationSchemas),
|
||||
'}'
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n\n')
|
||||
)
|
||||
)
|
||||
.replaceAll(/z\.object\({}\)\.merge\(([^)]*)\)/g, '$1')
|
||||
.replaceAll(/\/\*\*(\S.*)\*\//g, '/** $1 */')
|
||||
|
||||
const output = await prettify(
|
||||
[
|
||||
outputTypes,
|
||||
`
|
||||
export class ${clientName} extends AIFunctionsProvider {
|
||||
protected readonly ky: KyInstance
|
||||
${hasGlobalApiKeyInHeader ? 'protected readonly apiKey: string' : ''}
|
||||
protected readonly apiBaseUrl: string
|
||||
|
||||
constructor({
|
||||
${hasGlobalApiKeyInHeader ? `apiKey = getEnv('${nameUpperCase}_API_KEY'),` : ''}
|
||||
apiBaseUrl${apiBaseUrl ? ` = ${namespaceName}.apiBaseUrl` : ''},
|
||||
ky = defaultKy
|
||||
}: {
|
||||
apiKey?: string
|
||||
apiBaseUrl?: string
|
||||
ky?: KyInstance
|
||||
} = {}) {
|
||||
${
|
||||
hasGlobalApiKeyInHeader
|
||||
? `assert(
|
||||
apiKey,
|
||||
'${clientName} missing required "apiKey" (defaults to "${nameUpperCase}_API_KEY")'
|
||||
)`
|
||||
: ''
|
||||
}
|
||||
super()
|
||||
|
||||
${hasGlobalApiKeyInHeader ? `this.apiKey = apiKey` : ''}
|
||||
this.apiBaseUrl = apiBaseUrl
|
||||
|
||||
this.ky = ky.extend({
|
||||
prefixUrl: apiBaseUrl,
|
||||
${
|
||||
hasGlobalApiKeyInHeader
|
||||
? `headers: {
|
||||
${apiKeyHeaderNames.map((name) => `'${(resolvedSecuritySchemes[name] as any).name || 'Authorization'}': ${(resolvedSecuritySchemes[name] as any).schema?.toLowerCase() === 'bearer' ? '`Bearer ${apiKey}`' : 'apiKey'}`).join(',\n')}
|
||||
},`
|
||||
: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
`,
|
||||
aiClientMethodsString,
|
||||
'}'
|
||||
].join('\n\n')
|
||||
)
|
||||
|
||||
// console.log(output)
|
||||
await fs.mkdir(destFolder, { recursive: true })
|
||||
await fs.writeFile(destFileClient, output)
|
||||
await execa('npx', ['eslint', '--fix', destFileClient])
|
||||
}
|
||||
|
||||
await main()
|
|
@ -0,0 +1,221 @@
|
|||
/**
|
||||
* This file is forked from: https://github.com/kogosoftwarellc/open-api/tree/main/packages/openapi-jsonschema-parameters
|
||||
*
|
||||
* The original code is licensed under the MIT license.
|
||||
*/
|
||||
|
||||
import { type IJsonSchema, type OpenAPI } from 'openapi-types'
|
||||
|
||||
export interface OpenAPIParametersAsJSONSchema {
|
||||
body?: IJsonSchema
|
||||
formData?: IJsonSchema
|
||||
headers?: IJsonSchema
|
||||
path?: IJsonSchema
|
||||
query?: IJsonSchema
|
||||
cookie?: IJsonSchema
|
||||
}
|
||||
|
||||
const VALIDATION_KEYWORDS = new Set([
|
||||
'additionalItems',
|
||||
'default',
|
||||
'example',
|
||||
'description',
|
||||
'enum',
|
||||
'examples',
|
||||
'exclusiveMaximum',
|
||||
'exclusiveMinimum',
|
||||
'format',
|
||||
'items',
|
||||
'maxItems',
|
||||
'maxLength',
|
||||
'maximum',
|
||||
'minItems',
|
||||
'minLength',
|
||||
'minimum',
|
||||
'multipleOf',
|
||||
'pattern',
|
||||
'title',
|
||||
'type',
|
||||
'uniqueItems'
|
||||
])
|
||||
|
||||
const SUBSCHEMA_KEYWORDS = [
|
||||
'additionalItems',
|
||||
'items',
|
||||
'contains',
|
||||
'additionalProperties',
|
||||
'propertyNames',
|
||||
'not'
|
||||
]
|
||||
|
||||
const SUBSCHEMA_ARRAY_KEYWORDS = ['items', 'allOf', 'anyOf', 'oneOf']
|
||||
|
||||
const SUBSCHEMA_OBJECT_KEYWORDS = [
|
||||
'definitions',
|
||||
'properties',
|
||||
'patternProperties',
|
||||
'dependencies'
|
||||
]
|
||||
|
||||
export function convertParametersToJSONSchema(
|
||||
parameters: OpenAPI.Parameters
|
||||
): OpenAPIParametersAsJSONSchema {
|
||||
const parametersSchema: OpenAPIParametersAsJSONSchema = {}
|
||||
const bodySchema = getBodySchema(parameters)
|
||||
const formDataSchema = getSchema(parameters, 'formData')
|
||||
const headerSchema = getSchema(parameters, 'header')
|
||||
const pathSchema = getSchema(parameters, 'path')
|
||||
const querySchema = getSchema(parameters, 'query')
|
||||
const cookieSchema = getSchema(parameters, 'cookie')
|
||||
|
||||
if (bodySchema) {
|
||||
parametersSchema.body = bodySchema
|
||||
}
|
||||
|
||||
if (formDataSchema) {
|
||||
parametersSchema.formData = formDataSchema
|
||||
}
|
||||
|
||||
if (headerSchema) {
|
||||
parametersSchema.headers = headerSchema
|
||||
}
|
||||
|
||||
if (pathSchema) {
|
||||
parametersSchema.path = pathSchema
|
||||
}
|
||||
|
||||
if (querySchema) {
|
||||
parametersSchema.query = querySchema
|
||||
}
|
||||
|
||||
if (cookieSchema) {
|
||||
parametersSchema.cookie = cookieSchema
|
||||
}
|
||||
|
||||
return parametersSchema
|
||||
}
|
||||
|
||||
function copyValidationKeywords(src: any) {
|
||||
const dst: any = {}
|
||||
for (let i = 0, keys = Object.keys(src), len = keys.length; i < len; i++) {
|
||||
const keyword = keys[i]
|
||||
if (!keyword) continue
|
||||
|
||||
if (VALIDATION_KEYWORDS.has(keyword) || keyword.slice(0, 2) === 'x-') {
|
||||
dst[keyword] = src[keyword]
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
function handleNullable(schema: IJsonSchema) {
|
||||
return { anyOf: [schema, { type: 'null' }] }
|
||||
}
|
||||
|
||||
function handleNullableSchema(schema: any) {
|
||||
if (typeof schema !== 'object' || schema === null) {
|
||||
return schema
|
||||
}
|
||||
|
||||
const newSchema = { ...schema }
|
||||
|
||||
for (const keyword of SUBSCHEMA_KEYWORDS) {
|
||||
if (
|
||||
typeof schema[keyword] === 'object' &&
|
||||
schema[keyword] !== null &&
|
||||
!Array.isArray(schema[keyword])
|
||||
) {
|
||||
newSchema[keyword] = handleNullableSchema(schema[keyword])
|
||||
}
|
||||
}
|
||||
|
||||
for (const keyword of SUBSCHEMA_ARRAY_KEYWORDS) {
|
||||
if (Array.isArray(schema[keyword])) {
|
||||
newSchema[keyword] = schema[keyword].map(handleNullableSchema)
|
||||
}
|
||||
}
|
||||
|
||||
for (const keyword of SUBSCHEMA_OBJECT_KEYWORDS) {
|
||||
if (typeof schema[keyword] === 'object' && schema[keyword] !== null) {
|
||||
newSchema[keyword] = { ...schema[keyword] }
|
||||
for (const prop of Object.keys(schema[keyword])) {
|
||||
newSchema[keyword][prop] = handleNullableSchema(schema[keyword][prop])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete newSchema.$ref
|
||||
|
||||
if (schema.nullable) {
|
||||
delete newSchema.nullable
|
||||
return handleNullable(newSchema)
|
||||
}
|
||||
return newSchema
|
||||
}
|
||||
|
||||
function getBodySchema(parameters: any[]) {
|
||||
let bodySchema = parameters.find((param) => {
|
||||
return param.in === 'body' && param.schema
|
||||
})
|
||||
|
||||
if (bodySchema) {
|
||||
bodySchema = bodySchema.schema
|
||||
}
|
||||
|
||||
return bodySchema
|
||||
}
|
||||
|
||||
function getSchema(parameters: any[], type: string) {
|
||||
const params = parameters.filter(byIn(type))
|
||||
let schema: any
|
||||
|
||||
if (params.length) {
|
||||
schema = { type: 'object', properties: {} }
|
||||
|
||||
for (const param of params) {
|
||||
let paramSchema = copyValidationKeywords(param)
|
||||
|
||||
if ('schema' in param) {
|
||||
paramSchema = {
|
||||
...paramSchema,
|
||||
...handleNullableSchema(param.schema)
|
||||
}
|
||||
if ('examples' in param) {
|
||||
paramSchema.examples = getExamples(param.examples)
|
||||
}
|
||||
schema.properties[param.name] = paramSchema
|
||||
} else {
|
||||
if ('examples' in paramSchema) {
|
||||
paramSchema.examples = getExamples(paramSchema.examples)
|
||||
}
|
||||
schema.properties[param.name] = param.nullable
|
||||
? handleNullable(paramSchema)
|
||||
: paramSchema
|
||||
}
|
||||
}
|
||||
|
||||
schema.required = getRequiredParams(params)
|
||||
}
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
function getRequiredParams(parameters: any[]) {
|
||||
return parameters.filter(byRequired).map(toName)
|
||||
}
|
||||
|
||||
function getExamples(exampleSchema: any) {
|
||||
return Object.keys(exampleSchema).map((k) => exampleSchema[k].value)
|
||||
}
|
||||
|
||||
function byIn(str: string) {
|
||||
return (param: any) => param.in === str && param.type !== 'file'
|
||||
}
|
||||
|
||||
function byRequired(param: any) {
|
||||
return !!param.required
|
||||
}
|
||||
|
||||
function toName(param: any) {
|
||||
return param.name
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
import type SwaggerParser from '@apidevtools/swagger-parser'
|
||||
import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types'
|
||||
import { assert } from '@agentic/core'
|
||||
import {
|
||||
type JsonSchema,
|
||||
jsonSchemaToZod as jsonSchemaToZodImpl
|
||||
} from 'json-schema-to-zod'
|
||||
import * as prettier from 'prettier'
|
||||
|
||||
export function prettify(source: string): Promise<string> {
|
||||
return prettier.format(source, {
|
||||
parser: 'typescript',
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
jsxSingleQuote: true,
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: false,
|
||||
arrowParens: 'always',
|
||||
trailingComma: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
export function titleCase(identifier: string): string {
|
||||
return `${identifier.slice(0, 1).toUpperCase()}${identifier.slice(1)}`
|
||||
}
|
||||
|
||||
export function unTitleCase(identifier: string): string {
|
||||
return `${identifier.slice(0, 1).toLowerCase()}${identifier.slice(1)}`
|
||||
}
|
||||
|
||||
export function getAndResolve<T extends object = object>(
|
||||
obj: any,
|
||||
keys: string[],
|
||||
refs: SwaggerParser.$Refs,
|
||||
resolved?: Set<string>,
|
||||
depth = 0,
|
||||
maxDepth = 0
|
||||
): T | null {
|
||||
if (obj === undefined) return null
|
||||
if (typeof obj !== 'object') return null
|
||||
|
||||
if (!keys.length) {
|
||||
return dereference(obj, refs, resolved, depth, maxDepth) as T
|
||||
}
|
||||
|
||||
if (obj.$ref) {
|
||||
const derefed = refs.get(obj.$ref)
|
||||
resolved?.add(obj.$ref)
|
||||
if (!derefed) {
|
||||
return null
|
||||
}
|
||||
obj = derefed
|
||||
}
|
||||
|
||||
const key = keys[0]!
|
||||
const value = obj[key]
|
||||
keys = keys.slice(1)
|
||||
if (value === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
return getAndResolve<T>(value, keys, refs, resolved, depth, maxDepth)
|
||||
}
|
||||
|
||||
export function dereferenceFull<T extends object = object>(
|
||||
obj: T,
|
||||
refs: SwaggerParser.$Refs,
|
||||
resolved?: Set<string>
|
||||
): Exclude<T, OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject> {
|
||||
return dereference(obj, refs, resolved, 0, Number.POSITIVE_INFINITY) as any
|
||||
}
|
||||
|
||||
export function dereference<T extends object = object>(
|
||||
obj: T,
|
||||
refs: SwaggerParser.$Refs,
|
||||
resolved?: Set<string>,
|
||||
depth = 0,
|
||||
maxDepth = 1
|
||||
): T {
|
||||
if (!obj) return obj
|
||||
|
||||
if (depth >= maxDepth) {
|
||||
return obj
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) =>
|
||||
dereference(item, refs, resolved, depth + 1, maxDepth)
|
||||
) as T
|
||||
} else if (typeof obj === 'object') {
|
||||
if ('$ref' in obj) {
|
||||
const ref = obj.$ref as string
|
||||
const derefed = refs.get(ref)
|
||||
if (!derefed) {
|
||||
return obj
|
||||
}
|
||||
resolved?.add(ref)
|
||||
derefed.title = ref.split('/').pop()!
|
||||
return dereference(derefed, refs, resolved, depth + 1, maxDepth)
|
||||
} else {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).map(([key, value]) => [
|
||||
key,
|
||||
dereference(value, refs, resolved, depth + 1, maxDepth)
|
||||
])
|
||||
) as T
|
||||
}
|
||||
} else {
|
||||
return obj
|
||||
}
|
||||
}
|
||||
|
||||
export function jsonSchemaToZod(
|
||||
schema: JsonSchema,
|
||||
{
|
||||
name,
|
||||
type
|
||||
}: {
|
||||
name?: string
|
||||
type?: string
|
||||
} = {}
|
||||
): string {
|
||||
return jsonSchemaToZodImpl(schema, {
|
||||
name,
|
||||
module: 'esm',
|
||||
withJsdocs: true,
|
||||
type: type ?? true,
|
||||
noImport: true,
|
||||
parserOverride: (schema, _refs) => {
|
||||
if ('$ref' in schema) {
|
||||
const ref = schema.$ref as string
|
||||
if (!ref) return
|
||||
|
||||
const name = getComponentName(ref)
|
||||
if (!name) return
|
||||
|
||||
return `${name}Schema`
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const reservedWords = new Set([
|
||||
'Error',
|
||||
'Class',
|
||||
'Object',
|
||||
'interface',
|
||||
'type',
|
||||
'default',
|
||||
'switch',
|
||||
'for',
|
||||
'break',
|
||||
'case',
|
||||
'if',
|
||||
'else',
|
||||
'while',
|
||||
'do',
|
||||
'for',
|
||||
'return',
|
||||
'continue',
|
||||
'function',
|
||||
'console',
|
||||
'window',
|
||||
'global',
|
||||
'import',
|
||||
'export',
|
||||
'namespace',
|
||||
'using',
|
||||
'require',
|
||||
'module',
|
||||
'process',
|
||||
'async',
|
||||
'await',
|
||||
'const',
|
||||
'let',
|
||||
'var',
|
||||
'void',
|
||||
'undefined',
|
||||
'abstract',
|
||||
'extends',
|
||||
'implements',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'Infinity',
|
||||
'Nan',
|
||||
'Math',
|
||||
'Date',
|
||||
'RegExp',
|
||||
'JSON',
|
||||
'Buffer',
|
||||
'Promise',
|
||||
'Symbol',
|
||||
'Map',
|
||||
'Set',
|
||||
'WeakMap',
|
||||
'WeakSet',
|
||||
'Array',
|
||||
'Object',
|
||||
'Boolean',
|
||||
'Number',
|
||||
'String',
|
||||
'Function',
|
||||
'Symbol'
|
||||
])
|
||||
|
||||
export function getComponentName(ref: string) {
|
||||
const name0 = ref.split('/').pop()!
|
||||
assert(name0, `Invalid ref name ${ref}`)
|
||||
|
||||
const name1 = titleCase(name0)
|
||||
assert(name1, `Invalid ref name ${ref}`)
|
||||
|
||||
if (reservedWords.has(name1)) {
|
||||
return `${name1}Type`
|
||||
}
|
||||
|
||||
return name1
|
||||
}
|
||||
|
||||
export function getOperationParamsName(
|
||||
operationName: string,
|
||||
schemas?: Record<string, string>
|
||||
) {
|
||||
const name = `${titleCase(operationName)}Params`
|
||||
if (!schemas) return name
|
||||
|
||||
let tempName = name
|
||||
let index = 2
|
||||
while (schemas[tempName]) {
|
||||
tempName = `${name}${index}`
|
||||
++index
|
||||
}
|
||||
|
||||
return tempName
|
||||
}
|
||||
|
||||
export function getOperationResponseName(
|
||||
operationName: string,
|
||||
schemas?: Record<string, string>
|
||||
) {
|
||||
const name = `${titleCase(operationName)}Response`
|
||||
if (!schemas) return name
|
||||
|
||||
let tempName = name
|
||||
let index = 2
|
||||
while (schemas[tempName]) {
|
||||
tempName = `${name}${index}`
|
||||
++index
|
||||
}
|
||||
|
||||
return tempName
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "@agentic/tsconfig/base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
231
pnpm-lock.yaml
231
pnpm-lock.yaml
|
@ -160,7 +160,7 @@ importers:
|
|||
version: 5.8.2
|
||||
vitest:
|
||||
specifier: 3.0.9
|
||||
version: 3.0.9(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0)
|
||||
version: 3.0.9(@types/debug@4.1.12)(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0)
|
||||
zod:
|
||||
specifier: 'catalog:'
|
||||
version: 3.24.2
|
||||
|
@ -814,6 +814,40 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../tsconfig
|
||||
|
||||
packages/openapi-to-ts-client:
|
||||
dependencies:
|
||||
'@agentic/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@apidevtools/swagger-parser':
|
||||
specifier: ^10.1.1
|
||||
version: 10.1.1(openapi-types@12.1.3)
|
||||
camelcase:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
decamelize:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
execa:
|
||||
specifier: ^9.5.2
|
||||
version: 9.5.2
|
||||
json-schema-to-zod:
|
||||
specifier: ^2.6.0
|
||||
version: 2.6.0
|
||||
openapi-types:
|
||||
specifier: ^12.1.3
|
||||
version: 12.1.3
|
||||
zod:
|
||||
specifier: 'catalog:'
|
||||
version: 3.24.2
|
||||
devDependencies:
|
||||
'@agentic/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:../tsconfig
|
||||
ky:
|
||||
specifier: 'catalog:'
|
||||
version: 1.7.5
|
||||
|
||||
packages/people-data-labs:
|
||||
dependencies:
|
||||
'@agentic/core':
|
||||
|
@ -1374,6 +1408,22 @@ packages:
|
|||
resolution: {integrity: sha512-IQD9wkVReKAhsEAbDjh/0KrBGTEXelqZLpOBRDaIRvlzZ9sjmUP+gKbpvzyJnei2JHQiE8JAgj7YcNloINbGBw==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.7.2':
|
||||
resolution: {integrity: sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@apidevtools/openapi-schemas@2.1.0':
|
||||
resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@apidevtools/swagger-methods@3.0.2':
|
||||
resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
|
||||
|
||||
'@apidevtools/swagger-parser@10.1.1':
|
||||
resolution: {integrity: sha512-u/kozRnsPO/x8QtKYJOqoGtC4kH6yg1lfYkB9Au0WhYB0FNLpyFusttQtvhlwjtG3rOwiRz4D8DnnXa8iEpIKA==}
|
||||
peerDependencies:
|
||||
openapi-types: '>=7'
|
||||
|
||||
'@aws-crypto/crc32@3.0.0':
|
||||
resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==}
|
||||
|
||||
|
@ -1935,6 +1985,9 @@ packages:
|
|||
'@js-sdsl/ordered-map@4.4.2':
|
||||
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
|
||||
|
||||
'@jsdevtools/ono@7.1.3':
|
||||
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
|
||||
|
||||
'@langchain/core@0.3.42':
|
||||
resolution: {integrity: sha512-pT/jC5lqWK3YGDq8dQwgKoa6anqAhMtG1x5JbnrOj9NdaLeBbCKBDQ+/Ykzk3nZ8o+0UMsaXNZo7IVL83VVjHg==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -2972,6 +3025,9 @@ packages:
|
|||
'@rushstack/eslint-patch@1.10.4':
|
||||
resolution: {integrity: sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==}
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1':
|
||||
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
|
||||
|
||||
'@selderee/plugin-htmlparser2@0.11.0':
|
||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||
|
||||
|
@ -2979,6 +3035,10 @@ packages:
|
|||
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sindresorhus/merge-streams@4.0.0':
|
||||
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@smithy/abort-controller@4.0.1':
|
||||
resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
@ -3202,6 +3262,9 @@ packages:
|
|||
'@types/connect@3.4.38':
|
||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
|
||||
'@types/diff-match-patch@1.0.36':
|
||||
resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
|
||||
|
||||
|
@ -3227,6 +3290,9 @@ packages:
|
|||
'@types/memcached@2.2.10':
|
||||
resolution: {integrity: sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==}
|
||||
|
||||
'@types/ms@2.1.0':
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
|
||||
'@types/mysql@2.15.26':
|
||||
resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
|
||||
|
||||
|
@ -3441,6 +3507,14 @@ packages:
|
|||
zod:
|
||||
optional: true
|
||||
|
||||
ajv-draft-04@1.0.0:
|
||||
resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
|
||||
peerDependencies:
|
||||
ajv: ^8.5.0
|
||||
peerDependenciesMeta:
|
||||
ajv:
|
||||
optional: true
|
||||
|
||||
ajv-formats@3.0.1:
|
||||
resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
|
||||
peerDependencies:
|
||||
|
@ -3653,6 +3727,9 @@ packages:
|
|||
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-me-maybe@1.0.2:
|
||||
resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -3661,6 +3738,10 @@ packages:
|
|||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
camelcase@8.0.0:
|
||||
resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
caniuse-lite@1.0.30001678:
|
||||
resolution: {integrity: sha512-RR+4U/05gNtps58PEBDZcPWTgEO2MBeoPZ96aQcjmfkBWRIDfN451fW2qyDA9/+HohLLIL5GqiMwA+IB1pWarw==}
|
||||
|
||||
|
@ -3854,6 +3935,10 @@ packages:
|
|||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
decamelize@6.0.0:
|
||||
resolution: {integrity: sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
decimal.js@10.5.0:
|
||||
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
|
||||
|
||||
|
@ -4275,6 +4360,10 @@ packages:
|
|||
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
|
||||
engines: {node: '>=16.17'}
|
||||
|
||||
execa@9.5.2:
|
||||
resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==}
|
||||
engines: {node: ^18.19.0 || >=20.5.0}
|
||||
|
||||
expect-type@1.2.0:
|
||||
resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -4344,6 +4433,10 @@ packages:
|
|||
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||
engines: {node: ^12.20 || >= 14.13}
|
||||
|
||||
figures@6.1.0:
|
||||
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
@ -4490,6 +4583,10 @@ packages:
|
|||
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
get-stream@9.0.1:
|
||||
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-symbol-description@1.0.2:
|
||||
resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -4621,6 +4718,10 @@ packages:
|
|||
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
|
||||
human-signals@8.0.0:
|
||||
resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
humanize-ms@1.2.1:
|
||||
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
|
||||
|
||||
|
@ -4805,6 +4906,10 @@ packages:
|
|||
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
is-stream@4.0.1:
|
||||
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-string@1.0.7:
|
||||
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -4817,6 +4922,10 @@ packages:
|
|||
resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-unicode-supported@2.1.0:
|
||||
resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-weakmap@2.0.2:
|
||||
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -5031,6 +5140,7 @@ packages:
|
|||
|
||||
libsql@0.4.7:
|
||||
resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==}
|
||||
cpu: [x64, arm64, wasm32]
|
||||
os: [darwin, linux, win32]
|
||||
|
||||
lilconfig@3.1.3:
|
||||
|
@ -5281,6 +5391,10 @@ packages:
|
|||
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
nypm@0.6.0:
|
||||
resolution: {integrity: sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==}
|
||||
engines: {node: ^14.16.0 || >=16.10.0}
|
||||
|
@ -5456,6 +5570,10 @@ packages:
|
|||
resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
parse-ms@4.0.0:
|
||||
resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
parseley@0.12.1:
|
||||
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
|
||||
|
||||
|
@ -5622,6 +5740,10 @@ packages:
|
|||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
pretty-ms@9.2.0:
|
||||
resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
process-warning@4.0.1:
|
||||
resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==}
|
||||
|
||||
|
@ -6046,6 +6168,10 @@ packages:
|
|||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-final-newline@4.0.0:
|
||||
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -6342,6 +6468,10 @@ packages:
|
|||
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
unicorn-magic@0.3.0:
|
||||
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
universal-github-app-jwt@2.2.0:
|
||||
resolution: {integrity: sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ==}
|
||||
|
||||
|
@ -6608,6 +6738,10 @@ packages:
|
|||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yoctocolors@2.1.1:
|
||||
resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
zod-to-json-schema@3.24.3:
|
||||
resolution: {integrity: sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A==}
|
||||
peerDependencies:
|
||||
|
@ -6679,6 +6813,27 @@ snapshots:
|
|||
'@anush008/tokenizers-linux-x64-gnu': 0.0.0
|
||||
'@anush008/tokenizers-win32-x64-msvc': 0.0.0
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.7.2':
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.15
|
||||
js-yaml: 4.1.0
|
||||
|
||||
'@apidevtools/openapi-schemas@2.1.0': {}
|
||||
|
||||
'@apidevtools/swagger-methods@3.0.2': {}
|
||||
|
||||
'@apidevtools/swagger-parser@10.1.1(openapi-types@12.1.3)':
|
||||
dependencies:
|
||||
'@apidevtools/json-schema-ref-parser': 11.7.2
|
||||
'@apidevtools/openapi-schemas': 2.1.0
|
||||
'@apidevtools/swagger-methods': 3.0.2
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
ajv: 8.17.1
|
||||
ajv-draft-04: 1.0.0(ajv@8.17.1)
|
||||
call-me-maybe: 1.0.2
|
||||
openapi-types: 12.1.3
|
||||
|
||||
'@aws-crypto/crc32@3.0.0':
|
||||
dependencies:
|
||||
'@aws-crypto/util': 3.0.0
|
||||
|
@ -7482,6 +7637,8 @@ snapshots:
|
|||
|
||||
'@js-sdsl/ordered-map@4.4.2': {}
|
||||
|
||||
'@jsdevtools/ono@7.1.3': {}
|
||||
|
||||
'@langchain/core@0.3.42(openai@4.87.3(encoding@0.1.13)(ws@8.18.0)(zod@3.24.2))':
|
||||
dependencies:
|
||||
'@cfworker/json-schema': 4.1.1
|
||||
|
@ -8797,6 +8954,8 @@ snapshots:
|
|||
|
||||
'@rushstack/eslint-patch@1.10.4': {}
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1': {}
|
||||
|
||||
'@selderee/plugin-htmlparser2@0.11.0':
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
|
@ -8804,6 +8963,8 @@ snapshots:
|
|||
|
||||
'@sindresorhus/merge-streams@2.3.0': {}
|
||||
|
||||
'@sindresorhus/merge-streams@4.0.0': {}
|
||||
|
||||
'@smithy/abort-controller@4.0.1':
|
||||
dependencies:
|
||||
'@smithy/types': 4.1.0
|
||||
|
@ -9142,6 +9303,11 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
optional: true
|
||||
|
||||
'@types/diff-match-patch@1.0.36': {}
|
||||
|
||||
'@types/estree@1.0.6': {}
|
||||
|
@ -9162,6 +9328,9 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@types/ms@2.1.0':
|
||||
optional: true
|
||||
|
||||
'@types/mysql@2.15.26':
|
||||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
@ -9436,6 +9605,10 @@ snapshots:
|
|||
react: 18.3.1
|
||||
zod: 3.24.2
|
||||
|
||||
ajv-draft-04@1.0.0(ajv@8.17.1):
|
||||
optionalDependencies:
|
||||
ajv: 8.17.1
|
||||
|
||||
ajv-formats@3.0.1(ajv@8.17.1):
|
||||
optionalDependencies:
|
||||
ajv: 8.17.1
|
||||
|
@ -9697,10 +9870,14 @@ snapshots:
|
|||
call-bind-apply-helpers: 1.0.2
|
||||
get-intrinsic: 1.2.7
|
||||
|
||||
call-me-maybe@1.0.2: {}
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase@6.3.0: {}
|
||||
|
||||
camelcase@8.0.0: {}
|
||||
|
||||
caniuse-lite@1.0.30001678: {}
|
||||
|
||||
chai@5.2.0:
|
||||
|
@ -9883,6 +10060,8 @@ snapshots:
|
|||
|
||||
decamelize@1.2.0: {}
|
||||
|
||||
decamelize@6.0.0: {}
|
||||
|
||||
decimal.js@10.5.0: {}
|
||||
|
||||
decircular@0.1.1: {}
|
||||
|
@ -10472,6 +10651,21 @@ snapshots:
|
|||
signal-exit: 4.1.0
|
||||
strip-final-newline: 3.0.0
|
||||
|
||||
execa@9.5.2:
|
||||
dependencies:
|
||||
'@sindresorhus/merge-streams': 4.0.0
|
||||
cross-spawn: 7.0.6
|
||||
figures: 6.1.0
|
||||
get-stream: 9.0.1
|
||||
human-signals: 8.0.0
|
||||
is-plain-obj: 4.1.0
|
||||
is-stream: 4.0.1
|
||||
npm-run-path: 6.0.0
|
||||
pretty-ms: 9.2.0
|
||||
signal-exit: 4.1.0
|
||||
strip-final-newline: 4.0.0
|
||||
yoctocolors: 2.1.1
|
||||
|
||||
expect-type@1.2.0: {}
|
||||
|
||||
express@4.21.2:
|
||||
|
@ -10570,6 +10764,10 @@ snapshots:
|
|||
node-domexception: 1.0.0
|
||||
web-streams-polyfill: 3.3.3
|
||||
|
||||
figures@6.1.0:
|
||||
dependencies:
|
||||
is-unicode-supported: 2.1.0
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
dependencies:
|
||||
flat-cache: 3.2.0
|
||||
|
@ -10740,6 +10938,11 @@ snapshots:
|
|||
|
||||
get-stream@8.0.1: {}
|
||||
|
||||
get-stream@9.0.1:
|
||||
dependencies:
|
||||
'@sec-ant/readable-stream': 0.4.1
|
||||
is-stream: 4.0.1
|
||||
|
||||
get-symbol-description@1.0.2:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
|
@ -10902,6 +11105,8 @@ snapshots:
|
|||
|
||||
human-signals@5.0.0: {}
|
||||
|
||||
human-signals@8.0.0: {}
|
||||
|
||||
humanize-ms@1.2.1:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
@ -11060,6 +11265,8 @@ snapshots:
|
|||
|
||||
is-stream@3.0.0: {}
|
||||
|
||||
is-stream@4.0.1: {}
|
||||
|
||||
is-string@1.0.7:
|
||||
dependencies:
|
||||
has-tostringtag: 1.0.2
|
||||
|
@ -11072,6 +11279,8 @@ snapshots:
|
|||
dependencies:
|
||||
which-typed-array: 1.1.15
|
||||
|
||||
is-unicode-supported@2.1.0: {}
|
||||
|
||||
is-weakmap@2.0.2: {}
|
||||
|
||||
is-weakref@1.0.2:
|
||||
|
@ -11477,6 +11686,11 @@ snapshots:
|
|||
dependencies:
|
||||
path-key: 4.0.0
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
unicorn-magic: 0.3.0
|
||||
|
||||
nypm@0.6.0:
|
||||
dependencies:
|
||||
citty: 0.1.6
|
||||
|
@ -11667,6 +11881,8 @@ snapshots:
|
|||
index-to-position: 0.1.2
|
||||
type-fest: 4.35.0
|
||||
|
||||
parse-ms@4.0.0: {}
|
||||
|
||||
parseley@0.12.1:
|
||||
dependencies:
|
||||
leac: 0.6.0
|
||||
|
@ -11806,6 +12022,10 @@ snapshots:
|
|||
|
||||
prettier@3.5.3: {}
|
||||
|
||||
pretty-ms@9.2.0:
|
||||
dependencies:
|
||||
parse-ms: 4.0.0
|
||||
|
||||
process-warning@4.0.1: {}
|
||||
|
||||
process@0.11.10: {}
|
||||
|
@ -12317,6 +12537,8 @@ snapshots:
|
|||
|
||||
strip-final-newline@3.0.0: {}
|
||||
|
||||
strip-final-newline@4.0.0: {}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
dependencies:
|
||||
min-indent: 1.0.1
|
||||
|
@ -12602,6 +12824,8 @@ snapshots:
|
|||
|
||||
unicorn-magic@0.1.0: {}
|
||||
|
||||
unicorn-magic@0.3.0: {}
|
||||
|
||||
universal-github-app-jwt@2.2.0: {}
|
||||
|
||||
universal-user-agent@7.0.2: {}
|
||||
|
@ -12670,7 +12894,7 @@ snapshots:
|
|||
tsx: 4.19.3
|
||||
yaml: 2.7.0
|
||||
|
||||
vitest@3.0.9(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0):
|
||||
vitest@3.0.9(@types/debug@4.1.12)(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0):
|
||||
dependencies:
|
||||
'@vitest/expect': 3.0.9
|
||||
'@vitest/mocker': 3.0.9(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0))
|
||||
|
@ -12693,6 +12917,7 @@ snapshots:
|
|||
vite-node: 3.0.9(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.3)(yaml@2.7.0)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 22.13.10
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
|
@ -12860,6 +13085,8 @@ snapshots:
|
|||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
yoctocolors@2.1.1: {}
|
||||
|
||||
zod-to-json-schema@3.24.3(zod@3.24.2):
|
||||
dependencies:
|
||||
zod: 3.24.2
|
||||
|
|
Ładowanie…
Reference in New Issue