refactor: ai langchain (#1732)

* chore: init langchain

Signed-off-by: Innei <i@innei.in>

* feat: langchain function call

Signed-off-by: Innei <i@innei.in>

* fix: update

Signed-off-by: Innei <i@innei.in>

* update

Signed-off-by: Innei <i@innei.in>

---------

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-05-28 20:36:36 +08:00 committed by GitHub
parent b187cac557
commit a043cfa408
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 556 additions and 89 deletions

View File

@ -59,6 +59,7 @@
"@fastify/multipart": "8.2.0",
"@fastify/static": "7.0.4",
"@innei/next-async": "0.3.0",
"@langchain/openai": "0.0.33",
"@mx-space/external": "workspace:*",
"@nestjs/cache-manager": "2.2.2",
"@nestjs/common": "10.3.8",
@ -98,6 +99,7 @@
"json5": "2.2.3",
"jsonwebtoken": "9.0.2",
"jszip": "3.10.1",
"langchain": "0.2.0",
"linkedom": "0.18.0",
"lodash": "^4.17.21",
"lru-cache": "10.2.2",
@ -131,6 +133,7 @@
"zx-cjs": "7.0.7-0"
},
"devDependencies": {
"@langchain/core": "0.2.0",
"@nestjs/cli": "10.3.2",
"@nestjs/schematics": "10.1.1",
"@nestjs/testing": "10.3.8",

View File

@ -3,6 +3,7 @@ import removeMdCodeblock from 'remove-md-codeblock'
import { Injectable, Logger } from '@nestjs/common'
import { OnEvent } from '@nestjs/event-emitter'
import { JsonOutputFunctionsParser } from 'langchain/output_parsers'
import { BizException } from '~/common/exceptions/biz.exception'
import { BusinessEvents } from '~/constants/business-event.constant'
import { CollectionRefTypes } from '~/constants/db.constant'
@ -14,11 +15,10 @@ import { transformDataToPaginate } from '~/transformers/paginate.transformer'
import { md5 } from '~/utils'
import { ConfigsService } from '../../configs/configs.service'
import { DEFAULT_SUMMARY_LANG, LANGUAGE_CODE_TO_NAME } from '../ai.constants'
import { DEFAULT_SUMMARY_LANG } from '../ai.constants'
import { AiService } from '../ai.service'
import { AISummaryModel } from './ai-summary.model'
import type { PagerDto } from '~/shared/dto/pager.dto'
@Injectable()
export class AiSummaryService {
private readonly logger: Logger
@ -39,19 +39,62 @@ export class AiSummaryService {
private serializeText(text: string) {
return removeMdCodeblock(text)
}
async generateSummaryByOpenAI(
articleId: string,
lang = DEFAULT_SUMMARY_LANG,
) {
private async summaryChain(articleId: string, lang = DEFAULT_SUMMARY_LANG) {
const {
ai: { enableSummary, openAiPreferredModel },
ai: { enableSummary },
} = await this.configService.waitForConfigReady()
if (!enableSummary) {
throw new BizException(ErrorCodeEnum.AINotEnabled)
}
const openai = await this.aiService.getOpenAiClient()
const openai = await this.aiService.getOpenAiChain()
const article = await this.databaseService.findGlobalById(articleId)
if (!article || article.type === CollectionRefTypes.Recently) {
throw new BizException(ErrorCodeEnum.ContentNotFoundCantProcess)
}
const parser = new JsonOutputFunctionsParser()
const runnable = openai
.bind({
functions: [
{
name: 'extractor',
parameters: {
type: 'object',
properties: {
summary: {
type: 'string',
description: `The summary of the input text in the natural language ${lang}, and the length of the summary is less than 150 words.`,
},
},
required: ['summary'],
},
},
],
function_call: { name: 'extractor' },
})
.pipe(parser)
const result = await runnable.invoke([
this.serializeText(article.document.text),
])
return (result as any).summary
}
async generateSummaryByOpenAI(
articleId: string,
lang = DEFAULT_SUMMARY_LANG,
) {
const {
ai: { enableSummary },
} = await this.configService.waitForConfigReady()
if (!enableSummary) {
throw new BizException(ErrorCodeEnum.AINotEnabled)
}
const article = await this.databaseService.findGlobalById(articleId)
if (!article) {
@ -84,35 +127,14 @@ export class AiSummaryService {
this.cachedTaskId2AiPromise.set(taskId, taskPromise)
return await taskPromise
async function handle(
this: AiSummaryService,
id: string,
text: string,
title: string,
) {
async function handle(this: AiSummaryService, id: string, text: string) {
// 等待 30s
await redis.set(taskId, 'processing', 'EX', 30)
const completion = await openai.chat.completions.create({
messages: [
{
role: 'user',
content: `Summarize this article in ${LANGUAGE_CODE_TO_NAME[lang] || 'Chinese'} to 150 words:
"${text}"
CONCISE SUMMARY:`,
},
],
model: openAiPreferredModel,
})
const summary = await this.summaryChain(id, lang)
await redis.del(taskId)
const summary = completion.choices[0].message.content
this.logger.log(
`OpenAI 生成文章 ${id}${title}」的摘要花费了 ${completion.usage?.total_tokens}token`,
)
const contentMd5 = md5(text)
const doc = await this.aiSummaryModel.create({

View File

@ -1,55 +1,72 @@
import { Injectable, Logger } from '@nestjs/common'
import { ConfigsService } from '~/modules/configs/configs.service'
import { safeJSONParse } from '~/utils'
import { BizException } from '~/common/exceptions/biz.exception'
import { ErrorCodeEnum } from '~/constants/error-code.constant'
import { JsonOutputFunctionsParser } from 'langchain/output_parsers'
import { AiService } from '../ai.service'
import type { FunctionDefinition } from '@langchain/core/language_models/base'
@Injectable()
export class AiWriterService {
private readonly logger: Logger
constructor(
private readonly configService: ConfigsService,
private readonly aiService: AiService,
) {
constructor(private readonly aiService: AiService) {
this.logger = new Logger(AiWriterService.name)
}
async queryOpenAI(prompt: string): Promise<any> {
const openai = await this.aiService.getOpenAiClient()
const { openAiPreferredModel } = await this.configService.get('ai')
const result = await openai.chat.completions.create({
model: openAiPreferredModel,
messages: [{ role: 'user', content: prompt }],
})
const content = result.choices[0].message.content || ''
this.logger.log(
`查询 OpenAI 返回结果:${content} 花费了 ${result.usage?.total_tokens} 个 token`,
)
const json = safeJSONParse(content)
if (!json) {
throw new BizException(ErrorCodeEnum.AIResultParsingError)
async queryByFunctionSchema(
text: string,
parameters: FunctionDefinition['parameters'],
) {
const functionSchema: FunctionDefinition = {
name: 'extractor',
description: 'Extracts fields from the input.',
parameters,
}
return json
const model = await this.aiService.getOpenAiChain()
const parser = new JsonOutputFunctionsParser()
const runnable = model
.bind({
functions: [functionSchema],
function_call: { name: 'extractor' },
})
.pipe(parser)
const result = await runnable.invoke([text])
return result
}
async generateTitleAndSlugByOpenAI(text: string) {
return this
.queryOpenAI(`Please give the following text a title in the same language as the text and a slug in English, the output format is JSON. {title:string, slug:string}:
"${text}"
RESULT:`)
return this.queryByFunctionSchema(text, {
type: 'object',
properties: {
title: {
type: 'string',
description:
'The title of the article generated from the input text, the natural language of the title should be the same as the natural language of the input text',
},
slug: {
type: 'string',
description:
'The slug is named after the text entered, and is in English and conforms to url specifications',
},
lang: {
type: 'string',
description: 'The natural language of the input text',
},
},
required: ['title', 'slug', 'lang'],
})
}
async generateSlugByTitleViaOpenAI(title: string) {
return this
.queryOpenAI(`Please give the following title a slug in English, the output format is JSON. {slug:string}:
"${title}"
RESULT:`)
return this.queryByFunctionSchema(title, {
type: 'object',
properties: {
slug: {
type: 'string',
description:
'The slug is named after the text entered, and is in English and conforms to url specifications',
},
},
required: ['slug'],
})
}
}

View File

@ -1,5 +1,5 @@
import { ChatOpenAI } from '@langchain/openai'
import { Injectable } from '@nestjs/common'
import OpenAI from 'openai'
import { BizException } from '~/common/exceptions/biz.exception'
import { ErrorCodeEnum } from '~/constants/error-code.constant'
import { ConfigsService } from '../configs/configs.service'
@ -7,17 +7,21 @@ import { ConfigsService } from '../configs/configs.service'
@Injectable()
export class AiService {
constructor(private readonly configService: ConfigsService) {}
public async getOpenAiClient() {
public async getOpenAiChain() {
const {
ai: { openAiEndpoint, openAiKey },
ai: { openAiKey, openAiEndpoint, openAiPreferredModel },
} = await this.configService.waitForConfigReady()
if (!openAiKey) {
throw new BizException(ErrorCodeEnum.AINotEnabled, 'Key not found')
}
return new OpenAI({
return new ChatOpenAI({
model: openAiPreferredModel,
apiKey: openAiKey,
baseURL: openAiEndpoint || void 0,
fetch: isDev ? fetch : void 0,
configuration: {
baseURL: openAiEndpoint || void 0,
},
})
}
}

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:73e17b9ea9ab9042f8e690ff7d14fd63bafe7f83fbfabd138f5cde884776224a
size 115659
oid sha256:0f07a8b0bd159d40de4b3dec8741589774948472a7a5967db5b8663326de2b47
size 115913

View File

@ -109,6 +109,9 @@ importers:
'@innei/pretty-logger-nestjs':
specifier: 0.3.2
version: 0.3.2(@nestjs/common@10.3.8(class-transformer@0.5.1)(class-validator@0.13.2)(reflect-metadata@0.2.2)(rxjs@7.8.1))
'@langchain/openai':
specifier: 0.0.33
version: 0.0.33(encoding@0.1.13)
'@mx-space/external':
specifier: workspace:*
version: link:../../packages/external
@ -226,6 +229,9 @@ importers:
jszip:
specifier: 3.10.1
version: 3.10.1
langchain:
specifier: 0.2.0
version: 0.2.0(@aws-sdk/client-s3@3.583.0)(@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0))(axios@1.7.2)(encoding@0.1.13)(fast-xml-parser@4.2.5)(ignore@5.3.1)(ioredis@5.4.1)(mongodb@6.6.2(socks@2.8.3))(openai@4.47.1(encoding@0.1.13))
linkedom:
specifier: 0.18.0
version: 0.18.0
@ -324,6 +330,9 @@ importers:
specifier: ^0.10.0
version: 0.10.0
devDependencies:
'@langchain/core':
specifier: 0.2.0
version: 0.2.0(openai@4.47.1(encoding@0.1.13))
'@nestjs/cli':
specifier: 10.3.2
version: 10.3.2(@swc/core@1.5.7)(esbuild@0.19.11)
@ -1508,6 +1517,18 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
'@langchain/core@0.2.0':
resolution: {integrity: sha512-UbCJUp9eh2JXd9AW/vhPbTgtZoMgTqJgSan5Wf/EP27X8JM65lWdCOpJW+gHyBXvabbyrZz3/EGaptTUL5gutw==}
engines: {node: '>=18'}
'@langchain/openai@0.0.33':
resolution: {integrity: sha512-hTBo9y9bHtFvMT5ySBW7TrmKhLSA91iNahigeqAFBVrLmBDz+6rzzLFc1mpq6JEAR3fZKdaUXqso3nB23jIpTw==}
engines: {node: '>=18'}
'@langchain/textsplitters@0.0.2':
resolution: {integrity: sha512-6bQOuYHTGYlkgPY/8M5WPq4nnXZpEysGzRopQCYjg2WLcEoIPUMMrXsAaNNdvU3BOeMrhin8izvpDPD165hX6Q==}
engines: {node: '>=18'}
'@levischuck/tiny-cbor@0.2.2':
resolution: {integrity: sha512-f5CnPw997Y2GQ8FAvtuVVC19FX8mwNNC+1XJcIi16n/LTJifKO6QBgGLgN3YEmqtGMk17SKSuoWES3imJVxAVw==}
@ -2374,6 +2395,9 @@ packages:
'@types/remove-markdown@0.3.4':
resolution: {integrity: sha512-i753EH/p02bw7bLlpfS/4CV1rdikbGiLabWyVsAvsFid3cA5RNU1frG7JycgY+NSnFwtoGlElvZVceCytecTDA==}
'@types/retry@0.12.0':
resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
'@types/semver@7.5.8':
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
@ -2389,6 +2413,9 @@ packages:
'@types/unist@2.0.10':
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
'@types/uuid@9.0.8':
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
'@types/validator@13.11.10':
resolution: {integrity: sha512-e2PNXoXLr6Z+dbfx5zSh9TRlXJrELycxiaXznp4S5+D2M3b9bqJEitNHA5923jhnB2zzFiZHa2f0SI1HoIahpg==}
@ -2815,6 +2842,9 @@ packages:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
binary-search@1.3.6:
resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==}
bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
@ -3039,6 +3069,10 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
@ -3199,6 +3233,10 @@ packages:
supports-color:
optional: true
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
deep-eql@4.1.3:
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
engines: {node: '>=6'}
@ -3633,6 +3671,9 @@ packages:
eventemitter2@6.4.9:
resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==}
eventemitter3@4.0.7:
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
@ -4142,6 +4183,9 @@ packages:
is-alphanumerical@1.0.4:
resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==}
is-any-array@2.0.1:
resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==}
is-array-buffer@3.0.2:
resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
@ -4321,6 +4365,9 @@ packages:
resolution: {integrity: sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==}
engines: {node: '>=12'}
js-tiktoken@1.0.12:
resolution: {integrity: sha512-L7wURW1fH9Qaext0VzaUDpFGVQgjkdE3Dgsy9/+yXyGEpBKnylTd0mU0bfbNkKDlXRb6TEsZkwuflu1B8uQbJQ==}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@ -4384,6 +4431,10 @@ packages:
jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
jsonpointer@5.0.1:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
jsonwebtoken@9.0.2:
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
engines: {node: '>=12', npm: '>=6'}
@ -4404,6 +4455,176 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
langchain@0.2.0:
resolution: {integrity: sha512-8c7Dg9OIPk4lFIQGyfOytXbUGLLSsxs9MV53cLODspkOGzaUpwy5FGBie30SrOxIEFJo+FDaJgpDAFO3Xi4NMw==}
engines: {node: '>=18'}
peerDependencies:
'@aws-sdk/client-s3': ^3.310.0
'@aws-sdk/client-sagemaker-runtime': ^3.310.0
'@aws-sdk/client-sfn': ^3.310.0
'@aws-sdk/credential-provider-node': ^3.388.0
'@azure/storage-blob': ^12.15.0
'@browserbasehq/sdk': '*'
'@gomomento/sdk': ^1.51.1
'@gomomento/sdk-core': ^1.51.1
'@gomomento/sdk-web': ^1.51.1
'@google-ai/generativelanguage': ^0.2.1
'@mendable/firecrawl-js': ^0.0.13
'@notionhq/client': ^2.2.10
'@pinecone-database/pinecone': '*'
'@supabase/supabase-js': ^2.10.0
'@vercel/kv': ^0.2.3
'@xata.io/client': ^0.28.0
apify-client: ^2.7.1
assemblyai: ^4.0.0
axios: '*'
cheerio: ^1.0.0-rc.12
chromadb: '*'
convex: ^1.3.1
couchbase: ^4.3.0
d3-dsv: ^2.0.0
epub2: ^3.0.1
faiss-node: '*'
fast-xml-parser: '*'
handlebars: ^4.7.8
html-to-text: ^9.0.5
ignore: ^5.2.0
ioredis: ^5.3.2
jsdom: '*'
mammoth: ^1.6.0
mongodb: '>=5.2.0'
node-llama-cpp: '*'
notion-to-md: ^3.1.0
officeparser: ^4.0.4
pdf-parse: 1.1.1
peggy: ^3.0.2
playwright: ^1.32.1
puppeteer: ^19.7.2
pyodide: ^0.24.1
redis: ^4.6.4
sonix-speech-recognition: ^2.1.1
srt-parser-2: ^1.2.3
typeorm: ^0.3.12
weaviate-ts-client: '*'
web-auth-library: ^1.0.3
ws: ^8.14.2
youtube-transcript: ^1.0.6
youtubei.js: ^9.1.0
peerDependenciesMeta:
'@aws-sdk/client-s3':
optional: true
'@aws-sdk/client-sagemaker-runtime':
optional: true
'@aws-sdk/client-sfn':
optional: true
'@aws-sdk/credential-provider-node':
optional: true
'@azure/storage-blob':
optional: true
'@browserbasehq/sdk':
optional: true
'@gomomento/sdk':
optional: true
'@gomomento/sdk-core':
optional: true
'@gomomento/sdk-web':
optional: true
'@google-ai/generativelanguage':
optional: true
'@mendable/firecrawl-js':
optional: true
'@notionhq/client':
optional: true
'@pinecone-database/pinecone':
optional: true
'@supabase/supabase-js':
optional: true
'@vercel/kv':
optional: true
'@xata.io/client':
optional: true
apify-client:
optional: true
assemblyai:
optional: true
axios:
optional: true
cheerio:
optional: true
chromadb:
optional: true
convex:
optional: true
couchbase:
optional: true
d3-dsv:
optional: true
epub2:
optional: true
faiss-node:
optional: true
fast-xml-parser:
optional: true
handlebars:
optional: true
html-to-text:
optional: true
ignore:
optional: true
ioredis:
optional: true
jsdom:
optional: true
mammoth:
optional: true
mongodb:
optional: true
node-llama-cpp:
optional: true
notion-to-md:
optional: true
officeparser:
optional: true
pdf-parse:
optional: true
peggy:
optional: true
playwright:
optional: true
puppeteer:
optional: true
pyodide:
optional: true
redis:
optional: true
sonix-speech-recognition:
optional: true
srt-parser-2:
optional: true
typeorm:
optional: true
weaviate-ts-client:
optional: true
web-auth-library:
optional: true
ws:
optional: true
youtube-transcript:
optional: true
youtubei.js:
optional: true
langchainhub@0.0.10:
resolution: {integrity: sha512-mOVso7TGTMSlvTTUR1b4zUIMtu8zgie/pcwRm1SeooWwuHYMQovoNXjT6gEjvWEZ6cjt4gVH+1lu2tp1/phyIQ==}
langsmith@0.1.25:
resolution: {integrity: sha512-Hft4Y1yoMgFgCUXVQklRZ7ndmLQ/6FmRZE9P3u5BRdMq5Fa0hpg8R7jd7bLLBXkAjqcFvWo0AGhpb8MMY5FAiA==}
peerDependencies:
openai: '*'
peerDependenciesMeta:
openai:
optional: true
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@ -4733,6 +4954,21 @@ packages:
engines: {node: '>=10'}
hasBin: true
ml-array-mean@1.1.6:
resolution: {integrity: sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ==}
ml-array-sum@1.1.6:
resolution: {integrity: sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw==}
ml-distance-euclidean@2.0.0:
resolution: {integrity: sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q==}
ml-distance@4.0.1:
resolution: {integrity: sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw==}
ml-tree-similarity@1.0.0:
resolution: {integrity: sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg==}
mlly@1.6.1:
resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==}
@ -4850,6 +5086,10 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
mustache@4.2.0:
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
hasBin: true
mute-stream@0.0.8:
resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
@ -4963,6 +5203,10 @@ packages:
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
num-sort@2.1.0:
resolution: {integrity: sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg==}
engines: {node: '>=8'}
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@ -5007,6 +5251,9 @@ packages:
resolution: {integrity: sha512-WWSxhC/69ZhYWxH/OBsLEirIjUcfpQ5+ihkXKp06hmeYXgBBIUCa9IptMzYx6NdkiOCsSGYCnTIsxaic3AjRCQ==}
hasBin: true
openapi-types@12.1.3:
resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
openapi3-ts@2.0.2:
resolution: {integrity: sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==}
@ -5022,6 +5269,10 @@ packages:
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
engines: {node: '>=0.10.0'}
p-finally@1.0.0:
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
engines: {node: '>=4'}
p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
@ -5042,6 +5293,18 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
p-queue@6.6.2:
resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==}
engines: {node: '>=8'}
p-retry@4.6.2:
resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
engines: {node: '>=8'}
p-timeout@3.2.0:
resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
engines: {node: '>=8'}
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@ -5449,6 +5712,10 @@ packages:
resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==}
engines: {node: '>=4'}
retry@0.13.1:
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
engines: {node: '>= 4'}
reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@ -6465,6 +6732,14 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
zod-to-json-schema@3.23.0:
resolution: {integrity: sha512-az0uJ243PxsRIa2x1WmNE/pnuA05gUq/JB8Lwe1EDCCL/Fz9MgjYQ0fPlyc2Tcv6aF2ZA7WM5TWaRZVEFaAIag==}
peerDependencies:
zod: ^3.23.3
zod@3.23.8:
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
zx-cjs@7.0.7-0:
resolution: {integrity: sha512-CDwRWriV229ZQN5/wIk92DYQ33Q/jU2DvL+CQXa96qIwMINpW6RQWaXWCRticVDPF0CRKZ4y6uB/8GRzBw1MxA==}
engines: {node: '>= 16.0.0'}
@ -6652,7 +6927,7 @@ snapshots:
'@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/client-sts': 3.583.0
'@aws-sdk/core': 3.582.0
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/middleware-bucket-endpoint': 3.577.0
'@aws-sdk/middleware-expect-continue': 3.577.0
'@aws-sdk/middleware-flexible-checksums': 3.577.0
@ -6713,7 +6988,7 @@ snapshots:
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sts': 3.583.0
'@aws-sdk/core': 3.582.0
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@ -6802,7 +7077,7 @@ snapshots:
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/core': 3.582.0
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@ -6870,12 +7145,12 @@ snapshots:
'@smithy/util-stream': 3.0.1
tslib: 2.6.2
'@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)':
'@aws-sdk/credential-provider-ini@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)':
dependencies:
'@aws-sdk/client-sts': 3.583.0
'@aws-sdk/credential-provider-env': 3.577.0
'@aws-sdk/credential-provider-process': 3.577.0
'@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)
'@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))
'@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.0.0
@ -6887,13 +7162,13 @@ snapshots:
- '@aws-sdk/client-sso-oidc'
- aws-crt
'@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)':
'@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)':
dependencies:
'@aws-sdk/credential-provider-env': 3.577.0
'@aws-sdk/credential-provider-http': 3.582.0
'@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/credential-provider-ini': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/credential-provider-process': 3.577.0
'@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0)
'@aws-sdk/credential-provider-sso': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))
'@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.0.0
@ -6914,10 +7189,10 @@ snapshots:
'@smithy/types': 3.0.0
tslib: 2.6.2
'@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0)':
'@aws-sdk/credential-provider-sso@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))':
dependencies:
'@aws-sdk/client-sso': 3.583.0
'@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0)
'@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))
'@aws-sdk/types': 3.577.0
'@smithy/property-provider': 3.0.0
'@smithy/shared-ini-file-loader': 3.0.0
@ -7043,7 +7318,7 @@ snapshots:
'@smithy/types': 3.0.0
tslib: 2.6.2
'@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0)':
'@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))':
dependencies:
'@aws-sdk/client-sso-oidc': 3.583.0(@aws-sdk/client-sts@3.583.0)
'@aws-sdk/types': 3.577.0
@ -7830,6 +8105,40 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@langchain/core@0.2.0(openai@4.47.1(encoding@0.1.13))':
dependencies:
ansi-styles: 5.2.0
camelcase: 6.3.0
decamelize: 1.2.0
js-tiktoken: 1.0.12
langsmith: 0.1.25(openai@4.47.1(encoding@0.1.13))
ml-distance: 4.0.1
mustache: 4.2.0
p-queue: 6.6.2
p-retry: 4.6.2
uuid: 9.0.1
zod: 3.23.8
zod-to-json-schema: 3.23.0(zod@3.23.8)
transitivePeerDependencies:
- openai
'@langchain/openai@0.0.33(encoding@0.1.13)':
dependencies:
'@langchain/core': 0.2.0(openai@4.47.1(encoding@0.1.13))
js-tiktoken: 1.0.12
openai: 4.47.1(encoding@0.1.13)
zod: 3.23.8
zod-to-json-schema: 3.23.0(zod@3.23.8)
transitivePeerDependencies:
- encoding
'@langchain/textsplitters@0.0.2(openai@4.47.1(encoding@0.1.13))':
dependencies:
'@langchain/core': 0.2.0(openai@4.47.1(encoding@0.1.13))
js-tiktoken: 1.0.12
transitivePeerDependencies:
- openai
'@levischuck/tiny-cbor@0.2.2': {}
'@ljharb/through@2.3.13':
@ -8814,6 +9123,8 @@ snapshots:
'@types/remove-markdown@0.3.4': {}
'@types/retry@0.12.0': {}
'@types/semver@7.5.8': {}
'@types/send@0.17.3':
@ -8831,6 +9142,8 @@ snapshots:
'@types/unist@2.0.10': {}
'@types/uuid@9.0.8': {}
'@types/validator@13.11.10': {}
'@types/webidl-conversions@7.0.3': {}
@ -9347,6 +9660,8 @@ snapshots:
binary-extensions@2.2.0: {}
binary-search@1.3.6: {}
bl@4.1.0:
dependencies:
buffer: 5.7.1
@ -9458,8 +9773,7 @@ snapshots:
quick-lru: 6.1.2
type-fest: 4.9.0
camelcase@6.3.0:
optional: true
camelcase@6.3.0: {}
camelcase@8.0.0: {}
@ -9604,6 +9918,8 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
commander@10.0.1: {}
commander@12.1.0: {}
commander@2.20.3: {}
@ -9746,6 +10062,8 @@ snapshots:
dependencies:
ms: 2.1.2
decamelize@1.2.0: {}
deep-eql@4.1.3:
dependencies:
type-detect: 4.0.8
@ -10362,6 +10680,8 @@ snapshots:
eventemitter2@6.4.9: {}
eventemitter3@4.0.7: {}
eventemitter3@5.0.1: {}
events@3.3.0: {}
@ -11053,6 +11373,8 @@ snapshots:
is-alphabetical: 1.0.4
is-decimal: 1.0.4
is-any-array@2.0.1: {}
is-array-buffer@3.0.2:
dependencies:
call-bind: 1.0.7
@ -11203,6 +11525,10 @@ snapshots:
js-cookie@3.0.1: {}
js-tiktoken@1.0.12:
dependencies:
base64-js: 1.5.1
js-tokens@4.0.0: {}
js-tokens@8.0.3: {}
@ -11253,6 +11579,8 @@ snapshots:
optionalDependencies:
graceful-fs: 4.2.11
jsonpointer@5.0.1: {}
jsonwebtoken@9.0.2:
dependencies:
jws: 3.2.2
@ -11290,6 +11618,48 @@ snapshots:
dependencies:
json-buffer: 3.0.1
langchain@0.2.0(@aws-sdk/client-s3@3.583.0)(@aws-sdk/credential-provider-node@3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0))(axios@1.7.2)(encoding@0.1.13)(fast-xml-parser@4.2.5)(ignore@5.3.1)(ioredis@5.4.1)(mongodb@6.6.2(socks@2.8.3))(openai@4.47.1(encoding@0.1.13)):
dependencies:
'@langchain/core': 0.2.0(openai@4.47.1(encoding@0.1.13))
'@langchain/openai': 0.0.33(encoding@0.1.13)
'@langchain/textsplitters': 0.0.2(openai@4.47.1(encoding@0.1.13))
binary-extensions: 2.2.0
js-tiktoken: 1.0.12
js-yaml: 4.1.0
jsonpointer: 5.0.1
langchainhub: 0.0.10
langsmith: 0.1.25(openai@4.47.1(encoding@0.1.13))
ml-distance: 4.0.1
openapi-types: 12.1.3
p-retry: 4.6.2
uuid: 9.0.1
yaml: 2.3.4
zod: 3.23.8
zod-to-json-schema: 3.23.0(zod@3.23.8)
optionalDependencies:
'@aws-sdk/client-s3': 3.583.0
'@aws-sdk/credential-provider-node': 3.583.0(@aws-sdk/client-sso-oidc@3.583.0(@aws-sdk/client-sts@3.583.0))(@aws-sdk/client-sts@3.583.0)
axios: 1.7.2
fast-xml-parser: 4.2.5
ignore: 5.3.1
ioredis: 5.4.1
mongodb: 6.6.2(socks@2.8.3)
transitivePeerDependencies:
- encoding
- openai
langchainhub@0.0.10: {}
langsmith@0.1.25(openai@4.47.1(encoding@0.1.13)):
dependencies:
'@types/uuid': 9.0.8
commander: 10.0.1
p-queue: 6.6.2
p-retry: 4.6.2
uuid: 9.0.1
optionalDependencies:
openai: 4.47.1(encoding@0.1.13)
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@ -11588,6 +11958,27 @@ snapshots:
mkdirp@3.0.1: {}
ml-array-mean@1.1.6:
dependencies:
ml-array-sum: 1.1.6
ml-array-sum@1.1.6:
dependencies:
is-any-array: 2.0.1
ml-distance-euclidean@2.0.0: {}
ml-distance@4.0.1:
dependencies:
ml-array-mean: 1.1.6
ml-distance-euclidean: 2.0.0
ml-tree-similarity: 1.0.0
ml-tree-similarity@1.0.0:
dependencies:
binary-search: 1.3.6
num-sort: 2.1.0
mlly@1.6.1:
dependencies:
acorn: 8.11.3
@ -11717,6 +12108,8 @@ snapshots:
ms@2.1.3: {}
mustache@4.2.0: {}
mute-stream@0.0.8: {}
mute-stream@1.0.0: {}
@ -11823,6 +12216,8 @@ snapshots:
dependencies:
boolbase: 1.0.0
num-sort@2.1.0: {}
object-assign@4.1.1: {}
object-hash@3.0.0: {}
@ -11871,6 +12266,8 @@ snapshots:
transitivePeerDependencies:
- encoding
openapi-types@12.1.3: {}
openapi3-ts@2.0.2:
dependencies:
yaml: 1.10.2
@ -11898,6 +12295,8 @@ snapshots:
os-tmpdir@1.0.2: {}
p-finally@1.0.0: {}
p-limit@2.3.0:
dependencies:
p-try: 2.2.0
@ -11918,6 +12317,20 @@ snapshots:
dependencies:
p-limit: 3.1.0
p-queue@6.6.2:
dependencies:
eventemitter3: 4.0.7
p-timeout: 3.2.0
p-retry@4.6.2:
dependencies:
'@types/retry': 0.12.0
retry: 0.13.1
p-timeout@3.2.0:
dependencies:
p-finally: 1.0.0
p-try@2.2.0: {}
pako@1.0.11: {}
@ -12270,6 +12683,8 @@ snapshots:
ret@0.2.2: {}
retry@0.13.1: {}
reusify@1.0.4: {}
rfdc@1.3.1: {}
@ -13375,6 +13790,12 @@ snapshots:
yocto-queue@1.0.0: {}
zod-to-json-schema@3.23.0(zod@3.23.8):
dependencies:
zod: 3.23.8
zod@3.23.8: {}
zx-cjs@7.0.7-0: {}
zx@7.2.3: