diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..aaaa7a4ba --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +tab_width = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..c783a49a2 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +# ------------------------------------------------------------------------------ +# This is an example .env file. +# +# All of these environment vars must be defined either in your environment or in +# a local .env file in order to run this project. +# ------------------------------------------------------------------------------ diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..6de124a48 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,8 @@ +{ + "root": true, + "extends": ["@fisch0920/eslint-config/node"], + "rules": { + "unicorn/no-static-only-class": "off", + "@typescript-eslint/naming-convention": "off" + } +} diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 000000000..9377c232f --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1 @@ +github: [transitive-bullshit] diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..aa55da764 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,50 @@ +name: CI + +on: [push, pull_request] + +jobs: + test: + name: Test Node.js ${{ matrix.node-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + node-version: + - 20 + - 21 + - 22 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install pnpm + uses: pnpm/action-setup@v3 + id: pnpm-install + with: + version: 9.1.4 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run test + run: pnpm run test diff --git a/.gitignore b/.gitignore index 00b85523c..29026e30c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -*.swp -.idea - # dependencies -/node_modules +node_modules /.pnp .pnp.js @@ -12,11 +9,12 @@ /coverage # next.js -/.next/ -/out/ +.next/ +out/ # production -/build +build/ +dist/ # misc .DS_Store @@ -38,13 +36,6 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -# local env files .env -.env.local -.env.build -.env.development.local -.env.test.local -.env.production.local -# data dumps -out/ +old/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..f27575a8e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run precommit diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..605ae9cc9 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +enable-pre-post-scripts=true +package-manager-strict=false diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..af07fd262 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "jsxSingleQuote": true, + "semi": false, + "useTabs": false, + "tabWidth": 2, + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "trailingComma": "none" +} diff --git a/bin/scratch.ts b/bin/scratch.ts new file mode 100644 index 000000000..2d503e86f --- /dev/null +++ b/bin/scratch.ts @@ -0,0 +1,128 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import restoreCursor from 'restore-cursor' + +// import { SearxngClient } from '../src/services/searxng-client.js' +// import { ClearbitClient } from '../src/index.js' +// import { ProxycurlClient } from '../src/services/proxycurl-client.js' +// import { WikipediaClient } from '../src/index.js' +// import { PerigonClient } from '../src/index.js' +// import { FirecrawlClient } from '../src/index.js' +// import { ExaClient } from '../src/index.js' +// import { DiffbotClient } from '../src/index.js' +// import { WolframAlphaClient } from '../src/index.js' +// import { +// createTwitterV2Client, +// TwitterClient +// } from '../src/services/twitter/index.js' +// import { MidjourneyClient } from '../src/index.js' +// import { BingClient } from '../src/index.js' +import { TavilyClient } from '../src/index.js' + +/** + * Scratch pad for testing. + */ +async function main() { + restoreCursor() + + // const clearbit = new ClearbitClient() + // const res = await clearbit.companyEnrichment({ + // domain: 'https://clay.com' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const proxycurl = new ProxycurlClient() + // const res = await proxycurl.getLinkedInPerson({ + // linkedin_profile_url: 'https://linkedin.com/in/fisch2' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const wikipedia = new WikipediaClient() + // const res = await wikipedia.getPageSummary({ + // // title: 'Naruto_(TV_series)' + // title: 'SpaceX' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const searxng = new SearxngClient() + // const res = await searxng.search({ + // query: 'golden gate bridge', + // engines: ['reddit'] + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const perigon = new PerigonClient() + // const res = await perigon.searchArticles({ + // q: 'AI agents AND startup', + // sourceGroup: 'top50tech' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const firecrawl = new FirecrawlClient() + // const res = await firecrawl.scrapeUrl({ + // url: 'https://www.bbc.com/news/articles/cp4475gwny1o' + // // url: 'https://www.theguardian.com/technology/article/2024/jun/04/openai-google-ai-risks-letter' + // // url: 'https://www.firecrawl.dev' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const exa = new ExaClient() + // const res = await exa.search({ + // query: 'OpenAI', + // contents: { text: true } + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const diffbot = new DiffbotClient() + // // const res = await diffbot.analyzeUrl({ + // // url: 'https://www.bbc.com/news/articles/cp4475gwny1o' + // // }) + // const res = await diffbot.enhanceEntity({ + // type: 'Person', + // name: 'Kevin Raheja' + // }) + // console.log(JSON.stringify(res, null, 2)) + + // const wolfram = new WolframAlphaClient() + // const res = await wolfram.ask({ + // input: 'population of new york city' + // }) + // console.log(res) + + // const client = await createTwitterV2Client({ + // scopes: ['tweet.read', 'users.read', 'offline.access'] + // }) + // const twitter = new TwitterClient({ client }) + // // const res = await twitter.findUserByUsername({ username: 'transitive_bs' }) + // const res = await twitter.searchRecentTweets({ + // query: 'open source AI agents' + // }) + // console.log(res) + + // const midjourney = new MidjourneyClient() + // const res = await midjourney.imagine( + // 'tiny lil baby kittens playing with an inquisitive AI robot, kawaii, anime' + // ) + // console.log(JSON.stringify(res, null, 2)) + + // const bing = new BingClient() + // const res = await bing.search({ + // q: 'world cup 2024 freestyle wrestling news' + // }) + // console.log(JSON.stringify(res, null, 2)) + + const tavily = new TavilyClient() + const res = await tavily.search({ + query: 'when do experts predict that OpenAI will release GPT-5?', + include_answer: true + }) + console.log(JSON.stringify(res, null, 2)) +} + +try { + await main() +} catch (err) { + console.error('error', err) + process.exit(1) +} diff --git a/examples/ai-sdk/browserbase.ts b/examples/ai-sdk/browserbase.ts new file mode 100644 index 000000000..e3faba4f2 --- /dev/null +++ b/examples/ai-sdk/browserbase.ts @@ -0,0 +1,26 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { openai } from '@ai-sdk/openai' +import { Browserbase, BrowserbaseAISDK } from '@browserbasehq/sdk' +import { generateText } from 'ai' + +async function main() { + const browserbase = new Browserbase() + + const browserTool = BrowserbaseAISDK(browserbase, { textContent: true }) + console.log(browserTool.parameters) + + const result = await generateText({ + model: openai('gpt-4o'), + tools: { browserTool }, + toolChoice: 'required', + temperature: 0, + system: 'You are a helpful assistant. Be as concise as possible.', + prompt: 'What is the weather in San Francisco?' + }) + + console.log(result.toolResults[0]) +} + +await main() diff --git a/examples/ai-sdk/weather.ts b/examples/ai-sdk/weather.ts new file mode 100644 index 000000000..1fb6e3fd8 --- /dev/null +++ b/examples/ai-sdk/weather.ts @@ -0,0 +1,24 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { WeatherClient } from '@agentic/stdlib' +import { createAISDKTools } from '@agentic/stdlib/ai-sdk' +import { openai } from '@ai-sdk/openai' +import { generateText } from 'ai' + +async function main() { + const weather = new WeatherClient() + + const result = await generateText({ + model: openai('gpt-4o'), + tools: createAISDKTools(weather), + toolChoice: 'required', + temperature: 0, + system: 'You are a helpful assistant. Be as concise as possible.', + prompt: 'What is the weather in San Francisco?' + }) + + console.log(result.toolResults[0]) +} + +await main() diff --git a/examples/dexter/analyze.ts b/examples/dexter/analyze.ts new file mode 100644 index 000000000..ec03b3bff --- /dev/null +++ b/examples/dexter/analyze.ts @@ -0,0 +1,28 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { DiffbotClient, SearchAndCrawl, SerpAPIClient } from '@agentic/stdlib' +import { createDexterFunctions } from '@agentic/stdlib/dexter' +import { ChatModel, createAIRunner } from '@dexaai/dexter' + +async function main() { + const serpapi = new SerpAPIClient() + const diffbot = new DiffbotClient() + const searchAndCrawl = new SearchAndCrawl({ serpapi, diffbot }) + + const runner = createAIRunner({ + chatModel: new ChatModel({ + params: { model: 'gpt-4o', temperature: 0 } + // debug: true + }), + functions: createDexterFunctions(searchAndCrawl), + systemMessage: + 'You are a McKinsey analyst who is an expert at writing executive summaries. Always cite your sources and respond using Markdown.' + }) + + const topic = 'the 2024 olympics' + const result = await runner(`Summarize the latest news on ${topic}`) + console.log(result) +} + +await main() diff --git a/examples/dexter/code-interpreter.ts b/examples/dexter/code-interpreter.ts new file mode 100644 index 000000000..ffd1e2545 --- /dev/null +++ b/examples/dexter/code-interpreter.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { createDexterFunctions } from '@agentic/stdlib/dexter' +import { e2b } from '@agentic/stdlib/e2b' +import { ChatModel, createAIRunner } from '@dexaai/dexter' + +async function main() { + const runner = createAIRunner({ + chatModel: new ChatModel({ + params: { model: 'gpt-4o', temperature: 0 }, + debug: true + }), + functions: createDexterFunctions(e2b) + }) + + const result = await runner( + 'Visualize a distribution of height of men based on the latest data you know. Also print the median value.' + ) + console.log(result) +} + +await main() diff --git a/examples/dexter/election-news.ts b/examples/dexter/election-news.ts new file mode 100644 index 000000000..64ea15225 --- /dev/null +++ b/examples/dexter/election-news.ts @@ -0,0 +1,31 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { PerigonClient, SerperClient } from '@agentic/stdlib' +import { createDexterFunctions } from '@agentic/stdlib/dexter' +import { ChatModel, createAIRunner } from '@dexaai/dexter' + +async function main() { + const perigon = new PerigonClient() + const serper = new SerperClient() + + const runner = createAIRunner({ + chatModel: new ChatModel({ + params: { model: 'gpt-4o', temperature: 0 } + // debug: true + }), + functions: createDexterFunctions( + perigon.functions.pick('search_news_stories'), + serper + ), + systemMessage: + 'You are a helpful assistant. Be as concise as possible. Respond in markdown. Always cite your sources.' + }) + + const result = await runner( + 'Summarize the latest news stories about the upcoming US election.' + ) + console.log(result) +} + +await main() diff --git a/examples/dexter/weather.ts b/examples/dexter/weather.ts new file mode 100644 index 000000000..1b995af58 --- /dev/null +++ b/examples/dexter/weather.ts @@ -0,0 +1,24 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { WeatherClient } from '@agentic/stdlib' +import { createDexterFunctions } from '@agentic/stdlib/dexter' +import { ChatModel, createAIRunner } from '@dexaai/dexter' + +async function main() { + const weather = new WeatherClient() + + const runner = createAIRunner({ + chatModel: new ChatModel({ + params: { model: 'gpt-4o', temperature: 0 } + // debug: true + }), + functions: createDexterFunctions(weather), + systemMessage: 'You are a helpful assistant. Be as concise as possible.' + }) + + const result = await runner('What is the weather in San Francisco?') + console.log(result) +} + +await main() diff --git a/examples/genkit/weather.ts b/examples/genkit/weather.ts new file mode 100644 index 000000000..859f55cb9 --- /dev/null +++ b/examples/genkit/weather.ts @@ -0,0 +1,36 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { WeatherClient } from '@agentic/stdlib' +import { createGenkitTools } from '@agentic/stdlib/genkit' +import { generate } from '@genkit-ai/ai' +import { configureGenkit } from '@genkit-ai/core' +import { gpt4o, openAI } from 'genkitx-openai' + +async function main() { + const weather = new WeatherClient() + + configureGenkit({ + plugins: [openAI()] + }) + + const result = await generate({ + model: gpt4o, + tools: createGenkitTools(weather), + history: [ + { + role: 'system', + content: [ + { + text: 'You are a helpful assistant. Be as concise as possible.' + } + ] + } + ], + prompt: 'What is the weather in San Francisco?' + }) + + console.log(result) +} + +await main() diff --git a/examples/langchain/weather.ts b/examples/langchain/weather.ts new file mode 100644 index 000000000..61205bbd0 --- /dev/null +++ b/examples/langchain/weather.ts @@ -0,0 +1,38 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { WeatherClient } from '@agentic/stdlib' +import { createLangChainTools } from '@agentic/stdlib/langchain' +import { ChatPromptTemplate } from '@langchain/core/prompts' +import { ChatOpenAI } from '@langchain/openai' +import { AgentExecutor, createToolCallingAgent } from 'langchain/agents' + +async function main() { + const weather = new WeatherClient() + + const tools = createLangChainTools(weather) + const agent = createToolCallingAgent({ + llm: new ChatOpenAI({ model: 'gpt-4o', temperature: 0 }), + tools, + prompt: ChatPromptTemplate.fromMessages([ + ['system', 'You are a helpful assistant. Be as concise as possible.'], + ['placeholder', '{chat_history}'], + ['human', '{input}'], + ['placeholder', '{agent_scratchpad}'] + ]) + }) + + const agentExecutor = new AgentExecutor({ + agent, + tools + // verbose: true + }) + + const result = await agentExecutor.invoke({ + input: 'What is the weather in San Francisco?' + }) + + console.log(result.output) +} + +await main() diff --git a/examples/llamaindex/weather.ts b/examples/llamaindex/weather.ts new file mode 100644 index 000000000..970cc8052 --- /dev/null +++ b/examples/llamaindex/weather.ts @@ -0,0 +1,25 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { WeatherClient } from '@agentic/stdlib' +import { createLlamaIndexTools } from '@agentic/stdlib/llamaindex' +import { OpenAI, OpenAIAgent } from 'llamaindex' + +async function main() { + const weather = new WeatherClient() + + const tools = createLlamaIndexTools(weather) + const agent = new OpenAIAgent({ + llm: new OpenAI({ model: 'gpt-4o', temperature: 0 }), + systemPrompt: 'You are a helpful assistant. Be as concise as possible.', + tools + }) + + const response = await agent.chat({ + message: 'What is the weather in San Francisco?' + }) + + console.log(response.response.message.content) +} + +await main() diff --git a/examples/openai/weather.ts b/examples/openai/weather.ts new file mode 100644 index 000000000..66a3ca106 --- /dev/null +++ b/examples/openai/weather.ts @@ -0,0 +1,59 @@ +#!/usr/bin/env node +import 'dotenv/config' + +import { assert, WeatherClient } from '@agentic/stdlib' +import OpenAI from 'openai' + +async function main() { + const weather = new WeatherClient() + const openai = new OpenAI() + + const messages: OpenAI.ChatCompletionMessageParam[] = [ + { + role: 'system', + content: 'You are a helpful assistant. Be as concise as possible.' + }, + { role: 'user', content: 'What is the weather in San Francisco?' } + ] + + { + // First call to OpenAI to invoke the weather tool + const res = await openai.chat.completions.create({ + messages, + model: 'gpt-4o', + temperature: 0, + tools: weather.functions.toolSpecs, + tool_choice: 'required' + }) + const message = res.choices[0]?.message! + console.log(JSON.stringify(message, null, 2)) + assert(message.tool_calls?.[0]?.function?.name === 'get_current_weather') + + const fn = weather.functions.get('get_current_weather')! + assert(fn) + + const toolParams = message.tool_calls[0].function.arguments + const toolResult = await fn(toolParams) + + messages.push(message) + messages.push({ + role: 'tool', + tool_call_id: message.tool_calls[0].id, + content: JSON.stringify(toolResult) + }) + } + + { + // Second call to OpenAI to generate a text response + const res = await openai.chat.completions.create({ + messages, + model: 'gpt-4o', + temperature: 0, + tools: weather.functions.toolSpecs + }) + const message = res.choices[0].message + console.log(JSON.stringify(message, null, 2)) + } +} + +await main() diff --git a/examples/package.json b/examples/package.json new file mode 100644 index 000000000..4e65fa49e --- /dev/null +++ b/examples/package.json @@ -0,0 +1,43 @@ +{ + "name": "agentic-examples", + "private": true, + "version": "0.1.0", + "description": "TODO", + "author": "Travis Fischer ", + "license": "MIT", + "repository": { + "type": "git", + "url": "transitive-bullshit/agentic" + }, + "packageManager": "pnpm@9.1.4", + "engines": { + "node": ">=18" + }, + "type": "module", + "scripts": { + "preinstall": "npx only-allow pnpm", + "build": "tsc", + "clean": "del dist", + "prebuild": "run-s clean", + "pretest": "run-s build", + "test": "run-s test:*", + "test:typecheck": "tsc --noEmit" + }, + "dependencies": { + "@agentic/stdlib": "workspace:*", + "@ai-sdk/openai": "^0.0.24", + "@dexaai/dexter": "^2.1.0", + "@genkit-ai/ai": "^0.5.2", + "@genkit-ai/core": "^0.5.2", + "@instructor-ai/instructor": "^1.3.0", + "@langchain/core": "^0.2.6", + "@langchain/openai": "^0.1.2", + "ai": "^3.1.30", + "dotenv": "^16.4.5", + "genkitx-openai": "^0.10.0", + "langchain": "^0.2.5", + "llamaindex": "^0.3.16", + "openai": "^4.49.0", + "zod": "^3.23.8" + } +} diff --git a/examples/tsconfig.json b/examples/tsconfig.json new file mode 100644 index 000000000..157591203 --- /dev/null +++ b/examples/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.json", + "include": ["ai-sdk", "dexter", "genkit", "langchain", "llamaindex", "openai"] +} diff --git a/json-schema.json b/json-schema.json new file mode 100644 index 000000000..264f3489f --- /dev/null +++ b/json-schema.json @@ -0,0 +1,11603 @@ +{ + "servers": [ + { + "url": "https://nubela.co/proxycurl", + "description": "With SSL Proxycurl Server" + }, + { + "url": "http://nubela.co/proxycurl", + "description": "Without SSL Proxycurl Server" + } + ], + "security": [ + { + "BearerAuth": [ + "client" + ] + } + ], + "paths": { + "/api/linkedin/school": { + "get": { + "description": "Cost: 1 credit / successful request.\nGet structured data of a LinkedIn School Profile", + "parameters": [ + { + "in": "query", + "name": "url", + "required": true, + "description": "\n URL of the LinkedIn School Profile to crawl.\n\n URL should be in the format of `https://www.linkedin.com/school/`\n ", + "example": "https://www.linkedin.com/school/national-university-of-singapore", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "use_cache", + "required": false, + "description": "`if-present` The default behavior. Fetches profile from cache regardless of age of profile. If profile is not available in cache, API will attempt to source profile externally.\n\n`if-recent` API will make a best effort to return a fresh profile no older than 29 days.Costs an extra `1` credit on top of the cost of the base endpoint.", + "example": "if-present", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkedinSchool" + }, + "example": { + "linkedin_internal_id": "5524", + "description": "At NUS, we are shaping the future through our people and our pursuit of new frontiers in knowledge. In a single century, we have become a university of global influence and an Asian thought leader. Our location at the crossroads of Asia informs our mission and gives us a tremendous vantage point to help create opportunities and address the pressing issues facing Singapore, Asia and the world.\r\rAt NUS, we believe in education, research and service that change lives.", + "website": "http://nus.edu.sg", + "industry": "Higher Education", + "company_size": [ + 5001, + 10000 + ], + "company_size_on_linkedin": 16084, + "hq": { + "country": "SG", + "city": "Singapore", + "postal_code": "119077", + "line_1": "21 Lower Kent Ridge Road, Singapore", + "is_hq": true, + "state": null + }, + "company_type": "EDUCATIONAL_INSTITUTION", + "founded_year": 1905, + "specialities": [ + "education", + "research" + ], + "locations": [ + { + "country": "SG", + "city": "Singapore", + "postal_code": "119077", + "line_1": "21 Lower Kent Ridge Road, Singapore", + "is_hq": true, + "state": null + } + ], + "name": "National University of Singapore", + "tagline": null, + "universal_name_id": "national-university-of-singapore", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/national-university-of-singapore/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T071304Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=a66e032f168972bef4ea3821705194ea1c144415a1655bdb328f961ed30e2a24", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/national-university-of-singapore/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T071304Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=551f456b6156e4610bc3e7be43e2f9b0e4b071db5f41f56cc0e408fc1b5a1140", + "search_id": "5524", + "similar_companies": [ + { + "name": "NUS Business School", + "link": "https://www.linkedin.com/school/nus-business-school/", + "industry": "Higher Education", + "location": null + }, + { + "name": "NUS Faculty of Arts and Social Sciences", + "link": "https://www.linkedin.com/school/nusfass/", + "industry": "Higher Education", + "location": null + } + ], + "affiliated_companies": [], + "updates": [], + "follower_count": 539321 + } + } + }, + "description": "Profile data with profile picture, school location, etc" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "School API" + ], + "operationId": "School Profile Endpoint" + }, + "summary": "School Profile Endpoint" + }, + "/api/linkedin/company": { + "get": { + "description": "Cost: 1 credit / successful request.\nGet structured data of a Company Profile", + "parameters": [ + { + "in": "query", + "name": "url", + "required": true, + "description": "\n URL of the LinkedIn Company Profile to crawl.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n ", + "example": "https://www.linkedin.com/company/google/", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "resolve_numeric_id", + "required": false, + "description": "\n Enable support for Company Profile URLs with numerical IDs that you most frequently fetch from Sales Navigator.\n We achieve this by resolving numerical IDs into vanity IDs with cached company profiles from [LinkDB](https://nubela.co/proxycurl/linkdb).\n For example, we will turn `https://www.linkedin.com/company/1234567890` to `https://www.linkedin.com/company/acme-corp` -- for which the API endpoint only supports the latter.\n\n This parameter accepts the following values:\n - `false` - Will not resolve numerical IDs.\n - `true` (default value) - Enable support for Company Profile URLs with numerical IDs.\n Costs an extra `2` credit on top of the base cost of the endpoint.\n ", + "example": "true", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "categories", + "required": false, + "description": "\n Appends categories data of this company.\n\n Default value is `\"exclude\"`.\n The other acceptable value is `\"include\"`, which will include these categories (if available) for `1` extra credit.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "funding_data", + "required": false, + "description": "\n Returns a list of funding rounds that this company has received.\n\n Default value is `\"exclude\"`.\n The other acceptable value is `\"include\"`, which will include these categories (if available) for `1` extra credit.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "exit_data", + "required": false, + "description": "\n Returns a list of investment portfolio exits.\n\n Default value is `\"exclude\"`.\n The other acceptable value is `\"include\"`, which will include these categories (if available) for `1` extra credit.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "acquisitions", + "required": false, + "description": "\n Provides further enriched data on acquisitions made by this company from external sources.\n\n Default value is `\"exclude\"`.\n The other acceptable value is `\"include\"`, which will include these acquisition data (if available) for `1` extra credit.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "extra", + "required": false, + "description": "\n Enriches the Company Profile with extra details from external sources.\n Details include Crunchbase ranking, contact email, phone number, Facebook account, Twitter account, funding rounds and amount, IPO status, investor information, etc.\n\n Default value is `\"exclude\"`.\n The other acceptable value is `\"include\"`, which will include these extra details (if available) for `1` extra credit.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "use_cache", + "required": false, + "description": "\n `if-present` The default behavior.\n Fetches profile from cache regardless of age of profile.\n If profile is not available in cache, API will attempt to source profile externally.\n\n `if-recent` API will make a best effort to return a fresh profile no older than 29 days.\"\n Costs an extra `1` credit on top of the cost of the base endpoint.\n ", + "example": "if-present", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "fallback_to_cache", + "required": false, + "description": "\n Tweaks the fallback behavior if an error arises from fetching a fresh profile.\n\n This parameter accepts the following values:\n * `on-error` (default value) - Fallback to reading the profile from cache if an error arises.\n * `never` - Do not ever read profile from cache.\n ", + "example": "on-error", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkedinCompany" + }, + "example": { + "linkedin_internal_id": "1441", + "description": "A problem isn't truly solved until it's solved for all. Googlers build products that help create opportunities for everyone, whether down the street or across the globe. Bring your insight, imagination and a healthy disregard for the impossible. Bring everything that makes you unique. Together, we can build for everyone.\n\nCheck out our career opportunities at careers.google.com.", + "website": "https://goo.gle/3m1IN7m", + "industry": "Software Development", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 319856, + "hq": { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "search", + "ads" + ], + "locations": [ + { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + { + "country": "US", + "city": "New York", + "postal_code": "10011", + "line_1": "111 8th Ave", + "is_hq": false, + "state": "NY" + } + ], + "name": "Google", + "tagline": null, + "universal_name_id": "google", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3500b39da8db1d2d8f5727a9ac39a7c4a88b4632ed68209dee12f06bc79aca", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abb7a4b87583cffda8db24d58d906c644998fae8cbb99e98c69a35720fcd0050", + "search_id": "1441", + "similar_companies": [ + { + "name": "Amazon", + "link": "https://www.linkedin.com/company/amazon", + "industry": "Software Development", + "location": "Seattle, WA" + }, + { + "name": "Microsoft", + "link": "https://www.linkedin.com/company/microsoft", + "industry": "Software Development", + "location": "Redmond, Washington" + } + ], + "affiliated_companies": [ + { + "name": "YouTube", + "link": "https://www.linkedin.com/company/youtube", + "industry": "Software Development", + "location": "San Bruno, CA" + }, + { + "name": "Google Cloud", + "link": "https://www.linkedin.com/showcase/google-cloud", + "industry": "Software Development", + "location": "Mountain View, California" + } + ], + "updates": [ + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C5605AQFthnjiTD6Mvg/videocover-high/0/1660754102856?e=2147483647&v=beta&t=PPOsA9J3vCTXWhuZclqSBQl7DLSDLvy5hKWlkHI85YE", + "posted_on": { + "day": 13, + "month": 9, + "year": 2022 + }, + "text": "Want to kick start your #LifeAtGoogle but not sure where to begin? Explore our Build Your Future site, where you can learn about developmental programs, learn tips for future interviews, sign up for informational events, and even hear real stories from Googlers who’ve been where you are now. Get started → https://bit.ly/3SKPzQB", + "total_likes": 4267 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C4D22AQGcvTlKRR3qvQ/feedshare-shrink_2048_1536/0/1672854668558?e=1676505600&v=beta&t=whRRx9ULPEuyw_FgUg4Z3N3O9iksyJW7ewCGZA6ujdg", + "posted_on": null, + "text": "Ariana, welcome to Google. Here’s to a year full of growth, learning, and experiences at #LifeAtGoogle! 🎉", + "total_likes": 397 + } + ], + "follower_count": 27472792 + } + } + }, + "description": "Profile data with profile picture, office locations, etc" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Company Profile Endpoint" + }, + "summary": "Company Profile Endpoint" + }, + "/api/v2/linkedin": { + "get": { + "description": "Cost: 1 credit / successful request.\nGet structured data of a Personal Profile", + "parameters": [ + { + "in": "query", + "name": "extra", + "required": false, + "description": "\n Enriches the Person Profile with extra details from external sources.\n Extra details include gender, birth date, industry and interests.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide extra data field.\n - `include` - Append extra data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "github_profile_id", + "required": false, + "description": "\n Enriches the Person Profile with Github Id from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide Github Id data field.\n - `include` - Append Github Id data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "facebook_profile_id", + "required": false, + "description": "\n Enriches the Person Profile with Facebook Id from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide Facebook Id data field.\n - `include` - Append Facebook Id data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_id", + "required": false, + "description": "\n Enriches the Person Profile with Twitter Id from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide Twitter Id data field.\n - `include` - Append Twitter Id data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "personal_contact_number", + "required": false, + "description": "\n Enriches the Person Profile with personal numbers from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide personal numbers data field.\n - `include` - Append personal numbers data to the person profile object.\n Costs an extra `1` credit per email returned on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "personal_email", + "required": false, + "description": "\n Enriches the Person Profile with personal emails from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide personal emails data field.\n - `include` - Append personal emails data to the person profile object.\n Costs an extra `1` credit per email returned on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "inferred_salary", + "required": false, + "description": "\n Include inferred salary range from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide inferred salary data field.\n - `include` - Append inferred salary range data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "skills", + "required": false, + "description": "\n Include skills data from external sources.\n\n This parameter accepts the following values:\n - `exclude` (default value) - Does not provide skills data field.\n - `include` - Append skills data to the person profile object.\n Costs an extra `1` credit on top of the cost of the base endpoint (if data is available).\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "use_cache", + "required": false, + "description": "\n `if-present` The default behavior.\n Fetches profile from cache regardless of age of profile.\n If profile is not available in cache, API will attempt to source profile externally.\n\n `if-recent` API will make a best effort to return a fresh profile no older than 29 days.\"\n Costs an extra `1` credit on top of the cost of the base endpoint.\n ", + "example": "if-present", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "fallback_to_cache", + "required": false, + "description": "\n Tweaks the fallback behavior if an error arises from fetching a fresh profile.\n\n This parameter accepts the following values:\n * `on-error` (default value) - Fallback to reading the profile from cache if an error arises.\n * `never` - Do not ever read profile from cache.\n ", + "example": "on-error", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL from which you wish to extract person profile\n\n URL should be in the format of `https://x.com/`\n \nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://x.com/johnrmarty/", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "facebook_profile_url", + "required": false, + "description": "\n The Facebook Profile URL from which you wish to extract person profile\n\n URL should be in the format of `https://facebook.com/`\n \nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://facebook.com/johnrmarty/", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL from which you wish to extract person profile\n\n URL should be in the format of `https://linkedin.com/in/`\n \nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://linkedin.com/in/johnrmarty/", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PersonEndpointResponse" + }, + "example": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + } + } + }, + "description": "Profile data with profile picture, job history, etc." + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "People API" + ], + "operationId": "Person Profile Endpoint" + }, + "summary": "Person Profile Endpoint" + }, + "/api/customers": { + "get": { + "description": "Cost: 10 credits / result for users on an annual subscription or Enterprise plan.\nGet a list of probable corporate customers of a target company.", + "parameters": [ + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL of the company from which you want to get a list of customers of.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://www.linkedin.com/company/watsons", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL belonging to the company that you want to get a list of customers of.\n\n URL should be in the format of `https://x.com/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://x.com/watsonsproperty", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Limit the maximum results of customer companies returned per API call.\n\n The default value of this parameter is 10.\n\n Accepted values for this parameter is an integer ranging from 0 to 1000.\n ", + "example": "10", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerList" + }, + "example": { + "companies": [ + { + "linkedin_company_profile_url": "https://www.linkedin.com/company/spire-solicitors-llp", + "twitter_profile_url": "https://twitter.com/spirellp", + "email": "info@spiresolicitors.co.uk" + }, + { + "linkedin_company_profile_url": "https://www.linkedin.com/company/mall-wood-insurance-services-ltd", + "twitter_profile_url": "https://twitter.com/draytonins", + "email": null + } + ], + "next_page": null + } + } + }, + "description": "A list of probable customers of the target company." + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Customer API `EXPERIMENTAL`" + ], + "operationId": "Customer Listing Endpoint `EXPERIMENTAL`" + }, + "summary": "Customer Listing Endpoint `EXPERIMENTAL`" + }, + "/api/customers/count/": { + "get": { + "description": "Cost: 1 credit / result for users on an annual subscription or Enterprise plan.\nGet the total count of probable corporate customers of a target company.", + "parameters": [ + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL of the company from which you want to get a list of customers of.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://www.linkedin.com/company/watsons", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL belonging to the company that you want to get a list of customers of.\n\n URL should be in the format of https://x.com/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://x.com/watsonsproperty", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerCount" + }, + "example": { + "company_count": 125 + } + } + }, + "description": "Number of probable customers of the target company." + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Customer API `EXPERIMENTAL`" + ], + "operationId": "Customer Listing Count Endpoint `EXPERIMENTAL`" + }, + "summary": "Customer Listing Count Endpoint `EXPERIMENTAL`" + }, + "/api/linkedin/company/employees/": { + "get": { + "description": "Cost: 3 credits / employee returned.\nGet a list of employees of a Company.\n\nThis API endpoint is powered by [LinkDB](https://nubela.co/proxycurl/linkdb), our comprehensive dataset of people and company profiles.", + "parameters": [ + { + "in": "query", + "name": "country", + "required": false, + "description": "\n Limit the result set to the country locality of the profile. For example, set the parameter of `country=us` if you only want profiles from the US. Or you can set the parameter to `country=us,sg` if you want employees from both the US and Singapore.\n\n This parameter accepts a comma-separated case-insensitive values of [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n\n Costs an extra `3` credit per result returned.\n ", + "example": "us", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profiles", + "required": false, + "description": "\n Get the full profile of employees instead of only their profile urls.\n\n Each request respond with a streaming response of profiles.\n\n The valid values are:\n \n * `skip` (default): lists employee's profile url\n * `enrich`: lists full profile of employees\n\n Calling this API endpoint with this parameter would add `1` credit per employee returned.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "role_search", + "required": false, + "description": "\n Filter employees by their title by matching the employee's title against a *regular expression*.\n\n The default value of this parameter is `null`.\n\n The accepted value for this parameter is a **case-insensitive** regular expression.\n\n (The base cost of calling this API endpoint with this parameter would be `10` credits.\n Each employee matched and returned would cost 3 extra credits.)\n ", + "example": "(co)?-?founder", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Limit the maximum results returned per API call.\n\n The default value of this parameter is `10`.\n\n Accepted values for this parameter is an integer ranging from `1` to `200000`.\n\n When `enrich_profiles=enrich`, this parameter accepts value ranging from `1` to `10` and the default value is `10`.\n ", + "example": "10", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "employment_status", + "required": false, + "description": "\n Parameter to tell the API to return past or current employees.\n\n Valid values are `current`, `past`, and `all`:\n\n * `current` (default) : lists current employees\n * `past` : lists past employees\n * `all` : lists current & past employees\n ", + "example": "current", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort_by", + "required": false, + "description": "\n Sort employees by recency.\n\n Valid values are:\n * `recently-joined` - Sort employees by their join date. The most recent employee is on the top of the list.\n * `recently-left` - Sort employees by their departure date. The most recent employee who had just left is on the top of this list.\n * `oldest` - Returns the oldest employees first. The oldest employee who had joined this company historically is on the top of this list.\n * `none` - The default value. Do not sort.\n\n If this parameter is supplied with a value other than `none`, will add `50` credits to the base cost of the API endpoint regardless number of results returned. It will also add an additional cost of `10` credits per employee returned.\n ", + "example": "recently-joined", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "resolve_numeric_id", + "required": false, + "description": "\n Enable support for Company Profile URLs with numerical IDs that you most frequently fetch from Sales Navigator. \n We achieve this by resolving numerical IDs into vanity IDs with cached company profiles from [LinkDB](https://nubela.co/proxycurl/linkdb). \n For example, we will turn `https://www.linkedin.com/company/1234567890` to `https://www.linkedin.com/company/acme-corp` -- for which the API endpoint only supports the latter.\n \n This parameter accepts the following values:\n - `false` (default value) - Will not resolve numerical IDs.\n - `true` - Enable support for Company Profile URLs with numerical IDs. \n Costs an extra `2` credit on top of the base cost of the endpoint.\n ", + "example": "false", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "url", + "required": true, + "description": "\n URL of the LinkedIn Company Profile to target.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n ", + "example": "https://www.linkedin.com/company/microsoft", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmployeeList" + }, + "example": { + "employees": [ + { + "profile_url": "https://www.linkedin.com/in/williamhgates", + "profile": { + "public_identifier": "williamhgates", + "profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "background_cover_image_url": null, + "first_name": "Bill", + "last_name": "Gates", + "full_name": "Bill Gates", + "occupation": "Co-chair at Bill & Melinda Gates Foundation", + "headline": "Co-chair, Bill & Melinda Gates Foundation", + "summary": "Co-chair of the Bill & Melinda Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "company": "Breakthrough Energy ", + "company_linkedin_profile_url": "https://www.linkedin.com/company/breakthrough-energy/", + "title": "Founder", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQGwD9vNu044FA/company-logo_400_400/0/1601560874941?e=1672876800&v=beta&t=VKb6OAHEwlnazKYKm4fc9go-y4zkUv2BT6tosOdQ54Y" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2000 + }, + "ends_at": null, + "company": "Bill & Melinda Gates Foundation", + "company_linkedin_profile_url": "https://www.linkedin.com/company/bill-&-melinda-gates-foundation/", + "title": "Co-chair", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQE7Na_mKQhIJg/company-logo_400_400/0/1633731810932?e=1672876800&v=beta&t=Mz_ntwD4meCMcgo1L3JqDxBQRabFLIesd0Yz2ciAXNs" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 1973 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 1975 + }, + "field_of_study": null, + "degree_name": null, + "school": "Harvard University", + "school_linkedin_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQF5t62bcL0e9g/company-logo_400_400/0/1519855919126?e=1672876800&v=beta&t=9twXof1JlnNHfFprrDMi-C1Kp55HTT4ahINKHRflUHw" + }, + { + "starts_at": null, + "ends_at": null, + "field_of_study": null, + "degree_name": null, + "school": "Lakeside School", + "school_linkedin_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQENlfOPKBEk3Q/company-logo_400_400/0/1519856497259?e=1672876800&v=beta&t=v7nJTPaJMfH7WOBjb22dyvNKxAgdPdVd8uLCUkMB1LQ" + } + ], + "languages": [], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [], + "connections": null, + "people_also_viewed": [], + "recommendations": [], + "activities": [], + "similarly_named_profiles": [], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null + } + } + }, + "description": "List of employees" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Employee Listing Endpoint" + }, + "summary": "Employee Listing Endpoint" + }, + "/api/linkedin/company/employees/count": { + "get": { + "description": "Cost: 1 credit / successful request.\nGet a number of total employees of a Company.\n\nGet an employee count of this company from various sources.", + "parameters": [ + { + "in": "query", + "name": "use_cache", + "required": false, + "description": "\n `if-present`: The default behavior. Fetches data from LinkDB cache regardless of age of profile.\n\n `if-recent`: API will make a best effort to return a fresh data no older than 29 days. Costs an extra 1 credit on top of the cost of the base endpoint.\n ", + "example": "if-present", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_employee_count", + "required": false, + "description": "\n Option to include a scraped employee count value from the target company's LinkedIn profile.\n\n Valid values are `include` and `exclude`:\n\n * `exclude` (default) : To exclude the scraped employee count.\n * `include` : To include the scraped employee count.\n\n Costs an extra `1` credit on top of the base cost of the endpoint.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "employment_status", + "required": false, + "description": "\n Parameter to tell the API to filter past or current employees.\n\n Valid values are `current`, `past`, and `all`:\n\n * `current` (default) : count current employees\n * `past` : count past employees\n * `all` : count current & past employees\n ", + "example": "current", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "url", + "required": true, + "description": "\n URL of the LinkedIn Company Profile to target.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n ", + "example": "https://www.linkedin.com/company/apple/", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmployeeCount" + }, + "example": { + "linkedin_employee_count": 529274, + "linkdb_employee_count": 3 + } + } + }, + "description": "Number of employees in a company" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Employee Count Endpoint" + }, + "summary": "Employee Count Endpoint" + }, + "/api/linkedin/person/profile-picture": { + "get": { + "description": "Cost: 0 credit / successful request.\nGet the profile picture of a person.\n\nProfile pictures are served from cached people profiles found within [LinkDB](https://nubela.co/proxycurl/linkdb).\nIf the profile does not exist within [LinkDB](https://nubela.co/proxycurl/linkdb), then the API will return a `404` status code.", + "parameters": [ + { + "in": "query", + "name": "linkedin_person_profile_url", + "required": true, + "description": "\n LinkedIn Profile URL of the person that you are trying to get the profile picture of.\n ", + "example": "https://www.linkedin.com/in/williamhgates/", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfilePicture" + }, + "example": { + "tmp_profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU" + } + } + }, + "description": "Profile picture of a person" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "People API" + ], + "operationId": "Person Profile Picture Endpoint" + }, + "summary": "Person Profile Picture Endpoint" + }, + "/api/linkedin/company/profile-picture": { + "get": { + "description": "Cost: 0 credit / successful request.\nGet the profile picture of a company.\n\nProfile pictures are served from cached company profiles found within [LinkDB](https://nubela.co/proxycurl/linkdb).\nIf the profile does not exist within [LinkDB](https://nubela.co/proxycurl/linkdb), then the API will return a `404` status code.", + "parameters": [ + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": true, + "description": "\n LinkedIn Profile URL of the company that you are trying to get the profile picture of.\n ", + "example": "https://www.linkedin.com/company/apple/", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfilePicture" + }, + "example": { + "tmp_profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU" + } + } + }, + "description": "Profile picture of a company" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Company Profile Picture Endpoint" + }, + "summary": "Company Profile Picture Endpoint" + }, + "/api/linkedin/profile/resolve": { + "get": { + "description": "Cost: 2 credits / successful request.\nLook up a person with a name and company information.", + "parameters": [ + { + "in": "query", + "name": "similarity_checks", + "required": false, + "description": "\n Controls whether the API endpoint performs\n similarity comparisons between the input parameters\n and the results or simply returns the closest match.\n For instance, if you are searching for a person named\n \"Ben Chad\", and the closest result we have is \"Chavvy\n Plum\", our similarity checks will discard the obviously\n incorrect result and return `null` instead of a false\n positive.\n\n Include similarity checks to eliminate false positives.\n However, be aware that this might yield fewer results\n as false positives are discarded. Credits will still be\n deducted even if we return `null`.\n\n You can choose to skip similarity checks, in which\n case no credits will be charged if we return `null`.\n\n This parameter accepts the following values:\n * `include` (default) - Perform similarity checks and\n discard false positives. Credits will be deducted even\n if we return null .\n * `skip` - Bypass similarity checks. No credits will be\n deducted if no results are returned.\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profile", + "required": false, + "description": "\n Enrich the result with a cached profile of the lookup result.\n\n The valid values are:\n\n * `skip` (default): do not enrich the results with cached profile data\n * `enrich`: enriches the result with cached profile data\n\n Calling this API endpoint with this parameter would add 1 credit.\n\n If you require [fresh profile data](https://nubela.co/blog/how-fresh-are-profiles-returned-by-proxycurl-api/),\n please chain this API call with the [People Profile Endpoint](https://nubela.co/proxycurl/docs#people-api-person-profile-endpoint) with the `use_cache=if-recent` parameter.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "company_domain", + "required": true, + "description": "Company name or domain", + "example": "gatesfoundation.org", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "location", + "required": false, + "description": "\n The location of this user.\n\n Name of country, city or state.\n ", + "example": "Seattle", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "title", + "required": false, + "description": "Title that user is holding at his/her current job", + "example": "Co-chair", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "last_name", + "required": false, + "description": "Last name of the user", + "example": "Gates", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "first_name", + "required": true, + "description": "First name of the user", + "example": "Bill", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PersonLookupUrlEnrichResult" + }, + "example": { + "url": "https://www.linkedin.com/in/senatormarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + } + }, + "description": "LinkedIn (Person) Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "People API" + ], + "operationId": "Person Lookup Endpoint" + }, + "summary": "Person Lookup Endpoint" + }, + "/api/v2/linkedin/company/job": { + "get": { + "description": "Cost: 2 credits / successful request.\nList jobs posted by a company on LinkedIn", + "parameters": [ + { + "in": "query", + "name": "job_type", + "required": false, + "description": "\n The nature of the job.\n It accepts the following 7 case-insensitive values only:\n - `full-time`\n - `part-time`\n - `contract`\n - `internship`\n - `temporary`\n - `volunteer`\n - `anything` (default)\n ", + "example": "anything", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "experience_level", + "required": false, + "description": "\n The experience level needed for the job.\n It accepts the following 6 case-insensitive values only:\n - `internship`\n - `entry_level`\n - `associate`\n - `mid_senior_level`\n - `director`\n - `anything` (default)\n ", + "example": "entry_level", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "when", + "required": false, + "description": "\n The time when the job is posted,\n It accepts the following case-insensitive values only:\n - `yesterday`\n - `past-week`\n - `past-month`\n - `anytime` (default)\n ", + "example": "past-month", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "flexibility", + "required": false, + "description": "\n The flexibility of the job.\n It accepts the following 3 case insensitive values only:\n - `remote`\n - `on-site`\n - `hybrid`\n - `anything` (default)\n ", + "example": "remote", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "geo_id", + "required": false, + "description": "\n The `geo_id` of the location to search for.\n For example, `92000000` is the `geo_id` of world wide.\n\n See [this article](https://nubela.co/blog/how-to-fetch-geo_id-parameter-for-the-job-api/?utm_source=blog&utm_medium=web&utm_campaign=docs-redirect-to-geo_id-article) as to how you may be able to match regions to `geo_id` input values.\n ", + "example": "92000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "keyword", + "required": false, + "description": "\n The keyword to search for.\n ", + "example": "software engineer", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "search_id", + "required": false, + "description": "\n The `search_id` of the company on LinkedIn.\n You can get the `search_id` of a LinkedIn company via\n [Company Profile API](#company-api-company-profile-endpoint).\n ", + "example": "1035", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobListPage" + }, + "example": { + "job": [ + { + "company": "Microsoft", + "company_url": "https://www.linkedin.com/company/microsoft", + "job_title": "Product Management: Intern Opportunities for University Students", + "job_url": "https://www.linkedin.com/jobs/view/product-management-intern-opportunities-for-university-students-at-microsoft-3203330682", + "list_date": "2022-10-09", + "location": "New York, NY" + }, + { + "company": "Microsoft", + "company_url": "https://www.linkedin.com/company/microsoft", + "job_title": "Content Strategist", + "job_url": "https://www.linkedin.com/jobs/view/content-strategist-at-microsoft-3257692764", + "list_date": "2022-10-21", + "location": "United States" + } + ], + "next_page_no": 1, + "next_page_api_url": "http://nubela.co/proxycurl/proxycurl/api/v2/linkedin/company/job?pagination=eyJwYWdlIjogMX0&search_id=1035", + "previous_page_no": null, + "previous_page_api_url": null + } + } + }, + "description": "List of open job position" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Jobs API" + ], + "operationId": "Job Search Endpoint" + }, + "summary": "Job Search Endpoint" + }, + "/api/v2/linkedin/company/job/count": { + "get": { + "description": "Cost: 2 credits / successful request.\nCount number of jobs posted by a company on LinkedIn", + "parameters": [ + { + "in": "query", + "name": "job_type", + "required": false, + "description": "\n The nature of the job.\n It accepts the following 7 case-insensitive values only:\n - `full-time`\n - `part-time`\n - `contract`\n - `internship`\n - `temporary`\n - `volunteer`\n - `anything` (default)\n ", + "example": "entry_level", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "experience_level", + "required": false, + "description": "\n The experience level needed for the job.\n It accepts the following 6 case-insensitive values only:\n - `internship`\n - `entry_level`\n - `associate`\n - `mid_senior_level`\n - `director`\n - `anything` (default)\n ", + "example": "entry_level", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "when", + "required": false, + "description": "\n The time when the job is posted,\n It accepts the following case-insensitive values only:\n - `yesterday`\n - `past-week`\n - `past-month`\n - `anytime` (default)\n ", + "example": "past-month", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "flexibility", + "required": false, + "description": "\n The flexibility of the job.\n It accepts the following 3 case insensitive values only:\n - `remote`\n - `on-site`\n - `hybrid`\n - `anything` (default)\n ", + "example": "remote", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "geo_id", + "required": false, + "description": "\n The `geo_id` of the location to search for.\n For example, `92000000` is the `geo_id` of world wide.\n\n See [this article](https://nubela.co/blog/how-to-fetch-geo_id-parameter-for-the-job-api/?utm_source=blog&utm_medium=web&utm_campaign=docs-redirect-to-geo_id-article) as to how you may be able to match regions to `geo_id` input values.\n ", + "example": "92000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "keyword", + "required": false, + "description": "\n The keyword to search for.\n ", + "example": "software engineer", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "search_id", + "required": false, + "description": "\n The `search_id` of the company on LinkedIn.\n You can get the `search_id` of a LinkedIn company via\n [Company Profile API](#company-api-company-profile-endpoint).\n ", + "example": "1035", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobListCount" + }, + "example": { + "count": 887622 + } + } + }, + "description": "Count number of jobs posted" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Jobs API" + ], + "operationId": "Jobs Listing Count Endpoint" + }, + "summary": "Jobs Listing Count Endpoint" + }, + "/api/find/company/role/": { + "get": { + "description": "Cost: 3 credits / successful request.\nReturns the profile of a person who most closely matches a specified role\nin a company. For instance, it can be used to identify the \"CTO\" of\n\"Apple\". The endpoint yields a single result that represents the closest\nmatch. For a detailed comparison between this API endpoint and the\n[Employee Search Endpoint](#company-api-employee-search-endpoint)\nor the [Person Search Endpoint](#search-api-person-search-endpoint),\nrefer to [this article](\n https://nubela.co/blog/what-is-the-difference-between-the-person-search-endpoint-role-lookup-endpoint-and-the-employee-search-endpoint).", + "parameters": [ + { + "in": "query", + "name": "enrich_profile", + "required": false, + "description": "\n Enrich the result with a cached profile of the lookup result.\n\n The valid values are:\n\n * `skip` (default): do not enrich the results with cached profile data\n * `enrich`: enriches the result with cached profile data\n\n Calling this API endpoint with this parameter would add 1 credit.\n\n If you require [fresh profile data](https://nubela.co/blog/how-fresh-are-profiles-returned-by-proxycurl-api/),\n please chain this API call with the [Person Profile Endpoint](#people-api-person-profile-endpoint) with the `use_cache=if-recent` parameter.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "role", + "required": true, + "description": "Role of the profile that you are lookin up", + "example": "ceo", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "company_name", + "required": true, + "description": "Name of the company that you are searching for", + "example": "nubela", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RoleSearchEnrichedResult" + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/senatormarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + } + }, + "description": "LinkedIn (Person) Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "People API" + ], + "operationId": "Role Lookup Endpoint" + }, + "summary": "Role Lookup Endpoint" + }, + "/api/linkedin/company/resolve": { + "get": { + "description": "Cost: 2 credits / successful request.\nResolve Company LinkedIn Profile from company name,\n domain name and location.", + "parameters": [ + { + "in": "query", + "name": "company_location", + "required": false, + "description": "\n The location / region of company.\n ISO 3166-1 alpha-2 codes\n ", + "example": "sg", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "company_domain", + "required": false, + "description": "Company website or Company domain\nRequires either `company_domain` or `company_name`", + "example": "accenture.com", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "company_name", + "required": false, + "description": "Company Name\nRequires either `company_domain` or `company_name`", + "example": "Accenture", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profile", + "required": false, + "description": "\n Enrich the result with a cached profile of the lookup result.\n\n The valid values are:\n\n * `skip` (default): do not enrich the results with cached profile data\n * `enrich`: enriches the result with cached profile data\n\n Calling this API endpoint with this parameter would add 1 credit.\n\n If you require [fresh profile data](https://nubela.co/blog/how-fresh-are-profiles-returned-by-proxycurl-api/),\n please chain this API call with the [Company Profile Endpoint](https://nubela.co/proxycurl/docs#company-api-company-profile-endpoint) with the `use_cache=if-recent` parameter.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanyUrlEnrichResult" + }, + "example": { + "url": "https://www.linkedin.com/company/accenture", + "profile": { + "linkedin_internal_id": "1033", + "description": "Accenture is a global professional services company with leading capabilities in digital, cloud, and security. Combining unmatched experience and specialized skills across more than 40 industries, we offer Strategy and Consulting, Technology and Operations Services, and Accenture Song—all powered by the world’s largest network of Advanced Technology and Intelligent Operations centers. \n\nOur people deliver on the promise of technology and human ingenuity every day, serving clients in more than 120 countries. We embrace the power of change to create value and shared success for our clients, people, shareholders, partners, and communities. \n\nVisit us at accenture.com.", + "website": "http://www.accenture.com", + "industry": "Business Consulting and Services", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 541251, + "hq": { + "country": "IE", + "city": "Dublin 2", + "postal_code": null, + "line_1": "Grand Canal Harbour", + "is_hq": true, + "state": null + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "Management Consulting", + "Systems Integration and Technology" + ], + "locations": [ + { + "country": "IE", + "city": "Dublin 2", + "postal_code": null, + "line_1": "Grand Canal Harbour", + "is_hq": true, + "state": null + }, + { + "country": "US", + "city": "San Francisco", + "postal_code": "94105", + "line_1": "415 Mission Street Floor 31-34", + "is_hq": false, + "state": "California" + } + ], + "name": "Accenture", + "tagline": null, + "universal_name_id": "accenture", + "profile_pic_url": "https://media.licdn.com/dms/image/D4E0BAQGTUswcRlgg9A/company-logo_200_200/0/1689352303421/accenture_logo?e=2147483647&v=beta&t=cjQy2p9bf0c2mJqCNVzaiLqdByE0zboCX3vY5m4gRuY", + "background_cover_image_url": "https://media.licdn.com/dms/image/D4E3DAQEJ2lIxxNO81Q/image-scale_191_1128/0/1689359170613/accenture_cover?e=1698901200&v=beta&t=8ygpwsa5GjMoubooCGg1MqfGomnBaU9WHwnI3_Ek0_0", + "search_id": "1033", + "similar_companies": [ + { + "name": "Deloitte", + "link": "https://www.linkedin.com/company/deloitte", + "industry": "Business Consulting and Services", + "location": null + }, + { + "name": "Tata Consultancy Services", + "link": "https://in.linkedin.com/company/tata-consultancy-services", + "industry": "IT Services and IT Consulting", + "location": "Mumbai, Maharashtra" + } + ], + "affiliated_companies": [ + { + "name": "Accenture in India", + "link": "https://in.linkedin.com/company/accentureindia", + "industry": "IT Services and IT Consulting", + "location": "Bengaluru, Karnatka" + }, + { + "name": "Accenture Brasil", + "link": "https://br.linkedin.com/company/accenturebrasil", + "industry": "IT Services and IT Consulting", + "location": "São Paulo, São Paulo" + } + ], + "updates": [ + { + "article_link": null, + "image": null, + "posted_on": { + "day": 25, + "month": 10, + "year": 2023 + }, + "text": "Explore #AccentureLifeTrends 2024 to learn more: https://accntu.re/3MfdMg4", + "total_likes": 325 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/D5610AQEMoO_uNVz5BQ/ads-video-thumbnail_720_1280/0/1698154984087?e=1698901200&v=beta&t=WTxhLNSbSM-UBnFIcqYX4bdVhVUD6OoOoffR0xQnlDA", + "posted_on": { + "day": 25, + "month": 10, + "year": 2023 + }, + "text": "The ability to learn new things, without forgetting those that came before, is a huge differentiator between the #AI we're familiar with, and the #GenerativeAI powered by foundation models that we're seeing now.\n \nDiscover the trends shaping the next decade: https://accntu.re/474YxOH\n \n#TechVision2023", + "total_likes": 541 + } + ], + "follower_count": 11125167, + "acquisitions": null, + "exit_data": null, + "extra": null, + "funding_data": null, + "categories": null + }, + "last_updated": "2023-10-26T11:33:24Z" + } + } + }, + "description": "LinkedIn (Company) Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Company Lookup Endpoint" + }, + "summary": "Company Lookup Endpoint" + }, + "/api/linkedin/company/employee/search/": { + "get": { + "description": "Cost: 10 credits / successful request.\nSearch employees of a target by their job title. This API endpoint is syntactic\nsugar for the role_search parameter under the [Employee Listing Endpoint](#company-api-employee-listing-endpoint).\nThis API endpoint is powered by [LinkDB](https://nubela.co/proxycurl/linkdb), our comprehensive dataset of people\nand company profiles. For a detailed comparison between this API endpoint\nand the [Role Lookup Endpoint](#people-api-role-lookup-endpoint) or the [Person Search Endpoint](#search-api-person-search-endpoint), refer to [this article](https://nubela.co/blog/what-is-the-difference-between-the-person-search-endpoint-role-lookup-endpoint-and-the-employee-search-endpoint).", + "parameters": [ + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Tune the maximum results returned per API call.\n The default value of this parameter is `200000`.\n Accepted values for this parameter is an integer ranging from `1` to `200000`.\n When `enrich_profiles=enrich`, this parameter accepts value ranging from `1` to `10` and the default value is `100`.\n ", + "example": "10", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": true, + "description": "\n LinkedIn Profile URL of the target company.\n ", + "example": "https://www.linkedin.com/company/microsoft/", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "keyword_regex", + "required": true, + "description": "\n Job title keyword to search for in regular expression format.\n\n The accepted value for this parameter is a **case-insensitive** regular expression.\n ", + "example": "ceo|cto", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "country", + "required": false, + "description": "\n Limit the result set to the country locality of the profile. For example, set the parameter of `country=us` if you only want profiles from the US.\n\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n\n Costs an extra `3` credit per result returned.\n ", + "example": "us", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profiles", + "required": false, + "description": "\n Get the full profile of employees instead of only their profile urls.\n\n Each request respond with a streaming response of profiles.\n\n The valid values are:\n \n * `skip` (default): lists employee's profile url\n * `enrich`: lists full profile of employees\n\n Calling this API endpoint with this parameter would add `1` credit per employee returned.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "resolve_numeric_id", + "required": false, + "description": "\n Enable support for Company Profile URLs with numerical IDs that you most frequently fetch from Sales Navigator. \n We achieve this by resolving numerical IDs into vanity IDs with cached company profiles from [LinkDB](https://nubela.co/proxycurl/linkdb). \n For example, we will turn `https://www.linkedin.com/company/1234567890` to `https://www.linkedin.com/company/acme-corp` -- for which the API endpoint only supports the latter.\n \n This parameter accepts the following values:\n - `false` (default value) - Will not resolve numerical IDs.\n - `true` - Enable support for Company Profile URLs with numerical IDs. \n Costs an extra `2` credit on top of the base cost of the endpoint.\n ", + "example": "false", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmployeeList" + }, + "example": { + "employees": [ + { + "profile_url": "https://www.linkedin.com/in/satyanadella", + "profile": { + "public_identifier": "williamhgates", + "profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "background_cover_image_url": null, + "first_name": "Bill", + "last_name": "Gates", + "full_name": "Bill Gates", + "occupation": "Co-chair at Bill & Melinda Gates Foundation", + "headline": "Co-chair, Bill & Melinda Gates Foundation", + "summary": "Co-chair of the Bill & Melinda Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "company": "Breakthrough Energy ", + "company_linkedin_profile_url": "https://www.linkedin.com/company/breakthrough-energy/", + "title": "Founder", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQGwD9vNu044FA/company-logo_400_400/0/1601560874941?e=1672876800&v=beta&t=VKb6OAHEwlnazKYKm4fc9go-y4zkUv2BT6tosOdQ54Y" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2000 + }, + "ends_at": null, + "company": "Bill & Melinda Gates Foundation", + "company_linkedin_profile_url": "https://www.linkedin.com/company/bill-&-melinda-gates-foundation/", + "title": "Co-chair", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQE7Na_mKQhIJg/company-logo_400_400/0/1633731810932?e=1672876800&v=beta&t=Mz_ntwD4meCMcgo1L3JqDxBQRabFLIesd0Yz2ciAXNs" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 1973 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 1975 + }, + "field_of_study": null, + "degree_name": null, + "school": "Harvard University", + "school_linkedin_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQF5t62bcL0e9g/company-logo_400_400/0/1519855919126?e=1672876800&v=beta&t=9twXof1JlnNHfFprrDMi-C1Kp55HTT4ahINKHRflUHw" + }, + { + "starts_at": null, + "ends_at": null, + "field_of_study": null, + "degree_name": null, + "school": "Lakeside School", + "school_linkedin_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQENlfOPKBEk3Q/company-logo_400_400/0/1519856497259?e=1672876800&v=beta&t=v7nJTPaJMfH7WOBjb22dyvNKxAgdPdVd8uLCUkMB1LQ" + } + ], + "languages": [], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [], + "connections": null, + "people_also_viewed": [], + "recommendations": [], + "activities": [], + "similarly_named_profiles": [], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null + } + } + }, + "description": "List of employees" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Company API" + ], + "operationId": "Employee Search Endpoint" + }, + "summary": "Employee Search Endpoint" + }, + "/api/linkedin/school/students/": { + "get": { + "description": "Cost: 3 credits / student returned.\nGet a list of students of a school or university.", + "parameters": [ + { + "in": "query", + "name": "country", + "required": false, + "description": "\n Limit the result set to the country locality of the profile. For example, set the parameter of `country=us` if you only want profiles from the US.\n\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n\n Costs an extra `3` credit per result returned.\n ", + "example": "us", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profiles", + "required": false, + "description": "\n Get the full profile of students instead of only their profile urls.\n\n Each request respond with a streaming response of profiles.\n\n The valid values are:\n \n * `skip` (default): lists student's profile url\n * `enrich`: lists full profile of students\n\n *Calling this API endpoint with this parameter would add `1` credit per student returned.*\n ", + "example": "enrich", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "search_keyword", + "required": false, + "description": "\n Filter students by their major by matching the student's major against a *regular expression*.\n\n The default value of this parameter is `null`.\n\n The accepted value for this parameter is a **case-insensitive** regular expression.\n\n (The base cost of calling this API endpoint with this parameter would be `10` credits.\n Each student matched and returned would cost `6` credits per student returned.)\n ", + "example": "computer*|cs", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Limit the maximum results returned per API call.\n\n The default value of this parameter is `10`.\n\n Accepted values for this parameter is an integer ranging from `1` to `200000`.\n\n When `enrich_profiles=enrich`, this parameter accepts value ranging from `1` to `10` and the default value is `10`.\n ", + "example": "10", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "student_status", + "required": false, + "description": "\n Parameter to tell the API to return past or current students.\n\n Valid values are `current`, `past`, and `all`:\n\n * `current` (default) : lists current students\n * `past` : lists past students\n * `all` : lists current & past students\n ", + "example": "current", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort_by", + "required": false, + "description": "\n Sort students by matriculation or graduation dates.\n\n Valid values are:\n * `recently-matriculated` - Sort students by their matriculation date. Students who had had most recently started school is on the top of the list.\n * `recently-graduated` - Sort students by their graduation date. The most recently graduated student is on the top of this list.\n * `none` - The default value. Do not sort.\n\n If this parameter is supplied with a value other than `none`, will add `50` credits to the base cost of the API endpoint regardless number of results returned. It will also add an additional cost of `10` credits per student returned.\n ", + "example": "recently-matriculated", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "resolve_numeric_id", + "required": false, + "description": "\n Enable support for School Profile URLs with numerical IDs that you most frequently fetch from Sales Navigator. \n We achieve this by resolving numerical IDs into vanity IDs with cached company profiles from [LinkDB](https://nubela.co/proxycurl/linkdb). \n For example, we will turn `https://www.linkedin.com/school/1234567890` to `https://www.linkedin.com/school/acme-corp` -- for which the API endpoint only supports the latter.\n \n This parameter accepts the following values:\n - `false` (default value) - Will not resolve numerical IDs.\n - `true` - Enable support for School Profile URLs with numerical IDs. \n Costs an extra `2` credit on top of the base cost of the endpoint.\n ", + "example": "false", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_school_url", + "required": true, + "description": "\n URL of the LinkedIn School Profile to target.\n\n URL should be in the format of `https://www.linkedin.com/school/`\n ", + "example": "https://www.linkedin.com/school/stanford-university", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StudentList" + }, + "example": { + "students": [ + { + "profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null + } + } + }, + "description": "List of students" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "School API" + ], + "operationId": "Student Listing Endpoint" + }, + "summary": "Student Listing Endpoint" + }, + "/api/linkedin/profile/resolve/email": { + "get": { + "description": "Cost: 3 credits / successful request.\nResolve social media profiles correlated from an email address.\nThis API endpoint works with both personal and work emails.", + "parameters": [ + { + "in": "query", + "name": "email", + "required": false, + "description": "Email address of the user you want to look up.\nyes", + "example": "danial@nubela.co", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "lookup_depth", + "required": false, + "description": "\n This parameter describes the depth options for our API lookup function. This endpoint can execute either a superficial or a deep lookup.\n\n A **superficial lookup** involves comparing the provided email with entries in our database. This approach tends to yield fewer results and is typically less effective for work-related email addresses. However, it does not consume any credits if no results are returned.\n\n On the other hand, a **deep lookup** extends beyond our database to utilize advanced heuristics and identify the individual associated with a given email. This method is particularly recommended for work emails.\n\n Please note the following valid values for the depth of the lookup:\n\n * `superficial`: No credits are consumed if no results are found.\n * `deep` (default): Credits are used regardless of whether any results are returned.\n \nyes", + "example": "deep", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profile", + "required": false, + "description": "\n Enrich the result with a cached LinkedIn profile of the LinkedIn Profile URL result (if any).\n\n Valid values are:\n\n * `skip` (default): do not enrich the results with cached profile data.\n * `enrich`: enriches the result with cached profile data. \n\n Calling this API endpoint with this parameter would add `1` additional credit.\n\n If you require [fresh profile data](https://nubela.co/blog/how-fresh-are-profiles-returned-by-proxycurl-api/), please chain this API call with the `linkedin_profile_url` result with the [Person Profile Endpoint](https://nubela.co/proxycurl/docs#people-api-person-profile-endpoint) with the `use_cache=if-recent` parameter.\n \nno", + "example": "enrich", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReverseEmailUrlEnrichResult" + }, + "example": { + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + } + }, + "description": "Twitter, Facebook, and LinkedIn (Person) Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Reverse Email Lookup Endpoint" + }, + "summary": "Reverse Email Lookup Endpoint" + }, + "/api/resolve/phone": { + "get": { + "description": "Cost: 3 credits / successful request.\nFind social media profiles from a contact phone number.", + "parameters": [ + { + "in": "query", + "name": "phone_number", + "required": true, + "description": "[E.164 formatted](https://www.twilio.com/docs/glossary/what-e164) phone number of the person you want to identify social media profiles of.", + "example": "+14155552671", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReverseContactNumberResult" + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/senatormarty", + "twitter_profile_url": "https://www.twitter.com/proxycurl", + "facebook_profile_url": "https://www.facebook.com/zuck" + } + } + }, + "description": "Twitter, Facebook, and LinkedIn Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Reverse Contact Number Lookup Endpoint" + }, + "summary": "Reverse Contact Number Lookup Endpoint" + }, + "/api/linkedin/profile/email": { + "get": { + "description": "Cost: 3 credits / request.\nLookup work email address of a LinkedIn Person Profile.\n\nEmail addresses returned are verified to not be role-based or catch-all emails. Email addresses\nreturned by our API endpoint come with a 95+% deliverability guarantee\n\n**Endpoint behavior**\n\n*This endpoint* **_may not_** *return results immediately.*\n\nIf you provided a webhook in your request parameter, our application will call your webhook with\nthe result once. See `Webhook request` below.", + "parameters": [ + { + "in": "query", + "name": "linkedin_profile_url", + "required": true, + "description": "\n Linkedin Profile URL of the person you want to\n extract work email address from.\n ", + "example": "https://sg.linkedin.com/in/williamhgates", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "callback_url", + "required": false, + "description": "\n Webhook to notify your application when\n the request has finished processing.\n ", + "example": "https://webhook.site/29e12f17-d5a2-400a-9d08-42ee9d83600a", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExtractionEmailResult" + }, + "example": { + "email_queue_count": 0 + } + } + }, + "description": "Work Email Address" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Work Email Lookup Endpoint" + }, + "summary": "Work Email Lookup Endpoint" + }, + "/api/linkedin/job": { + "get": { + "description": "Cost: 2 credits / successful request.\nGet structured data of a LinkedIn Job Profile", + "parameters": [ + { + "in": "query", + "name": "url", + "required": true, + "description": "\n URL of the LinkedIn Job Profile to target.\n\n URL should be in the format of\n `https://www.linkedin.com/jobs/view/`.\n [Jobs Listing Endpoint](#jobs-api-jobs-listing-endpoint)\n can be used to retrieve a job URL.\n ", + "example": "https://www.linkedin.com/jobs/view/3667167926/", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobProfile" + }, + "example": { + "linkedin_internal_id": "content-strategist-at-microsoft-3257696537", + "job_description": "The Global Demand Center (GDC) within the Cloud Marketing group is leading the marketing transformation of Microsoft’s largest and fastest growing commercial businesses. Our always-on integrated marketing programs work to nurture and acquire new customers across segments, targeting business and technical audiences across our commercial cloud portfolio, with programs available in 42 markets and 30 languages. The GDC team is modernizing and integrating these channels through advanced analytics, marketing automation, and digital marketing. We are on a mission to drive market share, consumption, and consistent double-digit+ revenue growth. Content is the fuel that drives the digitally connected customer journeys at the core of the GDC engine, and we’re looking for a skilled, self-motivated, data-driven content strategist to build the content that motivates customers to take action. The Content Strategist will develop and execute content strategies for the ever-critical security space. You will be accountable for understanding the business priorities, getting close to our target audiences, defining the content journeys that attract, nurture, inspire, and retain customers, and manage quality execution and delivery of the content. You will work closely with your counterparts, the integrated marketing strategists, to drive business outcomes. Your network will include product marketers, integrated marketers, relationship marketers, sales, engineering, and agency partners to develop and execute on your plan. Our team: The Lifecycle Programs team is a fast-paced digital marketing organization. We put a focus on getting things done, simplifying anything and everything, and having fun while doing it. We all believe in connecting with customers at scale, supporting them at each stage of the customer journey, from early awareness and consideration, through onboarding and post purchase engagement. You will be in the middle of it all helping to identify the right content that delivers what customers want—where they want it, when they want it, and how they want it. \n \n**_Responsibilities \n_**\n * Define content journeys for Security and IT professionals across industries.\n * Build the resulting content strategies designed to accelerate the customer through the lifecycle.\n * Create a content plan to address the insights in the customer journey and strategy, ensuring the content is aligned to what the customer needs at each stage.\n * Deliver the content through our internal Studio or with select agency partners.\n * Be a customer advocate. Relentlessly champion the customer and the experiences they have with the content you create—how they find it, how they consume it, how they use it to make decisions.\n * Leverage data and market insights for decision making including content optimization and new concept development. \n\n\n**_Qualifications \n \n_** **Required/Minimum Qualifications \n**\n * Bachelor's Degree in Business, Marketing, Communications, Economics, Public Relations, or related field AND 1+ year(s) integrated marketing (e.g., digital, relationship, social media, campaign), event management, marketing strategy, business planning, marketing operations, or related work experience\n * OR equivalent experience. \n\n\n**_Additional Or Preferred Qualifications \n_**\n * Bachelor's Degree in Business, Marketing, Communications, Economics, Public Relations, or related field AND 3+ years integrated marketing (e.g., digital, relationship, social media, campaign), event management, marketing strategy, business planning, marketing operations, or related work experience\n * OR equivalent experience.\n * Strong customer centric mindset and demonstrated ability to put the customer first.\n * Clear and persuasive communication skills, both written and verbal.\n * Experience with program performance tracking and communications.\n * Recognized as a self-starter with a bias for action.\n * Creative problem-solving skills, and a growth mindset approach\n * Experience managing across highly matrixed organizations, often with competing priorities.\n * A demonstrated track record of business impact through content\n * Well-versed in digital marketing best practices, including journey mapping.\n * Understanding of content disciplines, including SEO, content strategy, and execution.\n * Preferred, but not required: experience with commercial technology sales process \n\n\nNarrative \n \nIntegrated Marketing IC3 - The typical base pay range for this role across the U.S. is USD $80,900 - $162,200 per year. There is a different range applicable to specific work locations, within the San Francisco Bay area and New York City metropolitan area, and the base pay range for this role in those locations is USD $105,300 - $176,900 per year. \n \nMicrosoft has different base pay ranges for different work locations within the United States, which allows us to pay employees competitively and consistently in different geographic markets (see below). The range above reflects the potential base pay across the U.S. for this role (except as noted below); the applicable base pay range will depend on what ultimately is determined to be the candidate’s primary work location. Individual base pay depends on various factors, in addition to primary work location, such as complexity and responsibility of role, job duties/requirements, and relevant experience and skills. Base pay ranges are reviewed and typically updated each year. Offers are made within the base pay range applicable at the time. \n \nAt Microsoft certain roles are eligible for additional rewards, including merit increases, annual bonus and stock. These awards are allocated based on individual performance. In addition, certain roles also have the opportunity to earn sales incentives based on revenue or utilization, depending on the terms of the plan and the employee’s role. Benefits/perks listed here may vary depending on the nature of employment with Microsoft and the country work location. U.S.-based employees have access to healthcare benefits, a 401(k) plan and company match, short-term and long-term disability coverage, basic life insurance, wellbeing benefits, paid vacation time, paid sick and mental health time, and several paid holidays, among others. \n \nOur commitment to pay equity \n \nWe are committed to the principle of pay equity – paying employees equitably for substantially similar work. To learn more about pay equity and our other commitments to increase representation and strengthen our culture of inclusion, check out our annual Diversity & Inclusion Report. ( https://www.microsoft.com/en-us/diversity/inside-microsoft/annual-report ) \n \nUnderstanding roles at Microsoft \n \nThe top of this page displays the role for which the base pay ranges apply – Integrated Marketing IC3. The way we define roles includes two things: discipline (the type of work) and career stage (scope and complexity). The career stage has two parts – the first identifies whether the role is a manager (M), an individual contributor (IC), an admin-technician-retail (ATR) job, or an intern. The second part identifies the relative seniority of the role – a higher number (or later letter alphabetically in the case of ATR) indicates greater scope and complexity. \n \nMicrosoft is an equal opportunity employer. All qualified applicants will receive consideration for employment without regard to age, ancestry, color, family or medical care leave, gender identity or expression, genetic information, marital status, medical condition, national origin, physical or mental disability, political affiliation, protected veteran status, race, religion, sex (including pregnancy), sexual orientation, or any other characteristic protected by applicable laws, regulations and ordinances. We also consider qualified applicants regardless of criminal histories, consistent with legal requirements. If you need assistance and/or a reasonable accommodation due to a disability during the application or the recruiting process, please send a request via the Accommodation request form. \n \nThe salary for this role in the state of Colorado is between $108,200 and $162,200. \n \nAt Microsoft, certain roles are eligible for additional rewards, including annual bonus and stock. These awards are allocated based on individual performance. In addition, certain roles also have the opportunity to earn sales incentives based on revenue or utilization, depending on the terms of the plan and the employee’s role. Benefits/perks listed below may vary depending on the nature of your employment with Microsoft and the country where you work. \n", + "apply_url": "https://sg.linkedin.com/jobs/view/externalApply/3257696537?url=https%3A%2F%2Fcareers%2Emicrosoft%2Ecom%2Fus%2Fen%2Fjob%2F1451110%2FContent-Strategist%3Fjobsource%3Dlinkedin%26utm_source%3Dlinkedin%26utm_medium%3Dlinkedin%26utm_campaign%3Dlinkedin-feed&urlHash=I9BQ&trk=public_jobs_apply-link-offsite", + "title": "Content Strategist", + "location": { + "country": "United States", + "region": "Hawaii", + "city": null, + "postal_code": null, + "latitude": null, + "longitude": null, + "street": null + }, + "company": { + "name": "Microsoft", + "url": "https://www.linkedin.com/company/microsoft", + "logo": "https://media.licdn.com/dms/image/C560BAQE88xCsONDULQ/company-logo_100_100/0/1618231291419?e=2147483647&v=beta&t=rffql7GLHsSqWXKbdP2LJMMv7CMTqu7-Ms9d9tophKI" + }, + "seniority_level": "Mid-Senior level", + "industry": [ + "IT Services and IT Consulting, Computer Hardware Manufacturing, and Software Development" + ], + "employment_type": "Full-time", + "job_functions": [ + "Marketing" + ], + "total_applicants": 200 + } + } + }, + "description": "Detailed job data" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Jobs API" + ], + "operationId": "Job Profile Endpoint" + }, + "summary": "Job Profile Endpoint" + }, + "/api/followers": { + "get": { + "description": "Cost: 10 credits / result for users on an annual subscription or Enterprise plan.\nGet a list of individual followers of a company.", + "parameters": [ + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL of the company from which you want to get a list of followers of.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://www.linkedin.com/company/henry-schein", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL belonging to the company that you want to get a list of followers of.\n\n URL should be in the format of `https://x.com/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://x.com/henryschein", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Limit the maximum results of followers returned per API call.\n\n The default value of this parameter is 10.\n\n Accepted values for this parameter is an integer ranging from 0 to 1000.\n ", + "example": "10", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FollowerList" + }, + "example": { + "followers": [ + { + "linkedin_profile_url": "https://www.linkedin.com/in/agiliosoftware", + "twitter_profile_url": "https://www.x.com/agilio_software", + "email": null + }, + { + "linkedin_profile_url": "https://www.linkedin.com/in/air-techniques", + "twitter_profile_url": "https://www.x.com/airtechniques", + "email": null + } + ], + "next_page": null + } + } + }, + "description": "A list of individual followers of the company" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Customer API `EXPERIMENTAL`" + ], + "operationId": "Follower Listing Endpoint `EXPERIMENTAL`" + }, + "summary": "Follower Listing Endpoint `EXPERIMENTAL`" + }, + "/api/followers/count": { + "get": { + "description": "Cost: 1 credit / result for users on an annual subscription or Enterprise plan.\nGet the count of followers of a company.", + "parameters": [ + { + "in": "query", + "name": "linkedin_company_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL of the company from which you want to get a list of followers of.\n\n URL should be in the format of `https://www.linkedin.com/company/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://www.linkedin.com/company/henry-schein", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL belonging to the company that you want to get a list of followers of.\n\n URL should be in the format of `https://x.com/`\n \n\n Yes (Include only one of: `linkedin_company_profile_url` or `twitter_profile_url`)\n ", + "example": "https://x.com/henryschein", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FollowerListCount" + }, + "example": { + "follower_count": 74 + } + } + }, + "description": "Count individuals of that company's followers" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Customer API `EXPERIMENTAL`" + ], + "operationId": "Follower Listing Count Endpoint `EXPERIMENTAL`" + }, + "summary": "Follower Listing Count Endpoint `EXPERIMENTAL`" + }, + "/api/v2/search/company": { + "get": { + "description": "Cost: 3 credits / result returned.\nSearch for companies that meet a set of criteria within\n our exhaustive dataset of company profiles.\n\n This API endpoint is powered by [LinkDB](https://nubela.co/proxycurl/linkdb), our exhaustive dataset of company profiles.\n\n This API endpoint can return at most of 10,000 results per search.\n\n Each search expression for a parameter is limited to a maximum of 255 characters.", + "parameters": [ + { + "in": "query", + "name": "country", + "required": false, + "description": "\n Filter companies with an office based in this country.\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n ", + "example": "US", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "region", + "required": false, + "description": "\n Filter companies with an office based in this country.\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n ", + "example": "United States", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "city", + "required": false, + "description": "\n Filter companies based in cities matching the provided search expression.\n ", + "example": "new AND york", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "type", + "required": false, + "description": "\n Filter companies of the provided LinkedIn type.\n\n Possible values:\n\n * `EDUCATIONAL`: Educational Institution\n * `GOVERNMENT_AGENCY`: Government Agency\n * `NON_PROFIT` : Nonprofit\n * `PARTNERSHIP` : Partnership\n * `PRIVATELY_HELD` : Privately Held\n * `PUBLIC_COMPANY` : Public Company\n * `SELF_EMPLOYED` : Self-Employed\n * `SELF_OWNED` : Sole Proprietorship\n ", + "example": "PRIVATELY_HELD", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "follower_count_min", + "required": false, + "description": "\n Filter companies with a LinkedIn follower count **more than** this value.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "follower_count_max", + "required": false, + "description": "\n Filter companies with a LinkedIn follower count **less than** this value.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "name", + "required": false, + "description": "\n Filter companies with a name matching the provided search expression.\n ", + "example": "google OR apple", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "industry", + "required": false, + "description": "\n Filter companies belonging to an `industry` that matches the provided search expression. The `industry` attribute, found in a LinkedIn Company profile, describes the industry in which the company operates. The value of this attribute is an enumerator. [This CSV file provides an exhaustive list of possible values for this attribute](https://drive.google.com/file/d/12yvYLuru7CRv3wKOIkHs5Ldocz31gJSS/view?usp=share_link).\n ", + "example": "technology", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "employee_count_max", + "required": false, + "description": "\n Filter companies with **at most** this many employees.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "employee_count_min", + "required": false, + "description": "\n Filter companies with **at least** this many employees.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "description", + "required": false, + "description": "\n Filter companies with a description matching the provided search expression.\n ", + "example": "medical device", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "founded_after_year", + "required": false, + "description": "\n Filter companies founded **after** this year.\n ", + "example": "1999", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "founded_before_year", + "required": false, + "description": "\n Filter companies founded **before** this year.\n ", + "example": "1999", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "funding_amount_max", + "required": false, + "description": "\n Filter companies that have raised **at most** this much (USD) funding amount.\n ", + "example": "1000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "funding_amount_min", + "required": false, + "description": "\n Filter companies that have raised **at least** this much (USD) funding amount.\n ", + "example": "1000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "funding_raised_after", + "required": false, + "description": "\n Filter companies that have raised funding **after** this date.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "funding_raised_before", + "required": false, + "description": "\n Filter companies that have raised funding **before** this date.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "public_identifier_in_list", + "required": false, + "description": "\n A list of public identifiers (the identifying portion of the company’s profile URL).\n The target company’s identifier must be a member of this list.\n ", + "example": "stripe,amazon", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "public_identifier_not_in_list", + "required": false, + "description": "\n A list of public identifiers (the identifying portion of the company’s profile URL).\n The target company’s identifier must **not** be a member of this list.\n ", + "example": "stripe,amazon", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Tune the maximum results returned per API call.\n\n The default value of this parameter is 100.\n\n Accepted values for this parameter is an integer ranging from 1 to 100.\n\n When `enrich_profiles=enrich`, this parameter accepts value ranging from `1` to `10`.\n ", + "example": "10", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profiles", + "required": false, + "description": "\n Get the company's complete profile data rather than just the URLs to their LinkedIn profiles.\n\n Each request respond with a streaming response of profiles.\n\n The valid values are:\n\n - skip (default): lists company's profile url\n - enrich: include company's profile data in the list\n\n Calling this API endpoint with this parameter would add 1 credit per result returned.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompanySearchResult" + }, + "example": { + "results": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple/", + "profile": { + "linkedin_internal_id": "1441", + "description": "A problem isn't truly solved until it's solved for all. Googlers build products that help create opportunities for everyone, whether down the street or across the globe. Bring your insight, imagination and a healthy disregard for the impossible. Bring everything that makes you unique. Together, we can build for everyone.\n\nCheck out our career opportunities at careers.google.com.", + "website": "https://goo.gle/3m1IN7m", + "industry": "Software Development", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 319856, + "hq": { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "search", + "ads" + ], + "locations": [ + { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + { + "country": "US", + "city": "New York", + "postal_code": "10011", + "line_1": "111 8th Ave", + "is_hq": false, + "state": "NY" + } + ], + "name": "Google", + "tagline": null, + "universal_name_id": "google", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3500b39da8db1d2d8f5727a9ac39a7c4a88b4632ed68209dee12f06bc79aca", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abb7a4b87583cffda8db24d58d906c644998fae8cbb99e98c69a35720fcd0050", + "search_id": "1441", + "similar_companies": [ + { + "name": "Amazon", + "link": "https://www.linkedin.com/company/amazon", + "industry": "Software Development", + "location": "Seattle, WA" + }, + { + "name": "Microsoft", + "link": "https://www.linkedin.com/company/microsoft", + "industry": "Software Development", + "location": "Redmond, Washington" + } + ], + "affiliated_companies": [ + { + "name": "YouTube", + "link": "https://www.linkedin.com/company/youtube", + "industry": "Software Development", + "location": "San Bruno, CA" + }, + { + "name": "Google Cloud", + "link": "https://www.linkedin.com/showcase/google-cloud", + "industry": "Software Development", + "location": "Mountain View, California" + } + ], + "updates": [ + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C5605AQFthnjiTD6Mvg/videocover-high/0/1660754102856?e=2147483647&v=beta&t=PPOsA9J3vCTXWhuZclqSBQl7DLSDLvy5hKWlkHI85YE", + "posted_on": { + "day": 13, + "month": 9, + "year": 2022 + }, + "text": "Want to kick start your #LifeAtGoogle but not sure where to begin? Explore our Build Your Future site, where you can learn about developmental programs, learn tips for future interviews, sign up for informational events, and even hear real stories from Googlers who’ve been where you are now. Get started → https://bit.ly/3SKPzQB", + "total_likes": 4267 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C4D22AQGcvTlKRR3qvQ/feedshare-shrink_2048_1536/0/1672854668558?e=1676505600&v=beta&t=whRRx9ULPEuyw_FgUg4Z3N3O9iksyJW7ewCGZA6ujdg", + "posted_on": null, + "text": "Ariana, welcome to Google. Here’s to a year full of growth, learning, and experiences at #LifeAtGoogle! 🎉", + "total_likes": 397 + } + ], + "follower_count": 27472792 + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null, + "total_result_count": 1 + } + } + }, + "description": "List of companies" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Search API" + ], + "operationId": "Company Search Endpoint" + }, + "summary": "Company Search Endpoint" + }, + "/api/v2/search/person/": { + "get": { + "description": "Cost: 3 credits / result returned.\nSearch for people who meet a set of criteria within our exhaustive dataset of people profiles.\n\nThis API endpoint is powered by [LinkDB](https://nubela.co/proxycurl/linkdb), our exhaustive dataset of people and company profiles.\n\nThis API endpoint can return at most 10,000 results per search.\n\nEach search expression for a parameter is limited to a maximum of 255 characters.", + "parameters": [ + { + "in": "query", + "name": "country", + "required": true, + "description": "\n Filter people located in this country.\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n ", + "example": "US", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "first_name", + "required": false, + "description": "\n Filter people whose first names match the provided search expression.\n ", + "example": "Sarah", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "last_name", + "required": false, + "description": "\n Filter people whose last names match the provided search expression.\n ", + "example": "Jackson OR Johnson", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "education_field_of_study", + "required": false, + "description": "\n Filter people with a field of study matching the provided search expression, based on education history.\n ", + "example": "computer science", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "education_degree_name", + "required": false, + "description": "\n Filter people who earned a degree matching the provided search expression, based on education history.\n ", + "example": "MBA", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "education_school_name", + "required": false, + "description": "\n Filter people who have attended a school whose name matches the provided search expression, based on education history.\n ", + "example": "Caltech OR Massachusetts Institute of Technology", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "education_school_linkedin_profile_url", + "required": false, + "description": "\n Filter people who have attended a school with a specific LinkedIn profile URL, based on education history.\n ", + "example": "https://www.linkedin.com/school/national-university-of-singapore/", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_role_title", + "required": false, + "description": "\n Filter people who are **currently** working as a role whose title matches the provided search expression. You'll be looking for profiles on [LinkDB](https://nubela.co/proxycurl/linkdb) that show a person's current job. However, keep in mind that some of these profiles may not be up-to-date, which means you might sometimes see a person's old job instead of their current job on LinkedIn.\n ", + "example": "founder", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "past_role_title", + "required": false, + "description": "\n Filter people who have **in the past** worked as a role whose title matches the provided search expression.\n ", + "example": "founder", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_role_before", + "required": false, + "description": "\n Filter people who started their current role **before** this date. You'll be looking for profiles on [LinkDB](https://nubela.co/proxycurl/linkdb) that show a person's current job. However, keep in mind that some of these profiles may not be up-to-date, which means you might sometimes see a person's old job instead of their current job on LinkedIn.\n\n This parameter takes a ISO8601 date. Default value of this parameter is `null`.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_role_after", + "required": false, + "description": "\n Filter people who started their current role **after** this date. You'll be looking for profiles on [LinkDB](https://nubela.co/proxycurl/linkdb) that show a person's current job. However, keep in mind that some of these profiles may not be up-to-date, which means you might sometimes see a person's old job instead of their current job on LinkedIn.\n\n This parameter takes a ISO8601 date. Default value of this parameter is `null`.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_linkedin_profile_url", + "required": false, + "description": "\n Filter people who are **currently** working at a company represented by this LinkedIn Company Profile URL.\n\n Default value of this parameter is `null`.\n ", + "example": "https://www.linkedin.com/company/apple", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "past_company_linkedin_profile_url", + "required": false, + "description": "\n Filter people who have **in the past** worked at the company represented by this LinkedIn Company Profile URL.\n\n This parameter takes a LinkedIn Company Profile URL. Default value of this parameter is `null`.\n ", + "example": "https://www.linkedin.com/company/apple", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_job_description", + "required": false, + "description": "\n Filter people with **current** job descriptions matching the provided search expression.\n ", + "example": "education", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "past_job_description", + "required": false, + "description": "\n Filter people with **past** job descriptions matching the provided search expression.\n ", + "example": "education", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_name", + "required": false, + "description": "\n Filter people who are **currently** working at a company whose name matches the provided search expression.\n ", + "example": "Stripe OR Apple", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "past_company_name", + "required": false, + "description": "\n Filter people who **have previously** worked at a company whose name matches the provided search expression.\n ", + "example": "Stripe OR Apple", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_groups", + "required": false, + "description": "\n Filter people who are members of LinkedIn groups whose names match the provided search expression.\n ", + "example": "haskell", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "languages", + "required": false, + "description": "\n Filter people who list a language matching the provided search expression.\n ", + "example": "Mandarin OR Chinese", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "region", + "required": false, + "description": "\n Filter people located in a region matching the provided search expression.\n A “region” in this context means “state,” “province,” or similar political division, depending on what country you’re querying.\n ", + "example": "California", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "city", + "required": false, + "description": "\n Filter people located in a city matching the provided search expression.\n ", + "example": "Seattle OR Los Angeles", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "headline", + "required": false, + "description": "\n Filter people whose LinkedIn headline fields match the provided search expression.\n ", + "example": "founder", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "summary", + "required": false, + "description": "\n Filter people whose LinkedIn summary fields match the provided search expression.\n ", + "example": "founder", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "industries", + "required": false, + "description": "\n Person's inferred industry. May sometimes exist when `current_company_industry` does not, but `current_company_industry` should be preferred when it exists.\n ", + "example": "automotive", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "interests", + "required": false, + "description": "\n Filter people whose Linkedin interest fields match the provided search expression.\n ", + "example": "technology", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "skills", + "required": false, + "description": "\n Filter people whose Linkedin skill fields match the provided search expression.\n ", + "example": "accounting", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_country", + "required": false, + "description": "\n Filter people who are currently working at a company with an office based in this country.\n\n This parameter accepts a case-insensitive [Alpha-2 ISO3166 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).\n ", + "example": "us", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_region", + "required": false, + "description": "\n Filter people who are currently working at a company based in a region matching the provided search expression.\n ", + "example": "United States", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_city", + "required": false, + "description": "\n Filter people who are currently working at a company based in a city matching the provided search expression.\n ", + "example": "Seattle OR Los Angeles", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_type", + "required": false, + "description": "\n Filter people who are currently working at a company of the provided LinkedIn type.\n\n Possible values:\n\n * `EDUCATIONAL`: Educational Institution\n * `GOVERNMENT_AGENCY`: Government Agency\n * `NON_PROFIT` : Nonprofit\n * `PARTNERSHIP` : Partnership\n * `PRIVATELY_HELD` : Privately Held\n * `PUBLIC_COMPANY` : Public Company\n * `SELF_EMPLOYED` : Self-Employed\n * `SELF_OWNED` : Sole Proprietorship\n ", + "example": "NON_PROFIT", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_follower_count_min", + "required": false, + "description": "\n Filter people who are currently working at a company with a LinkedIn follower count **more than** this value.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_follower_count_max", + "required": false, + "description": "\n Filter people who are currently working at a company with a LinkedIn follower count **less than** this value.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_industry", + "required": false, + "description": "\n Filter people who are currently working at a company belonging to an `industry` that matches the provided search expression. The `industry` attribute, found in a LinkedIn Company profile, describes the industry in which the company operates. The value of this attribute is an enumerator. [This CSV file provides an exhaustive list of possible values for this attribute](https://drive.google.com/file/d/12yvYLuru7CRv3wKOIkHs5Ldocz31gJSS/view?usp=share_link).\n ", + "example": "higher AND education", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_employee_count_min", + "required": false, + "description": "\n Filter people who are currently working at a company with **at least** this many employees.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_employee_count_max", + "required": false, + "description": "\n Filter people who are currently working at a company with **at most** this many employees.\n ", + "example": "1000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_description", + "required": false, + "description": "\n Filter people who are currently working at a company with a description matching the provided search expression.\n ", + "example": "medical device", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_founded_after_year", + "required": false, + "description": "\n Filter people who are currently working at a company that was founded **after** this year.\n ", + "example": "1999", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_founded_before_year", + "required": false, + "description": "\n Filter people who are currently working at a company that was founded **before** this year.\n ", + "example": "1999", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_funding_amount_min", + "required": false, + "description": "\n Filter people who are currently working at a company that has raised **at least** this much (USD) funding amount.\n ", + "example": "1000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_funding_amount_max", + "required": false, + "description": "\n Filter people who are currently working at a company that has raised **at most** this much (USD) funding amount.\n ", + "example": "1000000", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_funding_raised_after", + "required": false, + "description": "\n Filter people who are currently working at a company that has raised funding **after** this date.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "current_company_funding_raised_before", + "required": false, + "description": "\n Filter people who are currently working at a company that has raised funding **before** this date.\n ", + "example": "2019-12-30", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "public_identifier_in_list", + "required": false, + "description": "\n A list of public identifiers (the identifying portion of the person’s profile URL).\n The target person’s identifier must be a member of this list.\n ", + "example": "williamhgates,johnrmarty", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "public_identifier_not_in_list", + "required": false, + "description": "\n A list of public identifiers (the identifying portion of the person’s profile URL).\n The target person’s identifier must **not** be a member of this list.\n ", + "example": "williamhgates,johnrmarty", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n Tune the maximum results returned per API call.\n\n The default value of this parameter is `100`.\n\n Accepted values for this parameter is an integer ranging from `1` to `100`.\n\n When `enrich_profiles=enrich`, this parameter accepts value ranging from `1` to `10`.\n ", + "example": "10", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "enrich_profiles", + "required": false, + "description": "\n Get the person's complete profile data rather than just the URLs to their LinkedIn profiles.\n\n Each request respond with a streaming response of profiles.\n\n The valid values are:\n\n * `skip` (default): lists person's profile url only\n * `enrich`: include person's profile data in the list\n\n Calling this API endpoint with this parameter would add `1` credit per result returned.\n ", + "example": "enrich", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PersonSearchResult" + }, + "example": { + "results": [ + { + "linkedin_profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [], + "accomplishment_publications": [], + "accomplishment_honors_awards": [], + "accomplishment_patents": [], + "accomplishment_courses": [], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [], + "volunteer_work": [], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [], + "groups": [] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null, + "total_result_count": 1 + } + } + }, + "description": "LinkedIn (Person) Profile URL" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Search API" + ], + "operationId": "Person Search Endpoint" + }, + "summary": "Person Search Endpoint" + }, + "/api/credit-balance": { + "get": { + "description": "Cost: 0 credit / successful request.\nGet your current credit(s) balance", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreditBalance" + }, + "example": { + "credit_balance": 100000 + } + } + }, + "description": "Balance of credits" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Meta API" + ], + "operationId": "View Credit Balance Endpoint" + }, + "summary": "View Credit Balance Endpoint" + }, + "/api/disposable-email": { + "get": { + "description": "Cost: 0 credit / successful request.\nGiven an email address, checks if the email address belongs to a disposable email service.", + "parameters": [ + { + "in": "query", + "name": "email", + "required": true, + "description": "Email address to check", + "example": "steven@nubela.co", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DisposableEmail" + }, + "example": { + "is_disposable_email": false, + "is_free_email": false + } + } + }, + "description": "Disposable Email Check" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Disposable Email Address Check Endpoint" + }, + "summary": "Disposable Email Address Check Endpoint" + }, + "/api/contact-api/personal-contact": { + "get": { + "description": "Cost: 1 credit / contact number returned.\nFind personal phone numbers associated with a given social media profile.", + "parameters": [ + { + "in": "query", + "name": "page_size", + "required": false, + "description": "\n This controls the maximum number of numbers returned per API call.\n It's useful for limiting credit consumption as the number of numbers\n per identity can vary. The default value is 0, meaning there's no limit\n to the number of returned results.\n ", + "example": "0", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "\n The Twitter/X Profile URL from which you wish to extract personal\n contact numbers\n \n\n Yes (Include only one of: `linkedin_profile_url`,\n `twitter_profile_url`, or `facebook_profile_url`)\n ", + "example": "https://x.com/proxycurl", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "facebook_profile_url", + "required": false, + "description": "\n The Facebook Profile URL from which you wish to extract personal\n contact numbers\n \n\n Yes (Include only one of: `linkedin_profile_url`,\n `twitter_profile_url`, or `facebook_profile_url`)\n ", + "example": "https://www.facebook.com/zuck", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_profile_url", + "required": false, + "description": "\n The LinkedIn Profile URL from which you wish to extract personal\n contact numbers\n \n\n Yes (Include only one of: `linkedin_profile_url`,\n `twitter_profile_url`, or `facebook_profile_url`)\n ", + "example": "https://linkedin.com/in/steven-goh-6738131b", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PersonalContactNumbers" + }, + "example": { + "numbers": [ + "+1123123123" + ] + } + } + }, + "description": "List of Personal Contact Numbers" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Personal Contact Number Lookup Endpoint" + }, + "summary": "Personal Contact Number Lookup Endpoint" + }, + "/api/contact-api/personal-email": { + "get": { + "description": "Cost: 1 credit / email returned.\nFind personal email addresses associated with a given social media profile.", + "parameters": [ + { + "in": "query", + "name": "email_validation", + "required": false, + "description": "\n How to validate each email.\n \n Takes the following values:\n * `none` (default) - Do not perform email validation.\n * `fast` - Perform fast email validation (does not cost extra credit).\n * `precise` - Perform deliverability validation (costs 1 extra credit per email found).\n\n For backward-compatibility these are also accepted:\n * `include` - Equivalent to `precise`\n * `exclude` - Equivalent to `none`\n ", + "example": "include", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page_size", + "required": false, + "description": "This controls the maximum number of emails returned per API call. It's useful for limiting credit consumption as the number of emails per identity can vary. The default value is `0`, meaning there's no limit to the number of returned results.", + "example": 0, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "twitter_profile_url", + "required": false, + "description": "The Twitter/X Profile URL from which you wish to extract personal email addresses.\nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://x.com/proxycurl", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "facebook_profile_url", + "required": false, + "description": "The Facebook Profile URL from which you wish to extract personal email addresses.\nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://www.facebook.com/zuck", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "linkedin_profile_url", + "required": false, + "description": "The LinkedIn Profile URL from which you wish to extract personal email addresses.\nyes (Include only one of: `linkedin_profile_url`, `twitter_profile_url`, or `facebook_profile_url`)", + "example": "https://linkedin.com/in/steven-goh-6738131b", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PDLEmailResult" + }, + "example": { + "emails": [ + "random@gmail.com", + "random2@yahoo.com" + ], + "invalid_emails": [ + "random3@gmail.com" + ] + } + } + }, + "description": "List of Personal Emails" + }, + "400": { + "description": "Invalid parameters provided. Refer to the documentation and message body for more info" + }, + "401": { + "description": "Invalid API key" + }, + "403": { + "description": "You have run out of credits" + }, + "404": { + "description": "The requested resource (e.g: user profile, company) could not be found" + }, + "429": { + "description": "Rate limited. Please retry" + }, + "500": { + "description": "Internal Server Error" + }, + "503": { + "description": "Enrichment failed, please retry." + } + }, + "tags": [ + "Contact API" + ], + "operationId": "Personal Email Lookup Endpoint" + }, + "summary": "Personal Email Lookup Endpoint" + } + }, + "info": { + "title": "Proxycurl API", + "version": "1.0.0" + }, + "openapi": "3.0.0", + "components": { + "schemas": { + "CompanyLocation": { + "type": "object", + "properties": { + "country": { + "type": "string", + "nullable": true + }, + "city": { + "type": "string", + "nullable": true + }, + "postal_code": { + "type": "string", + "nullable": true + }, + "line_1": { + "type": "string", + "nullable": true + }, + "is_hq": { + "type": "boolean" + }, + "state": { + "type": "string", + "nullable": true + } + }, + "example": { + "country": "SG", + "city": "Singapore", + "postal_code": "119077", + "line_1": "21 Lower Kent Ridge Road, Singapore", + "is_hq": true, + "state": null + } + }, + "CompanyType": { + "type": "string", + "enum": [ + "EDUCATIONAL", + "GOVERNMENT_AGENCY", + "NON_PROFIT", + "PARTNERSHIP", + "PRIVATELY_HELD", + "PUBLIC_COMPANY", + "SELF_EMPLOYED", + "SELF_OWNED" + ] + }, + "SimilarCompany": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "link": { + "type": "string", + "nullable": true + }, + "industry": { + "type": "string", + "nullable": true + }, + "location": { + "type": "string", + "nullable": true + } + }, + "example": { + "name": "NUS Business School", + "link": "https://www.linkedin.com/school/nus-business-school/", + "industry": "Higher Education", + "location": null + } + }, + "AffiliatedCompany": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "link": { + "type": "string", + "nullable": true + }, + "industry": { + "type": "string", + "nullable": true + }, + "location": { + "type": "string", + "nullable": true + } + }, + "example": { + "name": "LinkedIn", + "link": "https://www.linkedin.com/company/linkedin", + "industry": "Internet", + "location": "Sunnyvale, California" + } + }, + "Date": { + "type": "object", + "properties": { + "day": { + "type": "integer", + "nullable": true + }, + "month": { + "type": "integer", + "nullable": true + }, + "year": { + "type": "integer" + } + }, + "example": { + "day": 30, + "month": 9, + "year": 2021 + } + }, + "CompanyUpdate": { + "type": "object", + "properties": { + "article_link": { + "type": "string", + "nullable": true, + "description": "The URL for which the post links out to" + }, + "image": { + "type": "string", + "nullable": true, + "description": "The URL to the image to the post (if it exists)" + }, + "posted_on": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "text": { + "type": "string", + "nullable": true, + "description": "The body of the update" + }, + "total_likes": { + "type": "integer", + "nullable": true, + "description": "The total likes a post has received" + } + }, + "example": { + "article_link": "https://lnkd.in/gr7cb5by", + "image": "https://media-exp1.licdn.com/dms/image/C5622AQEGh8idEAm14Q/feedshare-shrink_800/0/1633089889886?e=1637798400&v=beta&t=LtGtAUSJNrPYdHpVhTBLhGTWYqrHtFJ86PKSmTpou7c", + "posted_on": { + "day": 30, + "month": 9, + "year": 2021 + }, + "text": "Introducing Personal Email Lookup API https://lnkd.in/gr7cb5by", + "total_likes": 3 + } + }, + "LinkedinSchool": { + "type": "object", + "properties": { + "linkedin_internal_id": { + "type": "string", + "description": "\n LinkedIn's Internal and immutable ID of this Company profile.\n " + }, + "description": { + "type": "string", + "nullable": true, + "description": "A textual description of the company." + }, + "website": { + "type": "string", + "nullable": true, + "description": "The URL of the company's website." + }, + "industry": { + "type": "string", + "nullable": true, + "description": "The `industry` attribute, found in a LinkedIn Company profile, describes the industry in which the company operates. The value of this attribute is an enumerator. [This CSV file provides an exhaustive list of possible values for this attribute] (https://drive.google.com/file/d/12yvYLuru7CRv3wKOIkHs5Ldocz31gJSS/view?usp=share_link)." + }, + "company_size": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer", + "nullable": true + }, + { + "type": "integer", + "nullable": true + } + ] + }, + "minItems": 2, + "maxItems": 2, + "description": "Sequenceed range of company head count" + }, + "company_size_on_linkedin": { + "type": "integer", + "nullable": true, + "description": "The size of the company as indicated on LinkedIn." + }, + "hq": { + "$ref": "#/components/schemas/CompanyLocation", + "nullable": true + }, + "company_type": { + "$ref": "#/components/schemas/CompanyType", + "nullable": true, + "description": "Possible values:\n\n `EDUCATIONAL`: Educational Institution\n\n `GOVERNMENT_AGENCY`: Government Agency\n\n `NON_PROFIT` : Nonprofit\n\n `PARTNERSHIP` : Partnership\n\n `PRIVATELY_HELD`: Privately Held\n\n `PUBLIC_COMPANY`: Public Company\n\n `SELF_EMPLOYED`: Self-Employed\n\n `SELF_OWNED`: Sole Proprietorship" + }, + "founded_year": { + "type": "integer", + "nullable": true, + "description": "The year the company was founded." + }, + "specialities": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of specialities.\n " + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompanyLocation" + } + }, + "name": { + "type": "string", + "nullable": true, + "description": "The name of the company." + }, + "tagline": { + "type": "string", + "nullable": true, + "description": "A short, catchy phrase that represents the company's mission or brand." + }, + "universal_name_id": { + "type": "string", + "nullable": true, + "description": "A unique numerical identifier for the company used in the LinkedIn platform." + }, + "profile_pic_url": { + "type": "string", + "nullable": true, + "description": "The URL of the company's profile picture." + }, + "background_cover_image_url": { + "type": "string", + "nullable": true, + "description": "The URL of the company's background cover image." + }, + "search_id": { + "type": "string", + "description": "\n Useable with [Job listing endpoint](#jobs-api-jobs-listing-endpoint)\n " + }, + "similar_companies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimilarCompany" + } + }, + "affiliated_companies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AffiliatedCompany" + } + }, + "updates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompanyUpdate" + }, + "description": "A list of post updates made by the company. This field is not guaranteed to be returned. Do not rely on this attribute in production." + }, + "follower_count": { + "type": "integer", + "nullable": true, + "description": "The number of followers the company has on LinkedIn." + } + }, + "example": { + "linkedin_internal_id": "5524", + "description": "At NUS, we are shaping the future through our people and our pursuit of new frontiers in knowledge. In a single century, we have become a university of global influence and an Asian thought leader. Our location at the crossroads of Asia informs our mission and gives us a tremendous vantage point to help create opportunities and address the pressing issues facing Singapore, Asia and the world.\r\rAt NUS, we believe in education, research and service that change lives.", + "website": "http://nus.edu.sg", + "industry": "Higher Education", + "company_size": [ + 5001, + 10000 + ], + "company_size_on_linkedin": 16084, + "hq": { + "country": "SG", + "city": "Singapore", + "postal_code": "119077", + "line_1": "21 Lower Kent Ridge Road, Singapore", + "is_hq": true, + "state": null + }, + "company_type": "EDUCATIONAL_INSTITUTION", + "founded_year": 1905, + "specialities": [ + "education", + "research" + ], + "locations": [ + { + "country": "SG", + "city": "Singapore", + "postal_code": "119077", + "line_1": "21 Lower Kent Ridge Road, Singapore", + "is_hq": true, + "state": null + } + ], + "name": "National University of Singapore", + "tagline": "Think Different - But Not Too Different", + "universal_name_id": "national-university-of-singapore", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/national-university-of-singapore/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T071304Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=a66e032f168972bef4ea3821705194ea1c144415a1655bdb328f961ed30e2a24", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/national-university-of-singapore/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T071304Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=551f456b6156e4610bc3e7be43e2f9b0e4b071db5f41f56cc0e408fc1b5a1140", + "search_id": "5524", + "similar_companies": [ + { + "name": "NUS Business School", + "link": "https://www.linkedin.com/school/nus-business-school/", + "industry": "Higher Education", + "location": null + }, + { + "name": "NUS Faculty of Arts and Social Sciences", + "link": "https://www.linkedin.com/school/nusfass/", + "industry": "Higher Education", + "location": null + } + ], + "affiliated_companies": [ + { + "name": "LinkedIn", + "link": "https://www.linkedin.com/company/linkedin", + "industry": "Internet", + "location": "Sunnyvale, California" + } + ], + "updates": [ + { + "article_link": "https://lnkd.in/gr7cb5by", + "image": "https://media-exp1.licdn.com/dms/image/C5622AQEGh8idEAm14Q/feedshare-shrink_800/0/1633089889886?e=1637798400&v=beta&t=LtGtAUSJNrPYdHpVhTBLhGTWYqrHtFJ86PKSmTpou7c", + "posted_on": { + "day": 30, + "month": 9, + "year": 2021 + }, + "text": "Introducing Personal Email Lookup API https://lnkd.in/gr7cb5by", + "total_likes": 3 + } + ], + "follower_count": 539321 + } + }, + "AcquiredCompany": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "\n LinkedIn Company Profile URL of company that was involved\n " + }, + "crunchbase_profile_url": { + "type": "string", + "nullable": true, + "description": "Crunchbase Profile URL of company that was involved" + }, + "announced_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date by which this event was announced" + }, + "price": { + "type": "integer", + "nullable": true, + "description": "Price of acquisition" + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + }, + "Acquisitor": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "\n LinkedIn Company Profile URL of company that was involved\n " + }, + "crunchbase_profile_url": { + "type": "string", + "nullable": true, + "description": "Crunchbase Profile URL of company that was involved" + }, + "announced_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date by which this event was announced" + }, + "price": { + "type": "integer", + "nullable": true, + "description": "Price of acquisition" + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + }, + "Acquisition": { + "type": "object", + "properties": { + "acquired": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AcquiredCompany" + } + }, + "acquired_by": { + "$ref": "#/components/schemas/Acquisitor", + "nullable": true + } + }, + "example": { + "acquired": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + ], + "acquired_by": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + } + }, + "Exit": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "LinkedIn Profile URL of the company that has exited" + }, + "crunchbase_profile_url": { + "type": "string", + "nullable": true, + "description": "Crunchbase Profile URL of the company that has exited" + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of the company" + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/company/motiondsp", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/motiondsp", + "name": "MotionDSP" + } + }, + "CompanyDetails": { + "type": "object", + "properties": { + "crunchbase_profile_url": { + "type": "string", + "nullable": true, + "description": "Crunchbase Profile URL of the company" + }, + "ipo_status": { + "type": "string", + "nullable": true, + "description": "IPO status of the company" + }, + "crunchbase_rank": { + "type": "integer", + "nullable": true, + "description": "A measure of prominence of this company by Crunchbase" + }, + "founding_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date of founding" + }, + "operating_status": { + "type": "string", + "nullable": true, + "description": "Status of the company's operational status" + }, + "company_type": { + "type": "string", + "nullable": true, + "description": "Type of company" + }, + "contact_email": { + "type": "string", + "nullable": true, + "description": "General contact email of the company" + }, + "phone_number": { + "type": "string", + "nullable": true, + "description": "General contact number of the company" + }, + "facebook_id": { + "type": "string", + "nullable": true, + "description": "ID of the company's official Facebook account" + }, + "twitter_id": { + "type": "string", + "nullable": true, + "description": "ID of the company's official Twitter account" + }, + "number_of_funding_rounds": { + "type": "integer", + "nullable": true, + "description": "Total rounds of funding that this company has raised" + }, + "total_funding_amount": { + "type": "integer", + "nullable": true, + "description": "Total venture capital raised by this company" + }, + "stock_symbol": { + "type": "string", + "nullable": true, + "description": "Stock symbol of this public company" + }, + "ipo_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "The date by which this public company went public" + }, + "number_of_lead_investors": { + "type": "integer", + "nullable": true, + "description": "Total lead investors" + }, + "number_of_investors": { + "type": "integer", + "nullable": true, + "description": "Total investors" + }, + "total_fund_raised": { + "type": "integer", + "nullable": true, + "description": "\n The total amount of funds raised (by this VC firm) to be deployed as\n subsidiary investments (applicable only for VC firms)\n " + }, + "number_of_investments": { + "type": "integer", + "nullable": true, + "description": "\n Total investments made by this VC firm (applicable only for VC firms)\n " + }, + "number_of_lead_investments": { + "type": "integer", + "nullable": true, + "description": "\n Total investments that was led by this VC firm\n (applicable only for VC firms)\n " + }, + "number_of_exits": { + "type": "integer", + "nullable": true, + "description": "Total exits by this VC (applicable only for VC firms)" + }, + "number_of_acquisitions": { + "type": "integer", + "nullable": true, + "description": "Total companies acquired by this company" + } + }, + "example": { + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "ipo_status": "Public", + "crunchbase_rank": 13, + "founding_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "operating_status": "Active", + "company_type": "For Profit", + "contact_email": "info@nvidia.com", + "phone_number": "(140) 848-6200", + "facebook_id": "NVIDIA.IN", + "twitter_id": "nvidia", + "number_of_funding_rounds": 3, + "total_funding_amount": 4000000, + "stock_symbol": "NASDAQ:NVDA", + "ipo_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "number_of_lead_investors": 3, + "number_of_investors": 4, + "total_fund_raised": 1000, + "number_of_investments": 50, + "number_of_lead_investments": 3, + "number_of_exits": 7, + "number_of_acquisitions": 2 + } + }, + "Investor": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "LinkedIn Profile URL of investor" + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of investor" + }, + "type": { + "type": "string", + "nullable": true, + "description": "Type of investor" + } + }, + "example": { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + }, + "Funding": { + "type": "object", + "properties": { + "funding_type": { + "type": "string", + "nullable": true, + "description": "Type of funding" + }, + "money_raised": { + "type": "integer", + "nullable": true, + "description": "Amount of money raised" + }, + "announced_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date of announcement" + }, + "number_of_investor": { + "type": "integer", + "nullable": true, + "description": "Number of investors in this round" + }, + "investor_list": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Investor" + }, + "nullable": true + } + }, + "example": { + "funding_type": "Grant", + "money_raised": 25000000, + "announced_date": { + "day": 1, + "month": 1, + "year": 2001 + }, + "number_of_investor": 1, + "investor_list": [ + { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + ] + } + }, + "LinkedinCompany": { + "type": "object", + "properties": { + "linkedin_internal_id": { + "type": "string", + "description": "\n LinkedIn's Internal and immutable ID of this Company profile.\n " + }, + "description": { + "type": "string", + "nullable": true, + "description": "A textual description of the company." + }, + "website": { + "type": "string", + "nullable": true, + "description": "The URL of the company's website." + }, + "industry": { + "type": "string", + "nullable": true, + "description": "The `industry` attribute, found in a LinkedIn Company profile, describes the industry in which the company operates. The value of this attribute is an enumerator. [This CSV file provides an exhaustive list of possible values for this attribute] (https://drive.google.com/file/d/12yvYLuru7CRv3wKOIkHs5Ldocz31gJSS/view?usp=share_link)." + }, + "company_size": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer", + "nullable": true + }, + { + "type": "integer", + "nullable": true + } + ] + }, + "minItems": 2, + "maxItems": 2, + "description": "Sequenceed range of company head count" + }, + "company_size_on_linkedin": { + "type": "integer", + "nullable": true, + "description": "The size of the company as indicated on LinkedIn." + }, + "hq": { + "$ref": "#/components/schemas/CompanyLocation", + "nullable": true + }, + "company_type": { + "$ref": "#/components/schemas/CompanyType", + "nullable": true, + "description": "Possible values:\n\n `EDUCATIONAL`: Educational Institution\n\n `GOVERNMENT_AGENCY`: Government Agency\n\n `NON_PROFIT` : Nonprofit\n\n `PARTNERSHIP` : Partnership\n\n `PRIVATELY_HELD`: Privately Held\n\n `PUBLIC_COMPANY`: Public Company\n\n `SELF_EMPLOYED`: Self-Employed\n\n `SELF_OWNED`: Sole Proprietorship" + }, + "founded_year": { + "type": "integer", + "nullable": true, + "description": "The year the company was founded." + }, + "specialities": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of specialities.\n " + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompanyLocation" + } + }, + "name": { + "type": "string", + "nullable": true, + "description": "The name of the company." + }, + "tagline": { + "type": "string", + "nullable": true, + "description": "A short, catchy phrase that represents the company's mission or brand." + }, + "universal_name_id": { + "type": "string", + "nullable": true, + "description": "A unique numerical identifier for the company used in the LinkedIn platform." + }, + "profile_pic_url": { + "type": "string", + "nullable": true, + "description": "The URL of the company's profile picture." + }, + "background_cover_image_url": { + "type": "string", + "nullable": true, + "description": "The URL of the company's background cover image." + }, + "search_id": { + "type": "string", + "description": "\n Useable with [Job listing endpoint](#jobs-api-jobs-listing-endpoint)\n " + }, + "similar_companies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimilarCompany" + } + }, + "affiliated_companies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AffiliatedCompany" + } + }, + "updates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompanyUpdate" + }, + "description": "A list of post updates made by the company. This field is not guaranteed to be returned. Do not rely on this attribute in production." + }, + "follower_count": { + "type": "integer", + "nullable": true, + "description": "The number of followers the company has on LinkedIn." + }, + "acquisitions": { + "$ref": "#/components/schemas/Acquisition", + "nullable": true + }, + "exit_data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Exit" + }, + "nullable": true + }, + "extra": { + "$ref": "#/components/schemas/CompanyDetails", + "nullable": true, + "description": "Company extra when `extra=include`" + }, + "funding_data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Funding" + }, + "description": "Company Funding data when `funding_data=include`" + }, + "categories": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "The `categories` attribute is fetched from the company's Crunchbase profile. Values for this attribute are free-form text, and there is no exhaustive list of categories. Consider the categories attribute as \"hints\" regarding the products or services offered by the company." + }, + "customer_list": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "example": { + "linkedin_internal_id": "1441", + "description": "A problem isn't truly solved until it's solved for all. Googlers build products that help create opportunities for everyone, whether down the street or across the globe. Bring your insight, imagination and a healthy disregard for the impossible. Bring everything that makes you unique. Together, we can build for everyone.\n\nCheck out our career opportunities at careers.google.com.", + "website": "https://goo.gle/3m1IN7m", + "industry": "Software Development", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 319856, + "hq": { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "search", + "ads" + ], + "locations": [ + { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + { + "country": "US", + "city": "New York", + "postal_code": "10011", + "line_1": "111 8th Ave", + "is_hq": null, + "state": "NY" + } + ], + "name": "Google", + "tagline": "Think Different - But Not Too Different", + "universal_name_id": "google", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3500b39da8db1d2d8f5727a9ac39a7c4a88b4632ed68209dee12f06bc79aca", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abb7a4b87583cffda8db24d58d906c644998fae8cbb99e98c69a35720fcd0050", + "search_id": "1441", + "similar_companies": [ + { + "name": "Amazon", + "link": "https://www.linkedin.com/company/amazon", + "industry": "Software Development", + "location": "Seattle, WA" + }, + { + "name": "Microsoft", + "link": "https://www.linkedin.com/company/microsoft", + "industry": "Software Development", + "location": "Redmond, Washington" + } + ], + "affiliated_companies": [ + { + "name": "YouTube", + "link": "https://www.linkedin.com/company/youtube", + "industry": "Software Development", + "location": "San Bruno, CA" + }, + { + "name": "Google Cloud", + "link": "https://www.linkedin.com/showcase/google-cloud", + "industry": "Software Development", + "location": "Mountain View, California" + } + ], + "updates": [ + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C5605AQFthnjiTD6Mvg/videocover-high/0/1660754102856?e=2147483647&v=beta&t=PPOsA9J3vCTXWhuZclqSBQl7DLSDLvy5hKWlkHI85YE", + "posted_on": { + "day": 13, + "month": 9, + "year": 2022 + }, + "text": "Want to kick start your #LifeAtGoogle but not sure where to begin? Explore our Build Your Future site, where you can learn about developmental programs, learn tips for future interviews, sign up for informational events, and even hear real stories from Googlers who’ve been where you are now. Get started → https://bit.ly/3SKPzQB", + "total_likes": 4267 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C4D22AQGcvTlKRR3qvQ/feedshare-shrink_2048_1536/0/1672854668558?e=1676505600&v=beta&t=whRRx9ULPEuyw_FgUg4Z3N3O9iksyJW7ewCGZA6ujdg", + "posted_on": null, + "text": "Ariana, welcome to Google. Here’s to a year full of growth, learning, and experiences at #LifeAtGoogle! 🎉", + "total_likes": 397 + } + ], + "follower_count": 27472792, + "acquisitions": { + "acquired": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + ], + "acquired_by": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + }, + "exit_data": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/motiondsp", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/motiondsp", + "name": "MotionDSP" + } + ], + "extra": { + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "ipo_status": "Public", + "crunchbase_rank": 13, + "founding_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "operating_status": "Active", + "company_type": "For Profit", + "contact_email": "info@nvidia.com", + "phone_number": "(140) 848-6200", + "facebook_id": "NVIDIA.IN", + "twitter_id": "nvidia", + "number_of_funding_rounds": 3, + "total_funding_amount": 4000000, + "stock_symbol": "NASDAQ:NVDA", + "ipo_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "number_of_lead_investors": 3, + "number_of_investors": 4, + "total_fund_raised": 1000, + "number_of_investments": 50, + "number_of_lead_investments": 3, + "number_of_exits": 7, + "number_of_acquisitions": 2 + }, + "funding_data": [ + { + "funding_type": "Grant", + "money_raised": 25000000, + "announced_date": { + "day": 1, + "month": 1, + "year": 2001 + }, + "number_of_investor": 1, + "investor_list": [ + { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + ] + } + ], + "categories": [ + "artificial-intelligence", + "virtual-reality" + ] + } + }, + "Experience": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "company": { + "type": "string", + "nullable": true, + "description": "The company's display name." + }, + "company_linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "\n The company's profile URL on Linkedin.\n If present, could be used with \n [Company Profile Endpoint](#company-api-company-profile-endpoint) for more info.\n " + }, + "company_facebook_profile_url": { + "type": "string", + "nullable": true, + "description": "\n The company's profile URL on Facebook.\n " + }, + "title": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "location": { + "type": "string", + "nullable": true + }, + "logo_url": { + "type": "string", + "nullable": true, + "description": "URL of the logo of the organisation." + } + }, + "example": { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + } + }, + "Education": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "field_of_study": { + "type": "string", + "nullable": true + }, + "degree_name": { + "type": "string", + "nullable": true + }, + "school": { + "type": "string", + "nullable": true + }, + "school_linkedin_profile_url": { + "type": "string", + "nullable": true + }, + "school_facebook_profile_url": { + "type": "string", + "nullable": true, + "description": "\n The school's profile URL on Facebook.\n " + }, + "description": { + "type": "string", + "nullable": true + }, + "logo_url": { + "type": "string", + "nullable": true + }, + "grade": { + "type": "string" + }, + "activities_and_societies": { + "type": "string" + } + }, + "example": { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + } + }, + "AccomplishmentOrg": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "org_name": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + } + }, + "example": { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + }, + "Publication": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the publication." + }, + "publisher": { + "type": "string", + "nullable": true, + "description": "The publishing organisation body." + }, + "published_on": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date of publication." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Description of the publication." + }, + "url": { + "type": "string", + "nullable": true, + "description": "URL of the publication." + } + }, + "example": { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + }, + "HonourAward": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": true, + "description": "Title of the honour/award." + }, + "issuer": { + "type": "string", + "nullable": true, + "description": "The organisation body issuing this honour/award." + }, + "issued_on": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date that this honour/awared was issued." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Description of the honour/award." + } + }, + "example": { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + }, + "Patent": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": true, + "description": "Title of the patent." + }, + "issuer": { + "type": "string", + "nullable": true, + "description": "The organisation body that issued the patent." + }, + "issued_on": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date of patent issuance." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Description of the patent." + }, + "application_number": { + "type": "string", + "nullable": true, + "description": "Numerical representation that identifies the patent." + }, + "patent_number": { + "type": "string", + "nullable": true, + "description": "Application number of the patent." + }, + "url": { + "type": "string", + "nullable": true + } + }, + "example": { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + }, + "Course": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "Name of the course" + }, + "number": { + "type": "string", + "nullable": true, + "description": "The numerical representation of the course" + } + }, + "example": { + "name": "The course about ABCs", + "number": "123" + } + }, + "Project": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true, + "description": "\n Name of the project that has been or is currently being worked on.\n " + }, + "description": { + "type": "string", + "nullable": true, + "description": "Description of the project." + }, + "url": { + "type": "string", + "nullable": true, + "description": "A web location related to the project." + } + }, + "example": { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + } + }, + "TestScore": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "\n Title of the course for which test score was derived from.\n " + }, + "score": { + "type": "string", + "nullable": true, + "description": "Test score" + }, + "date_on": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Date of test was assesed." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Description of the test score." + } + }, + "example": { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + }, + "VolunteeringExperience": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true, + "description": "Name of volunteer activity." + }, + "cause": { + "type": "string", + "nullable": true + }, + "company": { + "type": "string", + "nullable": true, + "description": "The company's display name." + }, + "company_linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "\n The company's profile URL.\n If present, could be used with \n [Company Profile Endpoint](#company-api-company-profile-endpoint) for more info.\n " + }, + "description": { + "type": "string", + "nullable": true + }, + "logo_url": { + "type": "string", + "nullable": true, + "description": "URL of the logo of the organisation." + } + }, + "example": { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + }, + "Certification": { + "type": "object", + "properties": { + "starts_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "ends_at": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of the course or program." + }, + "license_number": { + "type": "string", + "nullable": true + }, + "display_source": { + "type": "string", + "nullable": true + }, + "authority": { + "type": "string", + "nullable": true, + "description": "The organisation body issuing this certificate." + }, + "url": { + "type": "string", + "nullable": true + } + }, + "example": { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + } + }, + "PeopleAlsoViewed": { + "type": "object", + "properties": { + "link": { + "type": "string", + "nullable": true, + "description": "\n URL of the profile.\n Useable with [Person profile endpoint](#people-api-person-profile-endpoint)\n " + }, + "name": { + "type": "string", + "nullable": true + }, + "summary": { + "type": "string", + "nullable": true + }, + "location": { + "type": "string", + "nullable": true + } + }, + "example": { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + }, + "Activity": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": true + }, + "link": { + "type": "string", + "nullable": true + }, + "activity_status": { + "type": "string", + "nullable": true + } + }, + "example": { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + }, + "SimilarProfile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "link": { + "type": "string", + "nullable": true + }, + "summary": { + "type": "string", + "nullable": true + }, + "location": { + "type": "string", + "nullable": true + } + }, + "example": { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + } + }, + "Article": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": true + }, + "link": { + "type": "string", + "nullable": true + }, + "published_date": { + "$ref": "#/components/schemas/Date", + "nullable": true + }, + "author": { + "type": "string", + "nullable": true + }, + "image_url": { + "type": "string", + "nullable": true + } + }, + "example": { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + }, + "PersonGroup": { + "type": "object", + "properties": { + "profile_pic_url": { + "type": "string", + "nullable": true, + "description": "The URL to the profile picture of this LinkedIn Group" + }, + "name": { + "type": "string", + "nullable": true, + "description": "Name of LinkedIn group for which this user is in" + }, + "url": { + "type": "string", + "nullable": true, + "description": "URL to the LinkedIn Group" + } + }, + "example": { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + }, + "InferredSalary": { + "type": "object", + "properties": { + "min": { + "type": "number", + "nullable": true + }, + "max": { + "type": "number", + "nullable": true + } + }, + "example": { + "min": 35000, + "max": 45000 + } + }, + "PersonExtra": { + "type": "object", + "properties": { + "github_profile_id": { + "type": "string", + "nullable": true, + "description": "This profile's Github account." + }, + "facebook_profile_id": { + "type": "string", + "nullable": true, + "description": "This profile's Facebook account." + }, + "twitter_profile_id": { + "type": "string", + "nullable": true, + "description": "This profile's twitter account." + }, + "website": { + "type": "string", + "nullable": true, + "description": "This account's website listed on his profile." + } + }, + "example": { + "github_profile_id": "github-username", + "facebook_profile_id": "facebook-username", + "twitter_profile_id": "twitter-username", + "website": "https://proxycurl.com" + } + }, + "PersonEndpointResponse": { + "type": "object", + "properties": { + "public_identifier": { + "type": "string", + "nullable": true, + "description": "\n The vanity identifier of the public LinkedIn profile.\n The vanity identifier comes after the `/in/` part of the LinkedIn Profile URL\n in the following format: `https://www.linkedin.com/in/`\n " + }, + "profile_pic_url": { + "type": "string", + "description": "\n A temporary link to the user's profile picture that is valid for 30 minutes. \n The temporal nature of the link is by design to prevent having Proxycurl be the mirror for the images.\n The developer is expected to handle these images by downloading the image and re-hosting the image.\n See [this post](https://nubela.co/blog/why-is-the-api-returning-s3-links-for-profile-pictures-scraped-from-linkedin-profiles/) for context.\n Some profile pictures might be of the standard LinkedIn's profile picture placeholder. It is so because. See [this post](https://nubela.co/blog/why-do-most-linkedin-profiles-fetched-via-the-person-profile-endpoint-return-a-placeholder-profile-picture/) for context.\n " + }, + "background_cover_image_url": { + "type": "string", + "nullable": true, + "description": "\n A temporary link to the user's background cover picture\n that is valid for 30 minutes.\n The temporal nature of the link is by design to prevent\n having Proxycurl be the mirror for the images.\n The developer is expected to handle these images \n by downloading the image and re-hosting the image. \n See [this post](https://nubela.co/blog/why-is-the-api-returning-s3-links-for-profile-pictures-scraped-from-linkedin-profiles/) for context.\n " + }, + "first_name": { + "type": "string", + "nullable": true, + "description": "First name of the user." + }, + "last_name": { + "type": "string", + "nullable": true, + "description": "Last name of the user." + }, + "full_name": { + "type": "string", + "nullable": true, + "description": "\n Full name of the user (`first_name` + `last_name`)\n " + }, + "follower_count": { + "type": "integer", + "description": "Follower count for this profile" + }, + "occupation": { + "type": "string", + "nullable": true, + "description": "\n The title and company name of the user's current employment.\n " + }, + "headline": { + "type": "string", + "nullable": true, + "description": "\n The tagline written by the user for his profile.\n " + }, + "summary": { + "type": "string", + "nullable": true, + "description": "\n A blurb (longer than the tagline) written by the user for his profile.\n " + }, + "country": { + "type": "string", + "nullable": true, + "description": "\n The user's country of residence depicted by\n a 2-letter country code (ISO 3166-1 alpha-2).\n " + }, + "country_full_name": { + "type": "string", + "nullable": true, + "description": "The user's country of residence, in English words." + }, + "city": { + "type": "string", + "nullable": true, + "description": "The city that the user is living at." + }, + "state": { + "type": "string", + "nullable": true, + "description": "The state that the user is living at." + }, + "experiences": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Experience" + }, + "description": "The user's list of historic work experiences." + }, + "education": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Education" + }, + "description": "The user's list of education background." + }, + "languages": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of languages that the user claims to be familiar with,\n and has added to his/her profile.\n Do note that we do not have the proficiency level as\n that data point is not available on a public LinkedIn profile.\n " + }, + "accomplishment_organisations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccomplishmentOrg" + }, + "description": "\n List of noteworthy organizations that this user is part of.\n " + }, + "accomplishment_publications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Publication" + }, + "description": "\n List of noteworthy publications that this user has partook in.\n " + }, + "accomplishment_honors_awards": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HonourAward" + }, + "description": "\n List of noteworthy honours and awards that this user has won.\n " + }, + "accomplishment_patents": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Patent" + }, + "description": "List of noteworthy patents won by this user." + }, + "accomplishment_courses": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Course" + }, + "description": "List of noteworthy courses partook by this user." + }, + "accomplishment_projects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Project" + }, + "description": "\n List of noteworthy projects undertaken by this user.\n " + }, + "accomplishment_test_scores": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TestScore" + }, + "description": "\n List of noteworthy test scores accomplished by this user.\n " + }, + "volunteer_work": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VolunteeringExperience" + }, + "description": "List of historic volunteer work experiences." + }, + "certifications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Certification" + }, + "description": "\n List of noteworthy certifications accomplished by this user.\n " + }, + "connections": { + "type": "integer", + "nullable": true, + "description": "Total *count* of LinkedIn connections." + }, + "people_also_viewed": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PeopleAlsoViewed" + }, + "description": "\n A list of other LinkedIn profiles closely related to this user.\n " + }, + "recommendations": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n List of recommendations made by other users about this profile.\n " + }, + "activities": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Activity" + }, + "description": "A list of LinkedIn status activities. This field is not guaranteed to be returned. Do not rely on this attribute in production." + }, + "similarly_named_profiles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimilarProfile" + }, + "description": "\n A list of other LinkedIn profiles with similar names.\n " + }, + "articles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Article" + }, + "description": "\n A list of content-based articles posted by this user. This field is not guaranteed to be returned. Do not rely on this attribute in production.\n " + }, + "groups": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PersonGroup" + }, + "description": "\n A list of LinkedIn groups that this user is a part of.\",\n " + }, + "skills": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of keyword-based skills that this user boasts of on his LinkedIn profile." + }, + "inferred_salary": { + "$ref": "#/components/schemas/InferredSalary", + "nullable": true, + "description": "A salary range inferred from the user's current job title and company." + }, + "gender": { + "type": "string", + "nullable": true, + "description": "Gender of the user." + }, + "birth_date": { + "$ref": "#/components/schemas/Date", + "nullable": true, + "description": "Birth date of the user." + }, + "industry": { + "type": "string", + "nullable": true, + "description": "Industry that the user works in." + }, + "extra": { + "$ref": "#/components/schemas/PersonExtra", + "nullable": true, + "description": "A bundle of extra data on this user." + }, + "interests": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of interests that the user has." + }, + "personal_emails": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of personal emails associated with this user." + }, + "personal_numbers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of personal mobile phone numbers associated with this user." + } + }, + "example": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ], + "inferred_salary": { + "min": 35000, + "max": 45000 + }, + "gender": "male", + "birth_date": { + "day": 1, + "month": 1, + "year": 1990 + }, + "industry": "government administration", + "extra": { + "github_profile_id": "github-username", + "facebook_profile_id": "facebook-username", + "twitter_profile_id": "twitter-username", + "website": "https://proxycurl.com" + }, + "interests": [ + "education", + "health", + "human rights" + ], + "personal_emails": [ + "abc@gmail.com", + "bcd@gmail.com", + "cde@@outlook.com" + ], + "personal_numbers": [ + "+6512345678", + "+6285123450953", + "+6502300340" + ] + } + }, + "CompanyCustomer": { + "type": "object", + "properties": { + "linkedin_company_profile_url": { + "type": "string", + "description": "LinkedIn Company Profile URL of a probable customer" + }, + "twitter_profile_url": { + "type": "string", + "nullable": true, + "description": "Twitter Profile URL of a probable customer" + }, + "email": { + "type": "string", + "nullable": true, + "description": "General Email address of company (if any)" + } + }, + "example": { + "linkedin_company_profile_url": "https://www.linkedin.com/company/spire-solicitors-llp", + "twitter_profile_url": "https://twitter.com/spirellp", + "email": "info@spiresolicitors.co.uk" + } + }, + "CustomerList": { + "type": "object", + "properties": { + "companies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CompanyCustomer" + }, + "description": "A list of companies that are probable customers." + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The API URI that will lead to the next page of results. This will be null for the final page.\n " + } + }, + "example": { + "companies": [ + { + "linkedin_company_profile_url": "https://www.linkedin.com/company/spire-solicitors-llp", + "twitter_profile_url": "https://twitter.com/spirellp", + "email": "info@spiresolicitors.co.uk" + }, + { + "linkedin_company_profile_url": "https://www.linkedin.com/company/mall-wood-insurance-services-ltd", + "twitter_profile_url": "https://twitter.com/draytonins", + "email": "hello@example.com" + } + ], + "next_page": null + } + }, + "CustomerCount": { + "type": "object", + "properties": { + "company_count": { + "type": "integer", + "nullable": true, + "description": "A count of of companies that are probable customers." + } + }, + "example": { + "company_count": 125 + } + }, + "PublicPerson": { + "type": "object", + "properties": { + "public_identifier": { + "type": "string", + "nullable": true, + "description": "\n The vanity identifier of the public LinkedIn profile.\n The vanity identifier comes after the `/in/` part of the LinkedIn Profile URL\n in the following format: `https://www.linkedin.com/in/`\n " + }, + "profile_pic_url": { + "type": "string", + "description": "\n A temporary link to the user's profile picture that is valid for 30 minutes. \n The temporal nature of the link is by design to prevent having Proxycurl be the mirror for the images.\n The developer is expected to handle these images by downloading the image and re-hosting the image.\n See [this post](https://nubela.co/blog/why-is-the-api-returning-s3-links-for-profile-pictures-scraped-from-linkedin-profiles/) for context.\n Some profile pictures might be of the standard LinkedIn's profile picture placeholder. It is so because. See [this post](https://nubela.co/blog/why-do-most-linkedin-profiles-fetched-via-the-person-profile-endpoint-return-a-placeholder-profile-picture/) for context.\n " + }, + "background_cover_image_url": { + "type": "string", + "nullable": true, + "description": "\n A temporary link to the user's background cover picture\n that is valid for 30 minutes.\n The temporal nature of the link is by design to prevent\n having Proxycurl be the mirror for the images.\n The developer is expected to handle these images \n by downloading the image and re-hosting the image. \n See [this post](https://nubela.co/blog/why-is-the-api-returning-s3-links-for-profile-pictures-scraped-from-linkedin-profiles/) for context.\n " + }, + "first_name": { + "type": "string", + "nullable": true, + "description": "First name of the user." + }, + "last_name": { + "type": "string", + "nullable": true, + "description": "Last name of the user." + }, + "full_name": { + "type": "string", + "nullable": true, + "description": "\n Full name of the user (`first_name` + `last_name`)\n " + }, + "follower_count": { + "type": "integer", + "description": "Follower count for this profile" + }, + "occupation": { + "type": "string", + "nullable": true, + "description": "\n The title and company name of the user's current employment.\n " + }, + "headline": { + "type": "string", + "nullable": true, + "description": "\n The tagline written by the user for his profile.\n " + }, + "summary": { + "type": "string", + "nullable": true, + "description": "\n A blurb (longer than the tagline) written by the user for his profile.\n " + }, + "country": { + "type": "string", + "nullable": true, + "description": "\n The user's country of residence depicted by\n a 2-letter country code (ISO 3166-1 alpha-2).\n " + }, + "country_full_name": { + "type": "string", + "nullable": true, + "description": "The user's country of residence, in English words." + }, + "city": { + "type": "string", + "nullable": true, + "description": "The city that the user is living at." + }, + "state": { + "type": "string", + "nullable": true, + "description": "The state that the user is living at." + }, + "experiences": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Experience" + }, + "description": "The user's list of historic work experiences." + }, + "education": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Education" + }, + "description": "The user's list of education background." + }, + "languages": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of languages that the user claims to be familiar with,\n and has added to his/her profile.\n Do note that we do not have the proficiency level as\n that data point is not available on a public LinkedIn profile.\n " + }, + "accomplishment_organisations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccomplishmentOrg" + }, + "description": "\n List of noteworthy organizations that this user is part of.\n " + }, + "accomplishment_publications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Publication" + }, + "description": "\n List of noteworthy publications that this user has partook in.\n " + }, + "accomplishment_honors_awards": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HonourAward" + }, + "description": "\n List of noteworthy honours and awards that this user has won.\n " + }, + "accomplishment_patents": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Patent" + }, + "description": "List of noteworthy patents won by this user." + }, + "accomplishment_courses": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Course" + }, + "description": "List of noteworthy courses partook by this user." + }, + "accomplishment_projects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Project" + }, + "description": "\n List of noteworthy projects undertaken by this user.\n " + }, + "accomplishment_test_scores": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TestScore" + }, + "description": "\n List of noteworthy test scores accomplished by this user.\n " + }, + "volunteer_work": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VolunteeringExperience" + }, + "description": "List of historic volunteer work experiences." + }, + "certifications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Certification" + }, + "description": "\n List of noteworthy certifications accomplished by this user.\n " + }, + "connections": { + "type": "integer", + "nullable": true, + "description": "Total *count* of LinkedIn connections." + }, + "people_also_viewed": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PeopleAlsoViewed" + }, + "description": "\n A list of other LinkedIn profiles closely related to this user.\n " + }, + "recommendations": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n List of recommendations made by other users about this profile.\n " + }, + "activities": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Activity" + }, + "description": "A list of LinkedIn status activities. This field is not guaranteed to be returned. Do not rely on this attribute in production." + }, + "similarly_named_profiles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimilarProfile" + }, + "description": "\n A list of other LinkedIn profiles with similar names.\n " + }, + "articles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Article" + }, + "description": "\n A list of content-based articles posted by this user. This field is not guaranteed to be returned. Do not rely on this attribute in production.\n " + }, + "groups": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PersonGroup" + }, + "description": "\n A list of LinkedIn groups that this user is a part of.\",\n " + }, + "skills": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of keyword-based skills that this user boasts of on his LinkedIn profile." + } + }, + "example": { + "public_identifier": "williamhgates", + "profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "background_cover_image_url": null, + "first_name": "Bill", + "last_name": "Gates", + "full_name": "Bill Gates", + "follower_count": null, + "occupation": "Co-chair at Bill & Melinda Gates Foundation", + "headline": "Co-chair, Bill & Melinda Gates Foundation", + "summary": "Co-chair of the Bill & Melinda Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "company": "Breakthrough Energy ", + "company_linkedin_profile_url": "https://www.linkedin.com/company/breakthrough-energy/", + "company_facebook_profile_url": null, + "title": "Founder", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQGwD9vNu044FA/company-logo_400_400/0/1601560874941?e=1672876800&v=beta&t=VKb6OAHEwlnazKYKm4fc9go-y4zkUv2BT6tosOdQ54Y" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2000 + }, + "ends_at": null, + "company": "Bill & Melinda Gates Foundation", + "company_linkedin_profile_url": "https://www.linkedin.com/company/bill-&-melinda-gates-foundation/", + "company_facebook_profile_url": null, + "title": "Co-chair", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQE7Na_mKQhIJg/company-logo_400_400/0/1633731810932?e=1672876800&v=beta&t=Mz_ntwD4meCMcgo1L3JqDxBQRabFLIesd0Yz2ciAXNs" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 1973 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 1975 + }, + "field_of_study": null, + "degree_name": null, + "school": "Harvard University", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQF5t62bcL0e9g/company-logo_400_400/0/1519855919126?e=1672876800&v=beta&t=9twXof1JlnNHfFprrDMi-C1Kp55HTT4ahINKHRflUHw", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": null, + "ends_at": null, + "field_of_study": null, + "degree_name": null, + "school": "Lakeside School", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQENlfOPKBEk3Q/company-logo_400_400/0/1519856497259?e=1672876800&v=beta&t=v7nJTPaJMfH7WOBjb22dyvNKxAgdPdVd8uLCUkMB1LQ", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Chinese", + "Japanese" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [], + "connections": null, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Professional and dedicated approach towards clients and collegues." + ], + "activities": [ + { + "title": "I am hiring!", + "link": "https://www.linkedin.com/feed/update/urn:li:activity:666", + "activity_status": "posted" + } + ], + "similarly_named_profiles": null, + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + } + }, + "Employee": { + "type": "object", + "properties": { + "profile_url": { + "type": "string", + "description": "\n LinkedIn Profile URL of the employee.\n " + }, + "profile": { + "$ref": "#/components/schemas/PublicPerson", + "nullable": true, + "description": "\n Enriched profile data of the employee.\n " + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "\n ISO 8601 timestamp since the enriched profile was last scraped.\n " + } + }, + "example": { + "profile_url": "https://www.linkedin.com/in/williamhgates", + "profile": { + "public_identifier": "williamhgates", + "profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "background_cover_image_url": null, + "first_name": "Bill", + "last_name": "Gates", + "full_name": "Bill Gates", + "follower_count": null, + "occupation": "Co-chair at Bill & Melinda Gates Foundation", + "headline": "Co-chair, Bill & Melinda Gates Foundation", + "summary": "Co-chair of the Bill & Melinda Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "company": "Breakthrough Energy ", + "company_linkedin_profile_url": "https://www.linkedin.com/company/breakthrough-energy/", + "company_facebook_profile_url": null, + "title": "Founder", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQGwD9vNu044FA/company-logo_400_400/0/1601560874941?e=1672876800&v=beta&t=VKb6OAHEwlnazKYKm4fc9go-y4zkUv2BT6tosOdQ54Y" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2000 + }, + "ends_at": null, + "company": "Bill & Melinda Gates Foundation", + "company_linkedin_profile_url": "https://www.linkedin.com/company/bill-&-melinda-gates-foundation/", + "company_facebook_profile_url": null, + "title": "Co-chair", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQE7Na_mKQhIJg/company-logo_400_400/0/1633731810932?e=1672876800&v=beta&t=Mz_ntwD4meCMcgo1L3JqDxBQRabFLIesd0Yz2ciAXNs" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 1973 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 1975 + }, + "field_of_study": null, + "degree_name": null, + "school": "Harvard University", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQF5t62bcL0e9g/company-logo_400_400/0/1519855919126?e=1672876800&v=beta&t=9twXof1JlnNHfFprrDMi-C1Kp55HTT4ahINKHRflUHw", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": null, + "ends_at": null, + "field_of_study": null, + "degree_name": null, + "school": "Lakeside School", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQENlfOPKBEk3Q/company-logo_400_400/0/1519856497259?e=1672876800&v=beta&t=v7nJTPaJMfH7WOBjb22dyvNKxAgdPdVd8uLCUkMB1LQ", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Chinese", + "Japanese" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [], + "connections": null, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Professional and dedicated approach towards clients and collegues." + ], + "activities": [ + { + "title": "I am hiring!", + "link": "https://www.linkedin.com/feed/update/urn:li:activity:666", + "activity_status": "posted" + } + ], + "similarly_named_profiles": null, + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "EmployeeList": { + "type": "object", + "properties": { + "employees": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Employee" + }, + "description": "\n A list of employee profiles (if enriched) and their associated profile URL.\n " + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The API URI that will lead to the next page of results. This will be null for the final page.\n " + } + }, + "example": { + "employees": [ + { + "profile_url": "https://www.linkedin.com/in/williamhgates", + "profile": { + "public_identifier": "williamhgates", + "profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "background_cover_image_url": null, + "first_name": "Bill", + "last_name": "Gates", + "full_name": "Bill Gates", + "follower_count": null, + "occupation": "Co-chair at Bill & Melinda Gates Foundation", + "headline": "Co-chair, Bill & Melinda Gates Foundation", + "summary": "Co-chair of the Bill & Melinda Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "company": "Breakthrough Energy ", + "company_linkedin_profile_url": "https://www.linkedin.com/company/breakthrough-energy/", + "company_facebook_profile_url": null, + "title": "Founder", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQGwD9vNu044FA/company-logo_400_400/0/1601560874941?e=1672876800&v=beta&t=VKb6OAHEwlnazKYKm4fc9go-y4zkUv2BT6tosOdQ54Y" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2000 + }, + "ends_at": null, + "company": "Bill & Melinda Gates Foundation", + "company_linkedin_profile_url": "https://www.linkedin.com/company/bill-&-melinda-gates-foundation/", + "company_facebook_profile_url": null, + "title": "Co-chair", + "description": null, + "location": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQE7Na_mKQhIJg/company-logo_400_400/0/1633731810932?e=1672876800&v=beta&t=Mz_ntwD4meCMcgo1L3JqDxBQRabFLIesd0Yz2ciAXNs" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 1973 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 1975 + }, + "field_of_study": null, + "degree_name": null, + "school": "Harvard University", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4E0BAQF5t62bcL0e9g/company-logo_400_400/0/1519855919126?e=1672876800&v=beta&t=9twXof1JlnNHfFprrDMi-C1Kp55HTT4ahINKHRflUHw", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": null, + "ends_at": null, + "field_of_study": null, + "degree_name": null, + "school": "Lakeside School", + "school_linkedin_profile_url": null, + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media-exp1.licdn.com/dms/image/C4D0BAQENlfOPKBEk3Q/company-logo_400_400/0/1519856497259?e=1672876800&v=beta&t=v7nJTPaJMfH7WOBjb22dyvNKxAgdPdVd8uLCUkMB1LQ", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Chinese", + "Japanese" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [], + "connections": null, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Professional and dedicated approach towards clients and collegues." + ], + "activities": [ + { + "title": "I am hiring!", + "link": "https://www.linkedin.com/feed/update/urn:li:activity:666", + "activity_status": "posted" + } + ], + "similarly_named_profiles": null, + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null + } + }, + "EmployeeCount": { + "type": "object", + "properties": { + "total_employee": { + "type": "integer" + }, + "linkedin_employee_count": { + "type": "integer", + "nullable": true, + "description": "The scraped value of employee count of this company from it's LinkedIn profile. This value does not respect `employement_status` parameter. It will always return the curent employee count of this company from LinkedIn." + }, + "linkdb_employee_count": { + "type": "integer", + "description": "The total number of employees found in LinkDB for this company. This value is limited by pre-crawled LinkedIn profiles stored in [LinkDB](https://nubela.co/proxycurl/linkdb)" + }, + "regression_notice": { + "type": "string" + } + }, + "example": { + "linkedin_employee_count": 529274, + "linkdb_employee_count": 3 + } + }, + "ProfilePicture": { + "type": "object", + "properties": { + "tmp_profile_pic_url": { + "type": "string", + "description": "\n Temporary URL to the profile picture (valid for just 30 minutes).\n See this [blog post](https://nubela.co/blog/why-is-the-api-returning-s3-links-for-profile-pictures-scraped-from-linkedin-profiles/) for more information." + } + }, + "example": { + "tmp_profile_pic_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU" + } + }, + "PersonLookupUrlEnrichResult": { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true, + "description": "The LinkedIn profile URL" + }, + "name_similarity_score": { + "type": "number", + "nullable": true, + "description": "A measure of how similar the input name is to the name in the returned profile. Values can range from `0` to `1` , with `0` indicating no similarity and `1` implying high similarity. In cases where a current profile for comparison is not available in our dataset, the result may be `null`." + }, + "company_similarity_score": { + "type": "number", + "nullable": true, + "description": "A measure of how similar the input company name/domain is to the name/domain of past or present companies in the returned profile. The score ranges from `0` to `1` , with `0` signifying no similarity and `1` denoting high similarity. If a relevant profile is unavailable in our dataset for comparison, a `null` score may be returned." + }, + "title_similarity_score": { + "type": "number", + "nullable": true, + "description": "A measure of how similar the input title is to the returned profile's past or present titles. Scores vary from `0` to `1` , where `0` means no similarity and `1` indicates high similarity. If a relevant profile for comparison isn't available in our dataset, a `null` result may occur." + }, + "location_similarity_score": { + "type": "number", + "nullable": true, + "description": "A measure of how similar the input location is to the returned profile's current location. The range is from `0` to `1` , with `0` representing no similarity and `1` signifying high similarity. If there isn't a relevant profile in our dataset for comparison, the score might be `null`. " + }, + "profile": { + "$ref": "#/components/schemas/PersonEndpointResponse" + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "ISO 8601 timestamp since the enriched profile was last scraped." + } + }, + "example": { + "url": "https://www.linkedin.com/in/senatormarty", + "name_similarity_score": 0.5, + "company_similarity_score": 0.5, + "title_similarity_score": 0.5, + "location_similarity_score": 0.5, + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ], + "inferred_salary": { + "min": 35000, + "max": 45000 + }, + "gender": "male", + "birth_date": { + "day": 1, + "month": 1, + "year": 1990 + }, + "industry": "government administration", + "extra": { + "github_profile_id": "github-username", + "facebook_profile_id": "facebook-username", + "twitter_profile_id": "twitter-username", + "website": "https://proxycurl.com" + }, + "interests": [ + "education", + "health", + "human rights" + ], + "personal_emails": [ + "abc@gmail.com", + "bcd@gmail.com", + "cde@@outlook.com" + ], + "personal_numbers": [ + "+6512345678", + "+6285123450953", + "+6502300340" + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "JobListEntry": { + "type": "object", + "properties": { + "company": { + "type": "string", + "nullable": true, + "description": "\n The name of the company that posted this job.\n " + }, + "company_url": { + "type": "string", + "nullable": true, + "description": "\n The LinkedIn Company Profile URL that posted this job.\n " + }, + "job_title": { + "type": "string", + "nullable": true, + "description": "\n Job title of the posted job.\n " + }, + "job_url": { + "type": "string", + "nullable": true, + "description": "\n Job Profile URL. You can fetch details about this job using this URL via the [Job Profile API Endpoint](https://nubela.co/proxycurl/docs#jobs-api-job-profile-endpoint).\n " + }, + "list_date": { + "type": "string", + "nullable": true, + "description": "\n The date that this job was listed.\n " + }, + "location": { + "type": "string", + "nullable": true, + "description": "\n The job location.\n " + } + }, + "example": { + "company": "Microsoft", + "company_url": "https://www.linkedin.com/company/microsoft", + "job_title": "Product Management: Intern Opportunities for University Students", + "job_url": "https://www.linkedin.com/jobs/view/product-management-intern-opportunities-for-university-students-at-microsoft-3203330682", + "list_date": "2022-10-09", + "location": "New York, NY" + } + }, + "JobListPage": { + "type": "object", + "properties": { + "job": { + "type": "array", + "items": { + "$ref": "#/components/schemas/JobListEntry" + } + }, + "next_page_no": { + "type": "integer", + "nullable": true + }, + "next_page_api_url": { + "type": "string", + "nullable": true, + "description": "\n The URL to the next page of results. This will be null for the final page.\n " + }, + "previous_page_no": { + "type": "integer", + "nullable": true + }, + "previous_page_api_url": { + "type": "string", + "nullable": true, + "description": "\n The URL to the previous page of results. This will be null for the first page.\n " + } + }, + "example": { + "job": [ + { + "company": "Microsoft", + "company_url": "https://www.linkedin.com/company/microsoft", + "job_title": "Product Management: Intern Opportunities for University Students", + "job_url": "https://www.linkedin.com/jobs/view/product-management-intern-opportunities-for-university-students-at-microsoft-3203330682", + "list_date": "2022-10-09", + "location": "New York, NY" + }, + { + "company": "Microsoft", + "company_url": "https://www.linkedin.com/company/microsoft", + "job_title": "Content Strategist", + "job_url": "https://www.linkedin.com/jobs/view/content-strategist-at-microsoft-3257692764", + "list_date": "2022-10-21", + "location": "United States" + } + ], + "next_page_no": 1, + "next_page_api_url": "http://nubela.co/proxycurl/proxycurl/api/v2/linkedin/company/job?pagination=eyJwYWdlIjogMX0&search_id=1035", + "previous_page_no": null, + "previous_page_api_url": "https://nubela.co/proxycurl/api/v2/linkedin/company/job?pagination=eyJwYWdlIjogMX0&search_id=1035" + } + }, + "JobListCount": { + "type": "object", + "properties": { + "count": { + "type": "integer" + } + }, + "example": { + "count": 887622 + } + }, + "RoleSearchEnrichedResult": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "LinkedIn Profile URL of the person that most closely matches the role" + }, + "profile": { + "$ref": "#/components/schemas/PersonEndpointResponse" + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "ISO 8601 timestamp since the enriched profile was last scraped." + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/senatormarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ], + "inferred_salary": { + "min": 35000, + "max": 45000 + }, + "gender": "male", + "birth_date": { + "day": 1, + "month": 1, + "year": 1990 + }, + "industry": "government administration", + "extra": { + "github_profile_id": "github-username", + "facebook_profile_id": "facebook-username", + "twitter_profile_id": "twitter-username", + "website": "https://proxycurl.com" + }, + "interests": [ + "education", + "health", + "human rights" + ], + "personal_emails": [ + "abc@gmail.com", + "bcd@gmail.com", + "cde@@outlook.com" + ], + "personal_numbers": [ + "+6512345678", + "+6285123450953", + "+6502300340" + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "CompanyUrlEnrichResult": { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true, + "description": "The LinkedIn profile URL" + }, + "profile": { + "$ref": "#/components/schemas/LinkedinCompany" + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "ISO 8601 timestamp since the enriched profile was last scraped." + } + }, + "example": { + "url": "https://www.linkedin.com/company/accenture", + "profile": { + "linkedin_internal_id": "1033", + "description": "Accenture is a global professional services company with leading capabilities in digital, cloud, and security. Combining unmatched experience and specialized skills across more than 40 industries, we offer Strategy and Consulting, Technology and Operations Services, and Accenture Song—all powered by the world’s largest network of Advanced Technology and Intelligent Operations centers. \n\nOur people deliver on the promise of technology and human ingenuity every day, serving clients in more than 120 countries. We embrace the power of change to create value and shared success for our clients, people, shareholders, partners, and communities. \n\nVisit us at accenture.com.", + "website": "http://www.accenture.com", + "industry": "Business Consulting and Services", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 541251, + "hq": { + "country": "IE", + "city": "Dublin 2", + "postal_code": null, + "line_1": "Grand Canal Harbour", + "is_hq": true, + "state": null + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "Management Consulting", + "Systems Integration and Technology" + ], + "locations": [ + { + "country": "IE", + "city": "Dublin 2", + "postal_code": null, + "line_1": "Grand Canal Harbour", + "is_hq": true, + "state": null + }, + { + "country": "US", + "city": "San Francisco", + "postal_code": "94105", + "line_1": "415 Mission Street Floor 31-34", + "is_hq": null, + "state": "California" + } + ], + "name": "Accenture", + "tagline": "Think Different - But Not Too Different", + "universal_name_id": "accenture", + "profile_pic_url": "https://media.licdn.com/dms/image/D4E0BAQGTUswcRlgg9A/company-logo_200_200/0/1689352303421/accenture_logo?e=2147483647&v=beta&t=cjQy2p9bf0c2mJqCNVzaiLqdByE0zboCX3vY5m4gRuY", + "background_cover_image_url": "https://media.licdn.com/dms/image/D4E3DAQEJ2lIxxNO81Q/image-scale_191_1128/0/1689359170613/accenture_cover?e=1698901200&v=beta&t=8ygpwsa5GjMoubooCGg1MqfGomnBaU9WHwnI3_Ek0_0", + "search_id": "1033", + "similar_companies": [ + { + "name": "Deloitte", + "link": "https://www.linkedin.com/company/deloitte", + "industry": "Business Consulting and Services", + "location": null + }, + { + "name": "Tata Consultancy Services", + "link": "https://in.linkedin.com/company/tata-consultancy-services", + "industry": "IT Services and IT Consulting", + "location": "Mumbai, Maharashtra" + } + ], + "affiliated_companies": [ + { + "name": "Accenture in India", + "link": "https://in.linkedin.com/company/accentureindia", + "industry": "IT Services and IT Consulting", + "location": "Bengaluru, Karnatka" + }, + { + "name": "Accenture Brasil", + "link": "https://br.linkedin.com/company/accenturebrasil", + "industry": "IT Services and IT Consulting", + "location": "São Paulo, São Paulo" + } + ], + "updates": [ + { + "article_link": null, + "image": null, + "posted_on": { + "day": 25, + "month": 10, + "year": 2023 + }, + "text": "Explore #AccentureLifeTrends 2024 to learn more: https://accntu.re/3MfdMg4", + "total_likes": 325 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/D5610AQEMoO_uNVz5BQ/ads-video-thumbnail_720_1280/0/1698154984087?e=1698901200&v=beta&t=WTxhLNSbSM-UBnFIcqYX4bdVhVUD6OoOoffR0xQnlDA", + "posted_on": { + "day": 25, + "month": 10, + "year": 2023 + }, + "text": "The ability to learn new things, without forgetting those that came before, is a huge differentiator between the #AI we're familiar with, and the #GenerativeAI powered by foundation models that we're seeing now.\n \nDiscover the trends shaping the next decade: https://accntu.re/474YxOH\n \n#TechVision2023", + "total_likes": 541 + } + ], + "follower_count": 11125167, + "acquisitions": { + "acquired": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + ], + "acquired_by": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + }, + "exit_data": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/motiondsp", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/motiondsp", + "name": "MotionDSP" + } + ], + "extra": { + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "ipo_status": "Public", + "crunchbase_rank": 13, + "founding_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "operating_status": "Active", + "company_type": "For Profit", + "contact_email": "info@nvidia.com", + "phone_number": "(140) 848-6200", + "facebook_id": "NVIDIA.IN", + "twitter_id": "nvidia", + "number_of_funding_rounds": 3, + "total_funding_amount": 4000000, + "stock_symbol": "NASDAQ:NVDA", + "ipo_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "number_of_lead_investors": 3, + "number_of_investors": 4, + "total_fund_raised": 1000, + "number_of_investments": 50, + "number_of_lead_investments": 3, + "number_of_exits": 7, + "number_of_acquisitions": 2 + }, + "funding_data": [ + { + "funding_type": "Grant", + "money_raised": 25000000, + "announced_date": { + "day": 1, + "month": 1, + "year": 2001 + }, + "number_of_investor": 1, + "investor_list": [ + { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + ] + } + ], + "categories": [ + "artificial-intelligence", + "virtual-reality" + ] + }, + "last_updated": "2023-10-26T11:33:24Z" + } + }, + "Student": { + "type": "object", + "properties": { + "profile_url": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/PublicPerson", + "nullable": true + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "\n ISO 8601 timestamp since the enriched profile was last scraped.\n " + } + }, + "example": { + "profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "StudentList": { + "type": "object", + "properties": { + "students": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Student" + }, + "description": "\n A list of student profiles (if enriched) and their associated profile URL.\n " + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The API URI that will lead to the next page of results. This will be null for the final page.\n " + } + }, + "example": { + "students": [ + { + "profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null + } + }, + "ReverseEmailUrlEnrichResult": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the closest match of the LinkedIn profile that belongs to this email address." + }, + "twitter_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the Twitter Profile URL that belongs to this email address." + }, + "facebook_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the Facebook Profile URL that belongs to this email address." + }, + "url": { + "type": "string", + "nullable": true + }, + "similarity_score": { + "type": "number", + "nullable": true, + "description": "This metric quantifies the degree of resemblance between the queried profile and the retrieved one. Scores range from `0` (no similarity) to `1` (high similarity). In the event that our dataset lacks a pertinent profile for comparison, the assigned score might be `null`." + }, + "backwards_compatibility_notes": { + "type": "string", + "nullable": true + }, + "profile": { + "$ref": "#/components/schemas/PersonEndpointResponse", + "nullable": true + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "ISO 8601 timestamp since the enriched profile was last scraped." + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/senatormarty", + "twitter_profile_url": "https://www.twitter.com/proxycurl", + "facebook_profile_url": "https://www.facebook.com/zuck", + "similarity_score": 0.82, + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ], + "inferred_salary": { + "min": 35000, + "max": 45000 + }, + "gender": "male", + "birth_date": { + "day": 1, + "month": 1, + "year": 1990 + }, + "industry": "government administration", + "extra": { + "github_profile_id": "github-username", + "facebook_profile_id": "facebook-username", + "twitter_profile_id": "twitter-username", + "website": "https://proxycurl.com" + }, + "interests": [ + "education", + "health", + "human rights" + ], + "personal_emails": [ + "abc@gmail.com", + "bcd@gmail.com", + "cde@@outlook.com" + ], + "personal_numbers": [ + "+6512345678", + "+6285123450953", + "+6502300340" + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "ReverseContactNumberResult": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the closest match of the LinkedIn profile that belongs to this phone number." + }, + "twitter_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the Twitter Profile URL that belongs to this phone number." + }, + "facebook_profile_url": { + "type": "string", + "nullable": true, + "description": "Returns the Facebook Profile URL that belongs to this phone number." + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/senatormarty", + "twitter_profile_url": "https://www.twitter.com/proxycurl", + "facebook_profile_url": "https://www.facebook.com/zuck" + } + }, + "ExtractionEmailResult": { + "type": "object", + "properties": { + "email_queue_count": { + "type": "integer", + "description": "Total queue in the email extraction process" + } + }, + "example": { + "email_queue_count": null + } + }, + "JobLocation": { + "type": "object", + "properties": { + "country": { + "type": "string", + "nullable": true, + "description": "\n Full country name.\n " + }, + "region": { + "type": "string", + "nullable": true, + "description": "\n Region.\n " + }, + "city": { + "type": "string", + "nullable": true, + "description": "\n The city for the job.\n " + }, + "postal_code": { + "type": "string", + "nullable": true, + "description": "\n Postal code of the business location for the job.\n " + }, + "latitude": { + "type": "number", + "nullable": true, + "description": "\n Latitude coordinates of the business location for the job.\n " + }, + "longitude": { + "type": "number", + "nullable": true, + "description": "\n Longitude coordinates of the business location for the job.\n " + }, + "street": { + "type": "string", + "nullable": true, + "description": "\n Street address of the business location for the job.\n " + } + }, + "example": { + "country": "United States", + "region": "Hawaii", + "city": null, + "postal_code": null, + "latitude": null, + "longitude": null, + "street": null + } + }, + "JobCompany": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "description": "\n The name of the company.\n " + }, + "url": { + "type": "string", + "nullable": true, + "description": "\n The LinkedIn Company Profile URL of the job posting company.\n " + }, + "logo": { + "type": "string", + "nullable": true, + "description": "\n The URL to the logo of this company.\n " + } + }, + "example": { + "name": "Microsoft", + "url": "https://www.linkedin.com/company/microsoft", + "logo": "https://media.licdn.com/dms/image/C560BAQE88xCsONDULQ/company-logo_100_100/0/1618231291419?e=2147483647&v=beta&t=rffql7GLHsSqWXKbdP2LJMMv7CMTqu7-Ms9d9tophKI" + } + }, + "JobProfile": { + "type": "object", + "properties": { + "linkedin_internal_id": { + "type": "string", + "nullable": true, + "description": "\n The internal ID representation of this job that LinkedIn has for this job.\n " + }, + "job_description": { + "type": "string", + "nullable": true, + "description": "\n Description of the posted job.\n " + }, + "apply_url": { + "type": "string", + "nullable": true, + "description": "\n The URL to apply for this job.\n " + }, + "title": { + "type": "string", + "nullable": true, + "description": "\n Title of the posted job.\n " + }, + "location": { + "$ref": "#/components/schemas/JobLocation" + }, + "company": { + "$ref": "#/components/schemas/JobCompany" + }, + "seniority_level": { + "type": "string", + "nullable": true, + "description": "\n The seniority level for this role.\n " + }, + "industry": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of industries that the company which posted this job lies in.\n " + }, + "employment_type": { + "type": "string", + "nullable": true, + "description": "\n Type of employment.\n " + }, + "job_functions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "\n A list of job functions that this role is expected to cover.\n " + }, + "total_applicants": { + "type": "integer", + "nullable": true, + "description": "\n Total applicants for this job so far.\n " + } + }, + "example": { + "linkedin_internal_id": "content-strategist-at-microsoft-3257696537", + "job_description": "The Global Demand Center (GDC) within the Cloud Marketing group is leading the marketing transformation of Microsoft’s largest and fastest growing commercial businesses. Our always-on integrated marketing programs work to nurture and acquire new customers across segments, targeting business and technical audiences across our commercial cloud portfolio, with programs available in 42 markets and 30 languages. The GDC team is modernizing and integrating these channels through advanced analytics, marketing automation, and digital marketing. We are on a mission to drive market share, consumption, and consistent double-digit+ revenue growth. Content is the fuel that drives the digitally connected customer journeys at the core of the GDC engine, and we’re looking for a skilled, self-motivated, data-driven content strategist to build the content that motivates customers to take action. The Content Strategist will develop and execute content strategies for the ever-critical security space. You will be accountable for understanding the business priorities, getting close to our target audiences, defining the content journeys that attract, nurture, inspire, and retain customers, and manage quality execution and delivery of the content. You will work closely with your counterparts, the integrated marketing strategists, to drive business outcomes. Your network will include product marketers, integrated marketers, relationship marketers, sales, engineering, and agency partners to develop and execute on your plan. Our team: The Lifecycle Programs team is a fast-paced digital marketing organization. We put a focus on getting things done, simplifying anything and everything, and having fun while doing it. We all believe in connecting with customers at scale, supporting them at each stage of the customer journey, from early awareness and consideration, through onboarding and post purchase engagement. You will be in the middle of it all helping to identify the right content that delivers what customers want—where they want it, when they want it, and how they want it. \n \n**_Responsibilities \n_**\n * Define content journeys for Security and IT professionals across industries.\n * Build the resulting content strategies designed to accelerate the customer through the lifecycle.\n * Create a content plan to address the insights in the customer journey and strategy, ensuring the content is aligned to what the customer needs at each stage.\n * Deliver the content through our internal Studio or with select agency partners.\n * Be a customer advocate. Relentlessly champion the customer and the experiences they have with the content you create—how they find it, how they consume it, how they use it to make decisions.\n * Leverage data and market insights for decision making including content optimization and new concept development. \n\n\n**_Qualifications \n \n_** **Required/Minimum Qualifications \n**\n * Bachelor's Degree in Business, Marketing, Communications, Economics, Public Relations, or related field AND 1+ year(s) integrated marketing (e.g., digital, relationship, social media, campaign), event management, marketing strategy, business planning, marketing operations, or related work experience\n * OR equivalent experience. \n\n\n**_Additional Or Preferred Qualifications \n_**\n * Bachelor's Degree in Business, Marketing, Communications, Economics, Public Relations, or related field AND 3+ years integrated marketing (e.g., digital, relationship, social media, campaign), event management, marketing strategy, business planning, marketing operations, or related work experience\n * OR equivalent experience.\n * Strong customer centric mindset and demonstrated ability to put the customer first.\n * Clear and persuasive communication skills, both written and verbal.\n * Experience with program performance tracking and communications.\n * Recognized as a self-starter with a bias for action.\n * Creative problem-solving skills, and a growth mindset approach\n * Experience managing across highly matrixed organizations, often with competing priorities.\n * A demonstrated track record of business impact through content\n * Well-versed in digital marketing best practices, including journey mapping.\n * Understanding of content disciplines, including SEO, content strategy, and execution.\n * Preferred, but not required: experience with commercial technology sales process \n\n\nNarrative \n \nIntegrated Marketing IC3 - The typical base pay range for this role across the U.S. is USD $80,900 - $162,200 per year. There is a different range applicable to specific work locations, within the San Francisco Bay area and New York City metropolitan area, and the base pay range for this role in those locations is USD $105,300 - $176,900 per year. \n \nMicrosoft has different base pay ranges for different work locations within the United States, which allows us to pay employees competitively and consistently in different geographic markets (see below). The range above reflects the potential base pay across the U.S. for this role (except as noted below); the applicable base pay range will depend on what ultimately is determined to be the candidate’s primary work location. Individual base pay depends on various factors, in addition to primary work location, such as complexity and responsibility of role, job duties/requirements, and relevant experience and skills. Base pay ranges are reviewed and typically updated each year. Offers are made within the base pay range applicable at the time. \n \nAt Microsoft certain roles are eligible for additional rewards, including merit increases, annual bonus and stock. These awards are allocated based on individual performance. In addition, certain roles also have the opportunity to earn sales incentives based on revenue or utilization, depending on the terms of the plan and the employee’s role. Benefits/perks listed here may vary depending on the nature of employment with Microsoft and the country work location. U.S.-based employees have access to healthcare benefits, a 401(k) plan and company match, short-term and long-term disability coverage, basic life insurance, wellbeing benefits, paid vacation time, paid sick and mental health time, and several paid holidays, among others. \n \nOur commitment to pay equity \n \nWe are committed to the principle of pay equity – paying employees equitably for substantially similar work. To learn more about pay equity and our other commitments to increase representation and strengthen our culture of inclusion, check out our annual Diversity & Inclusion Report. ( https://www.microsoft.com/en-us/diversity/inside-microsoft/annual-report ) \n \nUnderstanding roles at Microsoft \n \nThe top of this page displays the role for which the base pay ranges apply – Integrated Marketing IC3. The way we define roles includes two things: discipline (the type of work) and career stage (scope and complexity). The career stage has two parts – the first identifies whether the role is a manager (M), an individual contributor (IC), an admin-technician-retail (ATR) job, or an intern. The second part identifies the relative seniority of the role – a higher number (or later letter alphabetically in the case of ATR) indicates greater scope and complexity. \n \nMicrosoft is an equal opportunity employer. All qualified applicants will receive consideration for employment without regard to age, ancestry, color, family or medical care leave, gender identity or expression, genetic information, marital status, medical condition, national origin, physical or mental disability, political affiliation, protected veteran status, race, religion, sex (including pregnancy), sexual orientation, or any other characteristic protected by applicable laws, regulations and ordinances. We also consider qualified applicants regardless of criminal histories, consistent with legal requirements. If you need assistance and/or a reasonable accommodation due to a disability during the application or the recruiting process, please send a request via the Accommodation request form. \n \nThe salary for this role in the state of Colorado is between $108,200 and $162,200. \n \nAt Microsoft, certain roles are eligible for additional rewards, including annual bonus and stock. These awards are allocated based on individual performance. In addition, certain roles also have the opportunity to earn sales incentives based on revenue or utilization, depending on the terms of the plan and the employee’s role. Benefits/perks listed below may vary depending on the nature of your employment with Microsoft and the country where you work. \n", + "apply_url": "https://sg.linkedin.com/jobs/view/externalApply/3257696537?url=https%3A%2F%2Fcareers%2Emicrosoft%2Ecom%2Fus%2Fen%2Fjob%2F1451110%2FContent-Strategist%3Fjobsource%3Dlinkedin%26utm_source%3Dlinkedin%26utm_medium%3Dlinkedin%26utm_campaign%3Dlinkedin-feed&urlHash=I9BQ&trk=public_jobs_apply-link-offsite", + "title": "Content Strategist", + "location": { + "country": "United States", + "region": "Hawaii", + "city": null, + "postal_code": null, + "latitude": null, + "longitude": null, + "street": null + }, + "company": { + "name": "Microsoft", + "url": "https://www.linkedin.com/company/microsoft", + "logo": "https://media.licdn.com/dms/image/C560BAQE88xCsONDULQ/company-logo_100_100/0/1618231291419?e=2147483647&v=beta&t=rffql7GLHsSqWXKbdP2LJMMv7CMTqu7-Ms9d9tophKI" + }, + "seniority_level": "Mid-Senior level", + "industry": [ + "IT Services and IT Consulting, Computer Hardware Manufacturing, and Software Development" + ], + "employment_type": "Full-time", + "job_functions": [ + "Marketing" + ], + "total_applicants": 200 + } + }, + "Follower": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "nullable": true + }, + "twitter_profile_url": { + "type": "string" + }, + "email": { + "type": "string", + "nullable": true + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/agiliosoftware", + "twitter_profile_url": "https://www.x.com/agilio_software", + "email": null + } + }, + "FollowerList": { + "type": "object", + "properties": { + "followers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Follower" + }, + "description": "\n A list of individual followers of a company.\n " + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The API URI that will lead to the next page of results. This will be null for the final page.\n " + } + }, + "example": { + "followers": [ + { + "linkedin_profile_url": "https://www.linkedin.com/in/agiliosoftware", + "twitter_profile_url": "https://www.x.com/agilio_software", + "email": null + }, + { + "linkedin_profile_url": "https://www.linkedin.com/in/air-techniques", + "twitter_profile_url": "https://www.x.com/airtechniques", + "email": null + } + ], + "next_page": null + } + }, + "FollowerListCount": { + "type": "object", + "properties": { + "follower_count": { + "type": "integer", + "description": "A count of all individuals that are probable customers or followers." + } + }, + "example": { + "follower_count": 74 + } + }, + "CSearchResult": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "description": "\n The LinkedIn Profile URL of the company\n " + }, + "profile": { + "$ref": "#/components/schemas/LinkedinCompany", + "nullable": true, + "description": "\n If `enrich_profiles=enrich` is specified, the company's entire profile\n is returned. Otherwise this field will return `null`.\n " + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "\n ISO 8601 timestamp since the enriched profile was last scraped.\n " + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/company/apple/", + "profile": { + "linkedin_internal_id": "1441", + "description": "A problem isn't truly solved until it's solved for all. Googlers build products that help create opportunities for everyone, whether down the street or across the globe. Bring your insight, imagination and a healthy disregard for the impossible. Bring everything that makes you unique. Together, we can build for everyone.\n\nCheck out our career opportunities at careers.google.com.", + "website": "https://goo.gle/3m1IN7m", + "industry": "Software Development", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 319856, + "hq": { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "search", + "ads" + ], + "locations": [ + { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + { + "country": "US", + "city": "New York", + "postal_code": "10011", + "line_1": "111 8th Ave", + "is_hq": null, + "state": "NY" + } + ], + "name": "Google", + "tagline": "Think Different - But Not Too Different", + "universal_name_id": "google", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3500b39da8db1d2d8f5727a9ac39a7c4a88b4632ed68209dee12f06bc79aca", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abb7a4b87583cffda8db24d58d906c644998fae8cbb99e98c69a35720fcd0050", + "search_id": "1441", + "similar_companies": [ + { + "name": "Amazon", + "link": "https://www.linkedin.com/company/amazon", + "industry": "Software Development", + "location": "Seattle, WA" + }, + { + "name": "Microsoft", + "link": "https://www.linkedin.com/company/microsoft", + "industry": "Software Development", + "location": "Redmond, Washington" + } + ], + "affiliated_companies": [ + { + "name": "YouTube", + "link": "https://www.linkedin.com/company/youtube", + "industry": "Software Development", + "location": "San Bruno, CA" + }, + { + "name": "Google Cloud", + "link": "https://www.linkedin.com/showcase/google-cloud", + "industry": "Software Development", + "location": "Mountain View, California" + } + ], + "updates": [ + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C5605AQFthnjiTD6Mvg/videocover-high/0/1660754102856?e=2147483647&v=beta&t=PPOsA9J3vCTXWhuZclqSBQl7DLSDLvy5hKWlkHI85YE", + "posted_on": { + "day": 13, + "month": 9, + "year": 2022 + }, + "text": "Want to kick start your #LifeAtGoogle but not sure where to begin? Explore our Build Your Future site, where you can learn about developmental programs, learn tips for future interviews, sign up for informational events, and even hear real stories from Googlers who’ve been where you are now. Get started → https://bit.ly/3SKPzQB", + "total_likes": 4267 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C4D22AQGcvTlKRR3qvQ/feedshare-shrink_2048_1536/0/1672854668558?e=1676505600&v=beta&t=whRRx9ULPEuyw_FgUg4Z3N3O9iksyJW7ewCGZA6ujdg", + "posted_on": null, + "text": "Ariana, welcome to Google. Here’s to a year full of growth, learning, and experiences at #LifeAtGoogle! 🎉", + "total_likes": 397 + } + ], + "follower_count": 27472792, + "acquisitions": { + "acquired": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + ], + "acquired_by": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + }, + "exit_data": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/motiondsp", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/motiondsp", + "name": "MotionDSP" + } + ], + "extra": { + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "ipo_status": "Public", + "crunchbase_rank": 13, + "founding_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "operating_status": "Active", + "company_type": "For Profit", + "contact_email": "info@nvidia.com", + "phone_number": "(140) 848-6200", + "facebook_id": "NVIDIA.IN", + "twitter_id": "nvidia", + "number_of_funding_rounds": 3, + "total_funding_amount": 4000000, + "stock_symbol": "NASDAQ:NVDA", + "ipo_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "number_of_lead_investors": 3, + "number_of_investors": 4, + "total_fund_raised": 1000, + "number_of_investments": 50, + "number_of_lead_investments": 3, + "number_of_exits": 7, + "number_of_acquisitions": 2 + }, + "funding_data": [ + { + "funding_type": "Grant", + "money_raised": 25000000, + "announced_date": { + "day": 1, + "month": 1, + "year": 2001 + }, + "number_of_investor": 1, + "investor_list": [ + { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + ] + } + ], + "categories": [ + "artificial-intelligence", + "virtual-reality" + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "CompanySearchResult": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CSearchResult" + }, + "description": "\n A list of SearchResult objects.\n " + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The URL to the next page of search results. This will be null for the final page.\n " + }, + "total_result_count": { + "type": "integer", + "description": "Total results found." + } + }, + "example": { + "results": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple/", + "profile": { + "linkedin_internal_id": "1441", + "description": "A problem isn't truly solved until it's solved for all. Googlers build products that help create opportunities for everyone, whether down the street or across the globe. Bring your insight, imagination and a healthy disregard for the impossible. Bring everything that makes you unique. Together, we can build for everyone.\n\nCheck out our career opportunities at careers.google.com.", + "website": "https://goo.gle/3m1IN7m", + "industry": "Software Development", + "company_size": [ + 10001, + null + ], + "company_size_on_linkedin": 319856, + "hq": { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + "company_type": "PUBLIC_COMPANY", + "founded_year": null, + "specialities": [ + "search", + "ads" + ], + "locations": [ + { + "country": "US", + "city": "Mountain View", + "postal_code": "94043", + "line_1": "1600 Amphitheatre Parkway", + "is_hq": true, + "state": "CA" + }, + { + "country": "US", + "city": "New York", + "postal_code": "10011", + "line_1": "111 8th Ave", + "is_hq": null, + "state": "NY" + } + ], + "name": "Google", + "tagline": "Think Different - But Not Too Different", + "universal_name_id": "google", + "profile_pic_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/profile?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3500b39da8db1d2d8f5727a9ac39a7c4a88b4632ed68209dee12f06bc79aca", + "background_cover_image_url": "https://s3.us-west-000.backblazeb2.com/proxycurl/company/google/cover?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0004d7f56a0400b0000000001%2F20230119%2Fus-west-000%2Fs3%2Faws4_request&X-Amz-Date=20230119T060024Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=abb7a4b87583cffda8db24d58d906c644998fae8cbb99e98c69a35720fcd0050", + "search_id": "1441", + "similar_companies": [ + { + "name": "Amazon", + "link": "https://www.linkedin.com/company/amazon", + "industry": "Software Development", + "location": "Seattle, WA" + }, + { + "name": "Microsoft", + "link": "https://www.linkedin.com/company/microsoft", + "industry": "Software Development", + "location": "Redmond, Washington" + } + ], + "affiliated_companies": [ + { + "name": "YouTube", + "link": "https://www.linkedin.com/company/youtube", + "industry": "Software Development", + "location": "San Bruno, CA" + }, + { + "name": "Google Cloud", + "link": "https://www.linkedin.com/showcase/google-cloud", + "industry": "Software Development", + "location": "Mountain View, California" + } + ], + "updates": [ + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C5605AQFthnjiTD6Mvg/videocover-high/0/1660754102856?e=2147483647&v=beta&t=PPOsA9J3vCTXWhuZclqSBQl7DLSDLvy5hKWlkHI85YE", + "posted_on": { + "day": 13, + "month": 9, + "year": 2022 + }, + "text": "Want to kick start your #LifeAtGoogle but not sure where to begin? Explore our Build Your Future site, where you can learn about developmental programs, learn tips for future interviews, sign up for informational events, and even hear real stories from Googlers who’ve been where you are now. Get started → https://bit.ly/3SKPzQB", + "total_likes": 4267 + }, + { + "article_link": null, + "image": "https://media.licdn.com/dms/image/C4D22AQGcvTlKRR3qvQ/feedshare-shrink_2048_1536/0/1672854668558?e=1676505600&v=beta&t=whRRx9ULPEuyw_FgUg4Z3N3O9iksyJW7ewCGZA6ujdg", + "posted_on": null, + "text": "Ariana, welcome to Google. Here’s to a year full of growth, learning, and experiences at #LifeAtGoogle! 🎉", + "total_likes": 397 + } + ], + "follower_count": 27472792, + "acquisitions": { + "acquired": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/apple", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/apple", + "announced_date": { + "day": 1, + "month": 4, + "year": 1976 + }, + "price": 300000000 + } + ], + "acquired_by": { + "linkedin_profile_url": "https://www.linkedin.com/company/nvidia", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "announced_date": { + "day": 6, + "month": 3, + "year": 2020 + }, + "price": 10000 + } + }, + "exit_data": [ + { + "linkedin_profile_url": "https://www.linkedin.com/company/motiondsp", + "crunchbase_profile_url": "https://www.crunchbase.com/organization/motiondsp", + "name": "MotionDSP" + } + ], + "extra": { + "crunchbase_profile_url": "https://www.crunchbase.com/organization/nvidia", + "ipo_status": "Public", + "crunchbase_rank": 13, + "founding_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "operating_status": "Active", + "company_type": "For Profit", + "contact_email": "info@nvidia.com", + "phone_number": "(140) 848-6200", + "facebook_id": "NVIDIA.IN", + "twitter_id": "nvidia", + "number_of_funding_rounds": 3, + "total_funding_amount": 4000000, + "stock_symbol": "NASDAQ:NVDA", + "ipo_date": { + "day": 1, + "month": 1, + "year": 2000 + }, + "number_of_lead_investors": 3, + "number_of_investors": 4, + "total_fund_raised": 1000, + "number_of_investments": 50, + "number_of_lead_investments": 3, + "number_of_exits": 7, + "number_of_acquisitions": 2 + }, + "funding_data": [ + { + "funding_type": "Grant", + "money_raised": 25000000, + "announced_date": { + "day": 1, + "month": 1, + "year": 2001 + }, + "number_of_investor": 1, + "investor_list": [ + { + "linkedin_profile_url": "https://linkedin.com/company/darpa", + "name": "DARPA", + "type": "organization" + } + ] + } + ], + "categories": [ + "artificial-intelligence", + "virtual-reality" + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null, + "total_result_count": 1 + } + }, + "SearchResult": { + "type": "object", + "properties": { + "linkedin_profile_url": { + "type": "string", + "description": "\n The LinkedIn Profile URL of the person\n " + }, + "profile": { + "$ref": "#/components/schemas/PublicPerson", + "nullable": true, + "description": "\n If `enrich_profiles=enrich` is specified, the person's entire profile\n is returned. Otherwise this field will return `null`.\n " + }, + "last_updated": { + "type": "string", + "nullable": true, + "description": "\n ISO 8601 timestamp since the enriched profile was last scraped.\n " + } + }, + "example": { + "linkedin_profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + }, + "PersonSearchResult": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchResult" + }, + "description": "\n A list of SearchResult objects\n " + }, + "next_page": { + "type": "string", + "nullable": true, + "description": "\n The URL to the next page of search results. This will be null for the final page.\n " + }, + "total_result_count": { + "type": "integer", + "description": "Total results found." + } + }, + "example": { + "results": [ + { + "linkedin_profile_url": "https://www.linkedin.com/in/johnrmarty", + "profile": { + "public_identifier": "johnrmarty", + "profile_pic_url": "https://media.licdn.com/dms/image/C5603AQHaJSx0CBAUIA/profile-displayphoto-shrink_800_800/0/1558325759208?e=2147483647&v=beta&t=BluXpPg88xFnU2wMGLjuCUykSk_wKNdh8x3PI9wm6MI", + "background_cover_image_url": "https://media.licdn.com/dms/image/C5616AQH9tkBTUhHfng/profile-displaybackgroundimage-shrink_200_800/0/1614530499015?e=2147483647&v=beta&t=VEoCyedtZulnAVYWT9BXfKHi5OFp8avElNjiz8kjSTU", + "first_name": "John", + "last_name": "Marty", + "full_name": "John Marty", + "follower_count": null, + "occupation": "Co-Founder at Freedom Fund Real Estate", + "headline": "Financial Freedom through Real Estate - LinkedIn Top Voice", + "summary": "Most people go through life lost, disengaged, and unhappy at work and in their lives - I'm on a mission to solve that.\n\nI spent 10 years as the founder of Axxis Audio, an electronics company that grew to multi-million dollar sales, which I sold in 2012. At that time, I funneled my earnings into the creation of an Internet of Things company, but numerous factors lead to its demise after 2 hard fought years. \n\nAt 31, I was penny-less, had a baby on the way, and had zero job prospects (despite applying to 150 companies). My desperate situation led me to take a job at Best Buy for $12 an hour while reinventing myself through the completion of an MBA at the University of Colorado, and a 6-month software development boot camp. \n\nAfter graduation, I landed at American Express as a Senior Product Manager and then got poached by Amazon in 2017 (because of my LinkedIn profile). My journey has led to a deep sense of perspective, humility, and purpose that I draw on to help others find clarity, meaning, and happiness in their careers and lives. \n\nCheck out my website for details on my Mindset Reset Podcast, Public Speaking, Consulting, or my free 40 page LinkedIn guide\n\nhttp://www.johnraphaelmarty.com/\n\nFAQ's\n\nQ: Can you speak at my Company, University, event or podcast?\nA: I'd love to! I've shared my message on the future of employment, breaking into big tech, and my personal story of reinventing myself and discovering my sense of purpose (and how you can too!).\n\n☑️ YouTube Channel #1 (John Marty) : http://www.youtube.com/c/JohnMarty-uncommon\n☑️ YouTube Channel #2 (Tech Careers for non-engineers: https://www.youtube.com/channel/UC900gMMPLwRGGXSTW1gdZHA\n\nFUN FACTS:\n☑️ I am an Avid cyclist and runner, and I just started learning to skateboard a half-pipe.\n☑️ Into the Enneagram? - I'm a #3 (The Achiever)\n\nLETS CONNECT:\n☑️ Email: JohnRmarty@gmail.com (don't forget that \"R\"....The other guy gets my emails all the time)", + "country": "US", + "country_full_name": "United States of America", + "city": "Seattle", + "state": "Washington", + "experiences": [ + { + "starts_at": { + "day": 1, + "month": 8, + "year": 2021 + }, + "ends_at": null, + "company": "Freedom Fund Real Estate", + "company_linkedin_profile_url": "https://www.linkedin.com/company/freedomfund", + "company_facebook_profile_url": null, + "title": "Co-Founder", + "description": "Our mission is to provide everyday people seeking financial freedom long before the age of 65 with the ability to invest in high yield, short-term real estate investments that were only accessible in the past for a select few wealthy individuals. Each of our single family rehab projects require a minimum investment contribution of only $10K, we have simple terms, no multi-year hold periods, and no fees. With our unique model investors can log into our easy to use website, select the projects that they want to invest in, and get realtime updates on the status of their investments.\n\nWebsite: https://www.freedomfundinvestments.com/home", + "location": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQEYxazZM_hXgQ/company-logo_100_100/0/1634934418976?e=2147483647&v=beta&t=wI0YdMmxIctkzvnKxRfuAbT8h5eok_DlUqEph68J37s" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2021 + }, + "ends_at": null, + "company": "Mindset Reset Podcast", + "company_linkedin_profile_url": "https://www.linkedin.com/company/mindset-reset-podcast", + "company_facebook_profile_url": null, + "title": "Founder", + "description": "We dive into the mindsets of the world’s foremost thought leaders and turn them into actionable insights so that others can discover greater happiness, success, and fulfillment.\n\nhttps://podcasts.apple.com/us/podcast/mindset-reset/id1553212607", + "location": "Denver, Colorado, United States", + "logo_url": "https://media.licdn.com/dms/image/C560BAQF9QJVQm3SOvA/company-logo_100_100/0/1614527476576?e=2147483647&v=beta&t=m3tx83nMN-E3XQFoJG0Wmch8U4qKnJ9i--5NSAfffC0" + } + ], + "education": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2013 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "Finance + Economics", + "degree_name": "Master of Business Administration (MBA)", + "school": "University of Colorado Denver", + "school_linkedin_profile_url": "https://www.linkedin.com/school/university-of-colorado-denver/", + "school_facebook_profile_url": null, + "description": null, + "logo_url": "https://media.licdn.com/dms/image/C560BAQGVi9eAHgWxFw/company-logo_100_100/0/1673448029676?e=2147483647&v=beta&t=NG6ttckXvnS2DX3abTfVACRY2E9Q1EcryNaJLRbE9OE", + "grade": null, + "activities_and_societies": null + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": { + "day": 31, + "month": 12, + "year": 2015 + }, + "field_of_study": "School of Software Development", + "degree_name": null, + "school": "Galvanize Inc", + "school_linkedin_profile_url": "https://www.linkedin.com/school/galvanize-it/", + "school_facebook_profile_url": null, + "description": "rails, ruby, rspec, capybara, bootstrap, css, html, api integration, Jquery, Javascript", + "logo_url": "https://media.licdn.com/dms/image/C560BAQFKNxOZ4X0g8Q/company-logo_100_100/0/1670610916338?e=2147483647&v=beta&t=t7ImfhmsuIJ7HJGHEbPJ2suxdslKhzp9v-5h9_G4sWE", + "grade": null, + "activities_and_societies": null + } + ], + "languages": [ + "English", + "Spanish" + ], + "accomplishment_organisations": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "org_name": "Microsoft", + "title": "Software Developer", + "description": null + } + ], + "accomplishment_publications": [ + { + "name": "Nobel Peace Prize", + "publisher": "Acme Corp", + "published_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "url": "https://example.com" + } + ], + "accomplishment_honors_awards": [ + { + "title": "Nobel Peace Prize", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n " + } + ], + "accomplishment_patents": [ + { + "title": "The art of war", + "issuer": "Acme Corp", + "issued_on": { + "day": 1, + "month": 1, + "year": 1970 + }, + "description": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit\n ", + "application_number": "123", + "patent_number": "123", + "url": null + } + ], + "accomplishment_courses": [ + { + "name": "The course about ABCs", + "number": "123" + } + ], + "accomplishment_projects": [ + { + "starts_at": { + "day": 1, + "month": 3, + "year": 2015 + }, + "ends_at": null, + "title": "gMessenger", + "description": "gMessenger was built using Ruby on Rails, and the Bootstrap HTML, CSS, and JavaScript framework. It uses a Websocket-Rails integration to post a user's message content to the page in real time, with no page refresh required. gMessenger also includes custom authentication with three different permissions levels.", + "url": "http://gmessenger.herokuapp.com/" + }, + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2015 + }, + "ends_at": null, + "title": "Taskly", + "description": "A task and project management responsive web app utilizing Ruby on Rails - CSS and HTML", + "url": "https://hidden-coast-7204.herokuapp.com/" + } + ], + "accomplishment_test_scores": [ + { + "name": "CS1101S", + "score": "A", + "date_on": { + "day": 1, + "month": 1, + "year": 2010 + }, + "description": "Nailed it without studying." + } + ], + "volunteer_work": [ + { + "starts_at": { + "day": 1, + "month": 1, + "year": 2012 + }, + "ends_at": { + "day": 1, + "month": 8, + "year": 2016 + }, + "title": "Surveyor", + "cause": "To help the world", + "company": "Microsoft", + "company_linkedin_profile_url": "https://www.linkedin.com/company/microsoft", + "description": null, + "logo_url": null + } + ], + "certifications": [ + { + "starts_at": null, + "ends_at": null, + "name": "SAFe Agile Framework Practitioner - ( Scrum, XP, and Lean Practices in the SAFe Enterprise)", + "license_number": null, + "display_source": null, + "authority": "Scaled Agile, Inc.", + "url": null + }, + { + "starts_at": null, + "ends_at": null, + "name": "SCRUM Alliance Certified Product Owner", + "license_number": null, + "display_source": null, + "authority": "Scrum Alliance", + "url": null + } + ], + "connections": 500, + "people_also_viewed": [ + { + "link": "https://www.linkedin.com/in/johndoe", + "name": "John Doe", + "summary": "Software Engineer at Google", + "location": "Singapore" + } + ], + "recommendations": [ + "Rebecca Canfield\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John Marty is a genius at his craft. He is skilled in the art of making people feel empowered to seek out roles that they are qualified for, ask for salaries that they deserve, and creates a kind of pay it forward lifestyle. John helps you to get to places that you only thought were possible for other people. Anyone that is fortunate enough to learn from John should consider themselves extremely lucky. I know I do. ", + "Zoe Sanoff\n\n \n \n \n\n\n\n \n \n \n \n \n\n \n John is so focused on helping guide you through an interview process not just for Amazon but on interviewing in general. I've generally done well at interviewing, my skills are top notch now. John is so focused on on his clients and really goes above and beyond. John is genuine, knowledgeable, well spoken and non-judgemental. He is so encouraging, so positive and really easy to talk to. Thank you John!" + ], + "activities": [ + { + "title": "Yesterday I toured a $1.2M property in California that has a large 13K sq ft lot with two homes on it. After 5 minutes of being on-site I…", + "link": "https://www.linkedin.com/posts/johnrmarty_financialfreedom-realestate-technology-activity-6940294635743301632-rsLo", + "activity_status": "Shared by John Marty" + } + ], + "similarly_named_profiles": [ + { + "name": "John Martinez", + "link": "https://www.linkedin.com/in/john-martinez-90384a229", + "summary": "Owner of Fight or Flight Medical Consultants, LLC , Owner Marty’s Hardwood Works", + "location": "San Antonio, TX" + }, + { + "name": "John Marty", + "link": "https://www.linkedin.com/in/senatormarty", + "summary": null, + "location": "St Paul, MN" + } + ], + "articles": [ + { + "title": "Manufacturing opportunity", + "link": "https://www.linkedin.com/pulse/manufacturing-opportunity-bill-gates/", + "published_date": { + "day": 27, + "month": 11, + "year": 2019 + }, + "author": "Bill Gates", + "image_url": "https://media-exp1.licdn.com/dms/image/C4E12AQFftuPi0UiqWA/article-cover_image-shrink_720_1280/0/1574801149114?e=1640822400&v=beta&t=ZAe3ERmQCM8QHGmRPS2LJ-C76GD5PR7FBHMVL4Z6iVg" + } + ], + "groups": [ + { + "profile_pic_url": "https://media-exp1.licdn.com/dms/image/C4D07AQG9IK9V0pk3mQ/group-logo_image-shrink_92x92/0/1631371531293?e=1642060800&v=beta&t=UK1tfIppWa-Nx7k9whmm5f9XdZoBdJhApf9N3ke3204", + "name": "Hadoop Users", + "url": "https://www.linkedin.com/groups/988957" + } + ] + }, + "last_updated": "2023-10-26T11:34:30Z" + } + ], + "next_page": null, + "total_result_count": 1 + } + }, + "CreditBalance": { + "type": "object", + "properties": { + "credit_balance": { + "type": "integer", + "description": "Your current credit(s)" + } + }, + "example": { + "credit_balance": 100000 + } + }, + "DisposableEmail": { + "type": "object", + "properties": { + "is_disposable_email": { + "type": "boolean", + "description": "Returns a boolean value of the disposable nature of the given email address" + }, + "is_free_email": { + "type": "boolean", + "description": "Returns a boolean value of the free status of the given email address" + } + }, + "example": { + "is_disposable_email": null, + "is_free_email": null + } + }, + "PersonalContactNumbers": { + "type": "object", + "properties": { + "numbers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of contact numbers" + } + }, + "example": { + "numbers": [ + "+1123123123" + ] + } + }, + "PDLEmailResult": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of personal emails" + }, + "invalid_emails": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of invalid personal emails" + } + }, + "example": { + "emails": [ + "random@gmail.com", + "random2@yahoo.com" + ], + "invalid_emails": [ + "random3@gmail.com" + ] + } + } + }, + "securitySchemes": { + "BearerAuth": { + "type": "http", + "scheme": "bearer" + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" +} \ No newline at end of file diff --git a/license b/license new file mode 100644 index 000000000..bfa02ec5a --- /dev/null +++ b/license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Travis Fischer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/media/agentic-header.jpg b/media/agentic-header.jpg new file mode 100644 index 000000000..f3cb5a5b9 Binary files /dev/null and b/media/agentic-header.jpg differ diff --git a/package.json b/package.json new file mode 100644 index 000000000..2cc002408 --- /dev/null +++ b/package.json @@ -0,0 +1,179 @@ +{ + "name": "@agentic/stdlib", + "private": true, + "version": "0.1.0", + "description": "TODO", + "author": "Travis Fischer ", + "license": "MIT", + "repository": { + "type": "git", + "url": "transitive-bullshit/agentic" + }, + "packageManager": "pnpm@9.1.4", + "engines": { + "node": ">=18" + }, + "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" + }, + "./ai-sdk": { + "types": "./dist/sdks/ai-sdk.d.ts", + "import": "./dist/sdks/ai-sdk.js", + "default": "./dist/sdks/ai-sdk.js" + }, + "./dexter": { + "types": "./dist/sdks/dexter.d.ts", + "import": "./dist/sdks/dexter.js", + "default": "./dist/sdks/dexter.js" + }, + "./genkit": { + "types": "./dist/sdks/genkit.d.ts", + "import": "./dist/sdks/genkit.js", + "default": "./dist/sdks/genkit.js" + }, + "./langchain": { + "types": "./dist/sdks/langchain.d.ts", + "import": "./dist/sdks/langchain.js", + "default": "./dist/sdks/langchain.js" + }, + "./llamaindex": { + "types": "./dist/sdks/llamaindex.d.ts", + "import": "./dist/sdks/llamaindex.js", + "default": "./dist/sdks/llamaindex.js" + }, + "./calculator": { + "types": "./dist/tools/calculator.d.ts", + "import": "./dist/tools/calculator.js", + "default": "./dist/tools/calculator.js" + }, + "./e2b": { + "types": "./dist/tools/e2b.d.ts", + "import": "./dist/tools/e2b.js", + "default": "./dist/tools/e2b.js" + }, + "./twitter": { + "types": "./dist/services/twitter/index.d.ts", + "import": "./dist/services/twitter/index.js", + "default": "./dist/services/twitter/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "preinstall": "npx only-allow pnpm", + "build": "tsup", + "clean": "del dist", + "prebuild": "run-s clean", + "predev": "run-s clean", + "pretest": "run-s build", + "prepare": "husky", + "precommit": "lint-staged", + "test": "run-s test:*", + "test:format": "prettier --check \"**/*.{js,ts,tsx}\"", + "test:lint": "eslint .", + "test:typecheck": "tsc --noEmit", + "test:unit": "vitest run" + }, + "dependencies": { + "@nangohq/node": "^0.39.33", + "dedent": "^1.5.3", + "delay": "^6.0.0", + "hash-object": "^5.0.1", + "is-relative-url": "^4.0.0", + "jsonrepair": "^3.6.1", + "ky": "^1.2.4", + "normalize-url": "^8.0.1", + "p-map": "^7.0.2", + "p-throttle": "^6.1.0", + "quick-lru": "^7.0.0", + "type-fest": "^4.19.0", + "zod": "^3.23.3", + "zod-to-json-schema": "^3.23.0" + }, + "devDependencies": { + "@browserbasehq/sdk": "^1.2.1", + "@dexaai/dexter": "^2.0.3", + "@e2b/code-interpreter": "^0.0.7", + "@fisch0920/eslint-config": "^1.3.3", + "@genkit-ai/ai": "^0.5.2", + "@instructor-ai/instructor": "^1.3.0", + "@langchain/core": "^0.2.6", + "@total-typescript/ts-reset": "^0.5.1", + "@types/node": "^20.14.2", + "ai": "^3.1.30", + "del-cli": "^5.1.0", + "dotenv": "^16.4.5", + "eslint": "^8.57.0", + "expr-eval": "^2.0.2", + "husky": "^9.0.11", + "lint-staged": "^15.2.5", + "llamaindex": "^0.3.16", + "np": "^10.0.5", + "npm-run-all2": "^6.2.0", + "only-allow": "^1.2.1", + "openai-fetch": "^2.0.3", + "prettier": "^3.3.1", + "restore-cursor": "^5.0.0", + "ts-node": "^10.9.2", + "tsup": "^8.1.0", + "tsx": "^4.13.0", + "twitter-api-sdk": "^1.2.1", + "typescript": "^5.4.5", + "vitest": "2.0.0-beta.3" + }, + "peerDependencies": { + "@dexaai/dexter": "^2.0.3", + "@e2b/code-interpreter": "^0.0.7", + "@genkit-ai/ai": "^0.5.2", + "@langchain/core": "^0.2.6", + "ai": "^3.1.30", + "expr-eval": "^2.0.2", + "llamaindex": "^0.3.16", + "twitter-api-sdk": "^1.2.1" + }, + "peerDependenciesMeta": { + "@dexaai/dexter": { + "optional": true + }, + "@e2b/code-interpreter": { + "optional": true + }, + "@genkit-ai/ai": { + "optional": true + }, + "@langchain/core": { + "optional": true + }, + "ai": { + "optional": true + }, + "expr-eval": { + "optional": true + }, + "llamaindex": { + "optional": true + }, + "twitter-api-sdk": { + "optional": true + } + }, + "lint-staged": { + "*.{ts,tsx}": [ + "eslint --fix", + "prettier --ignore-unknown --write" + ] + }, + "pnpm": { + "overrides": { + "esbuild": "~0.21.4" + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 000000000..78dfb98a1 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,12675 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + esbuild: ~0.21.4 + +importers: + + .: + dependencies: + '@nangohq/node': + specifier: ^0.39.33 + version: 0.39.33 + dedent: + specifier: ^1.5.3 + version: 1.5.3 + delay: + specifier: ^6.0.0 + version: 6.0.0 + hash-object: + specifier: ^5.0.1 + version: 5.0.1 + is-relative-url: + specifier: ^4.0.0 + version: 4.0.0 + jsonrepair: + specifier: ^3.6.1 + version: 3.8.0 + ky: + specifier: ^1.2.4 + version: 1.3.0 + normalize-url: + specifier: ^8.0.1 + version: 8.0.1 + p-map: + specifier: ^7.0.2 + version: 7.0.2 + p-throttle: + specifier: ^6.1.0 + version: 6.1.0 + quick-lru: + specifier: ^7.0.0 + version: 7.0.0 + type-fest: + specifier: ^4.19.0 + version: 4.19.0 + zod: + specifier: ^3.23.3 + version: 3.23.8 + zod-to-json-schema: + specifier: ^3.23.0 + version: 3.23.0(zod@3.23.8) + devDependencies: + '@browserbasehq/sdk': + specifier: ^1.2.1 + version: 1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) + '@dexaai/dexter': + specifier: ^2.0.3 + version: 2.1.0 + '@e2b/code-interpreter': + specifier: ^0.0.7 + version: 0.0.7(bufferutil@4.0.8)(utf-8-validate@6.0.4) + '@fisch0920/eslint-config': + specifier: ^1.3.3 + version: 1.3.3(eslint@8.57.0)(typescript@5.4.5) + '@genkit-ai/ai': + specifier: ^0.5.2 + version: 0.5.2 + '@instructor-ai/instructor': + specifier: ^1.3.0 + version: 1.3.0(openai@4.49.0(encoding@0.1.13))(zod@3.23.8) + '@langchain/core': + specifier: ^0.2.6 + version: 0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + '@total-typescript/ts-reset': + specifier: ^0.5.1 + version: 0.5.1 + '@types/node': + specifier: ^20.14.2 + version: 20.14.2 + ai: + specifier: ^3.1.30 + version: 3.1.30(openai@4.49.0(encoding@0.1.13))(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.18)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8) + del-cli: + specifier: ^5.1.0 + version: 5.1.0 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + eslint: + specifier: ^8.57.0 + version: 8.57.0 + expr-eval: + specifier: ^2.0.2 + version: 2.0.2 + husky: + specifier: ^9.0.11 + version: 9.0.11 + lint-staged: + specifier: ^15.2.5 + version: 15.2.5 + llamaindex: + specifier: ^0.3.16 + version: 0.3.16(@aws-sdk/credential-providers@3.592.0)(@notionhq/client@2.2.15(encoding@0.1.13))(bufferutil@4.0.8)(encoding@0.1.13)(node-fetch@3.3.2)(socks@2.8.3)(typescript@5.4.5)(utf-8-validate@6.0.4) + np: + specifier: ^10.0.5 + version: 10.0.5(typescript@5.4.5) + npm-run-all2: + specifier: ^6.2.0 + version: 6.2.0 + only-allow: + specifier: ^1.2.1 + version: 1.2.1 + openai-fetch: + specifier: ^2.0.3 + version: 2.0.3 + prettier: + specifier: ^3.3.1 + version: 3.3.1 + restore-cursor: + specifier: ^5.0.0 + version: 5.0.0 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) + tsup: + specifier: ^8.1.0 + version: 8.1.0(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5) + tsx: + specifier: ^4.13.0 + version: 4.13.0 + twitter-api-sdk: + specifier: ^1.2.1 + version: 1.2.1(encoding@0.1.13) + typescript: + specifier: ^5.4.5 + version: 5.4.5 + vitest: + specifier: 2.0.0-beta.3 + version: 2.0.0-beta.3(@types/node@20.14.2) + + examples: + dependencies: + '@agentic/stdlib': + specifier: workspace:* + version: link:.. + '@ai-sdk/openai': + specifier: ^0.0.24 + version: 0.0.24(zod@3.23.8) + '@dexaai/dexter': + specifier: ^2.1.0 + version: 2.1.0 + '@genkit-ai/ai': + specifier: ^0.5.2 + version: 0.5.2 + '@genkit-ai/core': + specifier: ^0.5.2 + version: 0.5.2 + '@instructor-ai/instructor': + specifier: ^1.3.0 + version: 1.3.0(openai@4.49.0(encoding@0.1.13))(zod@3.23.8) + '@langchain/core': + specifier: ^0.2.6 + version: 0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + '@langchain/openai': + specifier: ^0.1.2 + version: 0.1.2(encoding@0.1.13)(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))) + ai: + specifier: ^3.1.30 + version: 3.1.30(openai@4.49.0(encoding@0.1.13))(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.18)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8) + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + genkitx-openai: + specifier: ^0.10.0 + version: 0.10.0(@genkit-ai/ai@0.5.2)(@genkit-ai/core@0.5.2)(encoding@0.1.13) + langchain: + specifier: ^0.2.5 + version: 0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) + llamaindex: + specifier: ^0.3.16 + version: 0.3.16(@aws-sdk/credential-providers@3.592.0)(@notionhq/client@2.2.15(encoding@0.1.13))(bufferutil@4.0.8)(encoding@0.1.13)(node-fetch@3.3.2)(socks@2.8.3)(typescript@5.4.5)(utf-8-validate@6.0.4) + openai: + specifier: ^4.49.0 + version: 4.49.0(encoding@0.1.13) + zod: + specifier: ^3.23.8 + version: 3.23.8 + +packages: + + '@ai-sdk/openai@0.0.24': + resolution: {integrity: sha512-uLqisEHe6Xp45KXnxdTnwdq8UBJwU345GUdoR4QD/yhLWnoJZf9YSltIyWxaHIcrm4acLCxD5xoy+4L9jwXbBQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/provider-utils@0.0.13': + resolution: {integrity: sha512-cB2dPm9flj+yin5sjBLFcXdW8sZtAXLE/OLKgz9uHpHM55s7mnwZrDGfO6ot/ukHTxDDJunZLW7qSjgK/u0F1g==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/provider@0.0.10': + resolution: {integrity: sha512-NzkrtREQpHID1cTqY/C4CI30PVOaXWKYytDR2EcytmFgnP7Z6+CrGIA/YCnNhYAuUm6Nx+nGpRL/Hmyrv7NYzg==} + engines: {node: '>=18'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@anthropic-ai/sdk@0.21.1': + resolution: {integrity: sha512-fqdt74RTdplnaFOYhwNjjK/Ec09Dqv9ekYr7PuC6GdhV1RWkziqbpJBewn42CYYqCr92JeX6g+IXVgXmq9l7XQ==} + + '@aws-crypto/ie11-detection@3.0.0': + resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} + + '@aws-crypto/sha256-browser@3.0.0': + resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} + + '@aws-crypto/sha256-js@3.0.0': + resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@3.0.0': + resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} + + '@aws-crypto/util@3.0.0': + resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-cognito-identity@3.592.0': + resolution: {integrity: sha512-mk3JOBsk5hlrLTZFuoGIhFKFflOdxqMKmOgyUFs5+gBLuH0/lN3wNWJxk+BiY1nHzkxhBND1hDHc5dvZRugBJA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sso-oidc@3.592.0': + resolution: {integrity: sha512-11Zvm8nm0s/UF3XCjzFRpQU+8FFVW5rcr3BHfnH6xAe5JEoN6bJN/n+wOfnElnjek+90hh+Qc7s141AMrCjiiw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sso@3.592.0': + resolution: {integrity: sha512-w+SuW47jQqvOC7fonyjFjsOh3yjqJ+VpWdVrmrl0E/KryBE7ho/Wn991Buf/EiHHeJikoWgHsAIPkBH29+ntdA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sts@3.592.0': + resolution: {integrity: sha512-KUrOdszZfcrlpKr4dpdkGibZ/qq3Lnfu1rjv1U+V1QJQ9OuMo9J3sDWpWV9tigNqY0aGllarWH5cJbz9868W/w==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/core@3.592.0': + resolution: {integrity: sha512-gLPMXR/HXDP+9gXAt58t7gaMTvRts9i6Q7NMISpkGF54wehskl5WGrbdtHJFylrlJ5BQo3XVY6i661o+EuR1wg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-cognito-identity@3.592.0': + resolution: {integrity: sha512-uHiMPCkFhZOhlSfKgVqPhMdruiOuVkLUn07gQqvxHYhFKkEOPV+6BZbPKBwBTXr8TIREztQzCMPswa5pGk2zbQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-env@3.587.0': + resolution: {integrity: sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-http@3.587.0': + resolution: {integrity: sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-ini@3.592.0': + resolution: {integrity: sha512-3kG6ngCIOPbLJZZ3RV+NsU7HVK6vX1+1DrPJKj9fVlPYn7IXsk8NAaUT5885yC7+jKizjv0cWLrLKvAJV5gfUA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.592.0 + + '@aws-sdk/credential-provider-node@3.592.0': + resolution: {integrity: sha512-BguihBGTrEjVBQ07hm+ZsO29eNJaxwBwUZMftgGAm2XcMIEClNPfm5hydxu2BmA4ouIJQJ6nG8pNYghEumM+Aw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-process@3.587.0': + resolution: {integrity: sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-sso@3.592.0': + resolution: {integrity: sha512-fYFzAdDHKHvhtufPPtrLdSv8lO6GuW3em6n3erM5uFdpGytNpjXvr3XGokIsuXcNkETAY/Xihg+G9ksNE8WJxQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.587.0': + resolution: {integrity: sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.587.0 + + '@aws-sdk/credential-providers@3.592.0': + resolution: {integrity: sha512-fHAt001Aemiy9p8VtLKWiPQ36g1YgiLC1pm31W+WmKxU663dbt2yYTIAyVOB1nQC7HrVCOZEg2FU0TtuZt/wXQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-host-header@3.577.0': + resolution: {integrity: sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-logger@3.577.0': + resolution: {integrity: sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.577.0': + resolution: {integrity: sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-user-agent@3.587.0': + resolution: {integrity: sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/region-config-resolver@3.587.0': + resolution: {integrity: sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/token-providers@3.587.0': + resolution: {integrity: sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sso-oidc': ^3.587.0 + + '@aws-sdk/types@3.577.0': + resolution: {integrity: sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-endpoints@3.587.0': + resolution: {integrity: sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-locate-window@3.568.0': + resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-user-agent-browser@3.577.0': + resolution: {integrity: sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==} + + '@aws-sdk/util-user-agent-node@3.587.0': + resolution: {integrity: sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + + '@babel/code-frame@7.24.6': + resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.6': + resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.6': + resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.24.6': + resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + + '@browserbasehq/sdk@1.2.1': + resolution: {integrity: sha512-2fEyseWDGQnhJzoUuyUzXXVykG2cfgEnSpzm1iYVwfgpdqGbiEsMbcw6/HfUUXWSMrm/GZEnlHHqVIRa92x2Ng==} + + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + + '@datastax/astra-db-ts@1.2.1': + resolution: {integrity: sha512-d0rptvx8EE8o4BqDvUaF84K6zsy5un0Q6T+UEHpnKzeTH9YK2DvgRmzbVNJOuqDg+iVrL7+xhP1MGOhWQgKFMQ==} + engines: {node: '>=14.0.0'} + + '@dexaai/dexter@2.1.0': + resolution: {integrity: sha512-3vhTSlpoW0DhQy2DaI3ocoZdw8RxBmsSysrGT0yZP6ZT2zHXlNVzYMj/ffbHmcR2y+VCkESKDJ/Vde4Ytf4agQ==} + engines: {node: '>= 18'} + + '@e2b/code-interpreter@0.0.7': + resolution: {integrity: sha512-e8nAY4zXU2b9nKthqq/pCPlTVD7f01dtzCtvabWmhlx7Wq+AUln14Q1Wf+uRVJXHkwS9BDv2CupdZpUChsjoCA==} + engines: {node: '>=18'} + + '@esbuild/aix-ppc64@0.21.4': + resolution: {integrity: sha512-Zrm+B33R4LWPLjDEVnEqt2+SLTATlru1q/xYKVn8oVTbiRBGmK2VIMoIYGJDGyftnGaC788IuzGFAlb7IQ0Y8A==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.4': + resolution: {integrity: sha512-fYFnz+ObClJ3dNiITySBUx+oNalYUT18/AryMxfovLkYWbutXsct3Wz2ZWAcGGppp+RVVX5FiXeLYGi97umisA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.4': + resolution: {integrity: sha512-E7H/yTd8kGQfY4z9t3nRPk/hrhaCajfA3YSQSBrst8B+3uTcgsi8N+ZWYCaeIDsiVs6m65JPCaQN/DxBRclF3A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.4': + resolution: {integrity: sha512-mDqmlge3hFbEPbCWxp4fM6hqq7aZfLEHZAKGP9viq9wMUBVQx202aDIfc3l+d2cKhUJM741VrCXEzRFhPDKH3Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.4': + resolution: {integrity: sha512-72eaIrDZDSiWqpmCzVaBD58c8ea8cw/U0fq/PPOTqE3c53D0xVMRt2ooIABZ6/wj99Y+h4ksT/+I+srCDLU9TA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.4': + resolution: {integrity: sha512-uBsuwRMehGmw1JC7Vecu/upOjTsMhgahmDkWhGLWxIgUn2x/Y4tIwUZngsmVb6XyPSTXJYS4YiASKPcm9Zitag==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.4': + resolution: {integrity: sha512-8JfuSC6YMSAEIZIWNL3GtdUT5NhUA/CMUCpZdDRolUXNAXEE/Vbpe6qlGLpfThtY5NwXq8Hi4nJy4YfPh+TwAg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.4': + resolution: {integrity: sha512-8d9y9eQhxv4ef7JmXny7591P/PYsDFc4+STaxC1GBv0tMyCdyWfXu2jBuqRsyhY8uL2HU8uPyscgE2KxCY9imQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.4': + resolution: {integrity: sha512-/GLD2orjNU50v9PcxNpYZi+y8dJ7e7/LhQukN3S4jNDXCKkyyiyAz9zDw3siZ7Eh1tRcnCHAo/WcqKMzmi4eMQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.4': + resolution: {integrity: sha512-2rqFFefpYmpMs+FWjkzSgXg5vViocqpq5a1PSRgT0AvSgxoXmGF17qfGAzKedg6wAwyM7UltrKVo9kxaJLMF/g==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.4': + resolution: {integrity: sha512-pNftBl7m/tFG3t2m/tSjuYeWIffzwAZT9m08+9DPLizxVOsUl8DdFzn9HvJrTQwe3wvJnwTdl92AonY36w/25g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.4': + resolution: {integrity: sha512-cSD2gzCK5LuVX+hszzXQzlWya6c7hilO71L9h4KHwqI4qeqZ57bAtkgcC2YioXjsbfAv4lPn3qe3b00Zt+jIfQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.4': + resolution: {integrity: sha512-qtzAd3BJh7UdbiXCrg6npWLYU0YpufsV9XlufKhMhYMJGJCdfX/G6+PNd0+v877X1JG5VmjBLUiFB0o8EUSicA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.4': + resolution: {integrity: sha512-yB8AYzOTaL0D5+2a4xEy7OVvbcypvDR05MsB/VVPVA7nL4hc5w5Dyd/ddnayStDgJE59fAgNEOdLhBxjfx5+dg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.4': + resolution: {integrity: sha512-Y5AgOuVzPjQdgU59ramLoqSSiXddu7F3F+LI5hYy/d1UHN7K5oLzYBDZe23QmQJ9PIVUXwOdKJ/jZahPdxzm9w==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.4': + resolution: {integrity: sha512-Iqc/l/FFwtt8FoTK9riYv9zQNms7B8u+vAI/rxKuN10HgQIXaPzKZc479lZ0x6+vKVQbu55GdpYpeNWzjOhgbA==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.4': + resolution: {integrity: sha512-Td9jv782UMAFsuLZINfUpoF5mZIbAj+jv1YVtE58rFtfvoKRiKSkRGQfHTgKamLVT/fO7203bHa3wU122V/Bdg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.4': + resolution: {integrity: sha512-Awn38oSXxsPMQxaV0Ipb7W/gxZtk5Tx3+W+rAPdZkyEhQ6968r9NvtkjhnhbEgWXYbgV+JEONJ6PcdBS+nlcpA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.4': + resolution: {integrity: sha512-IsUmQeCY0aU374R82fxIPu6vkOybWIMc3hVGZ3ChRwL9hA1TwY+tS0lgFWV5+F1+1ssuvvXt3HFqe8roCip8Hg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.4': + resolution: {integrity: sha512-hsKhgZ4teLUaDA6FG/QIu2q0rI6I36tZVfM4DBZv3BG0mkMIdEnMbhc4xwLvLJSS22uWmaVkFkqWgIS0gPIm+A==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.4': + resolution: {integrity: sha512-UUfMgMoXPoA/bvGUNfUBFLCh0gt9dxZYIx9W4rfJr7+hKe5jxxHmfOK8YSH4qsHLLN4Ck8JZ+v7Q5fIm1huErg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.4': + resolution: {integrity: sha512-yIxbspZb5kGCAHWm8dexALQ9en1IYDfErzjSEq1KzXFniHv019VT3mNtTK7t8qdy4TwT6QYHI9sEZabONHg+aw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.4': + resolution: {integrity: sha512-sywLRD3UK/qRJt0oBwdpYLBibk7KiRfbswmWRDabuncQYSlf8aLEEUor/oP6KRz8KEG+HoiVLBhPRD5JWjS8Sg==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.10.0': + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@fastify/deepmerge@1.3.0': + resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} + + '@fisch0920/eslint-config@1.3.3': + resolution: {integrity: sha512-BhjKXkVVSmdj1M60rAbJMaM1yFUFMlOeaWNmxOL4SNgLF2TR+LFNlcUkVH7bb2A5sq4BEc+2POBCCDXwKOlbUg==} + engines: {node: '>=18'} + peerDependencies: + typescript: ^5.0.0 + + '@genkit-ai/ai@0.5.2': + resolution: {integrity: sha512-VuXSTlNGhUSjU0SrFq5sREj99LRFInxPqMWOUMdaM48Y1RKtZLs+TuimW7Y5NJ2/SS0u1fq3cbD3YE0j+GAk/g==} + + '@genkit-ai/core@0.5.2': + resolution: {integrity: sha512-feAhel5qEdbfPTnBxCVHzfHLCV6WWVN0J5x2Av4AJMl3M04fQYhXmmPqdgTaiaEZ0nUZ1jSxpnn5aTk2U4VV/Q==} + + '@google-cloud/vertexai@1.2.0': + resolution: {integrity: sha512-EH0dnoMRIBQzJEEOUWN03eWPSdLBFdsZA/am3eU+qYrnNyY9okUueOajZd79U48KwgFbqoFrCA9yHQ30DgfD8Q==} + engines: {node: '>=18.0.0'} + + '@google/generative-ai@0.12.0': + resolution: {integrity: sha512-krWjurjEUHSFhCX4lGHMOhbnpBfYZGU31mpHpPBQwcfWm0T+/+wxC4UCAJfkxxc3/HvGJVG8r4AqrffaeDHDlA==} + engines: {node: '>=18.0.0'} + + '@grpc/grpc-js@1.10.8': + resolution: {integrity: sha512-vYVqYzHicDqyKB+NQhAc54I1QWCBLCrYG6unqOIcBTHx+7x8C9lcoLj3KVJXs2VB4lUbpWY+Kk9NipcbXYWmvg==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.13': + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} + engines: {node: '>=6'} + hasBin: true + + '@huggingface/inference@2.7.0': + resolution: {integrity: sha512-u7Fn637Q3f7nUB1tajM4CgzhvoFQkOQr5W5Fm+2wT9ETgGoLBh25BLlYPTJRjAd2WY01s71v0lqAwNvHHCc3mg==} + engines: {node: '>=18'} + + '@huggingface/jinja@0.2.2': + resolution: {integrity: sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==} + engines: {node: '>=18'} + + '@huggingface/tasks@0.10.9': + resolution: {integrity: sha512-KdGnpw7sTLgr9nUwH6NrMHi/6/yBe5HdeXeKWauajseKZXwyrTYwNYIzMnh8/hE7Qa2UnseAdFMpCqe54vGd4A==} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + + '@inquirer/figures@1.0.3': + resolution: {integrity: sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==} + engines: {node: '>=18'} + + '@instructor-ai/instructor@1.3.0': + resolution: {integrity: sha512-nzadwGSkiVLcK3NAVeinPUrA6KwV5mkyWDGTXLMR8eXKbzlUwmLwQ+PTabPn2hCR+LtQ+7MvtuoR2acSTXgy6Q==} + peerDependencies: + openai: '>=4.28.0' + zod: '>=3.22.4' + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + + '@langchain/core@0.2.6': + resolution: {integrity: sha512-YB9F0vdi/PcgBLSKtDwQ3gV6w4xVfk4ph0U43Okz2dAapKfBkVVB0rzr/afYUt/WHs864MuaO8uLN64egSDtIA==} + engines: {node: '>=18'} + + '@langchain/openai@0.1.2': + resolution: {integrity: sha512-giydNZyEzUBrjZrmQRfnc2SI0+TyAjaVMd8wMKq8O4X/Y3BJd0LFlfD+3MM6Lyu/qaphZ1Ycfr7XR5hY0EcGqQ==} + engines: {node: '>=18'} + + '@langchain/textsplitters@0.0.3': + resolution: {integrity: sha512-cXWgKE3sdWLSqAa8ykbCcUsUF1Kyr5J3HOWYGuobhPEycXW4WI++d5DhzdpL238mzoEXTi90VqfSCra37l5YqA==} + engines: {node: '>=18'} + + '@ljharb/through@2.3.13': + resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} + engines: {node: '>= 0.4'} + + '@llamaindex/cloud@0.0.5': + resolution: {integrity: sha512-8HBSiAZkmX1RvpEM2czEVKqMUCKk7uvMSiDpMGWlEj3MUKBYCh+r8E2TtVhZfU4TunEI7nJRMcVBfXDyFz6Lpw==} + peerDependencies: + node-fetch: ^3.3.2 + peerDependenciesMeta: + node-fetch: + optional: true + + '@llamaindex/env@0.1.3': + resolution: {integrity: sha512-PM9cZ8x6jjdugWG30vBxb9Ju2LFmGY0l0pN7AUXXKULFNytQddx96xHh07pV/juf/WqjhFp75FVAykAlqO/qzQ==} + peerDependencies: + '@aws-crypto/sha256-js': ^5.2.0 + pathe: ^1.1.2 + peerDependenciesMeta: + '@aws-crypto/sha256-js': + optional: true + pathe: + optional: true + + '@mistralai/mistralai@0.4.0': + resolution: {integrity: sha512-KmFzNro1RKxIFh19J3osmUQhucefBBauMXN5fa9doG6dT9OHR/moBvvn+riVlR7c0AVfuxO8Dfa03AyLYYzbyg==} + + '@mongodb-js/saslprep@1.1.7': + resolution: {integrity: sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==} + + '@nangohq/node@0.39.33': + resolution: {integrity: sha512-TkwH6pRsTT4ORZAc/ZEjnI8fHXJx068sXFa1X0oUwclZiSXP50Dd7z6vdHiEYGjsi+k7BGYOlQTLCQqJsMHGrg==} + engines: {node: '>=18.0'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@notionhq/client@2.2.15': + resolution: {integrity: sha512-XhdSY/4B1D34tSco/GION+23GMjaS9S2zszcqYkMHo8RcWInymF6L1x+Gk7EmHdrSxNFva2WM8orhC4BwQCwgw==} + engines: {node: '>=12'} + + '@opentelemetry/api-logs@0.49.1': + resolution: {integrity: sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.8.0': + resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/context-async-hooks@1.22.0': + resolution: {integrity: sha512-Nfdxyg8YtWqVWkyrCukkundAjPhUXi93JtVQmqDT1mZRVKqA7e2r7eJCrI+F651XUBMp0hsOJSGiFk3QSpaIJw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/context-async-hooks@1.25.0': + resolution: {integrity: sha512-sBW313mnMyFg0cp/40BRzrZBWG+581s2j5gIsa5fgGadswyILk4mNFATsqrCOpAx945RDuZ2B7ThQLgor9OpfA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.22.0': + resolution: {integrity: sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/core@1.25.0': + resolution: {integrity: sha512-n0B3s8rrqGrasTgNkXLKXzN0fXo+6IYP7M5b7AMsrZM33f/y6DS6kJ0Btd7SespASWq8bgL3taLo0oe0vB52IQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-trace-otlp-grpc@0.49.1': + resolution: {integrity: sha512-Zbd7f3zF7fI2587MVhBizaW21cO/SordyrZGtMtvhoxU6n4Qb02Gx71X4+PzXH620e0+JX+Pcr9bYb1HTeVyJA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-http@0.49.1': + resolution: {integrity: sha512-KOLtZfZvIrpGZLVvblKsiVQT7gQUZNKcUUH24Zz6Xbi7LJb9Vt6xtUZFYdR5IIjvt47PIqBKDWUQlU0o1wAsRw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.49.1': + resolution: {integrity: sha512-n8ON/c9pdMyYAfSFWKkgsPwjYoxnki+6Olzo+klKfW7KqLWoyEkryNkbcMIYnGGNXwdkMIrjoaP0VxXB26Oxcg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-zipkin@1.22.0': + resolution: {integrity: sha512-XcFs6rGvcTz0qW5uY7JZDYD0yNEXdekXAb6sFtnZgY/cHY6BQ09HMzOjv9SX+iaXplRDcHr1Gta7VQKM1XXM6g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation@0.49.1': + resolution: {integrity: sha512-0DLtWtaIppuNNRRllSD4bjU8ZIiLp1cDXvJEbp752/Zf+y3gaLNaoGRGIlX4UHhcsrmtL+P2qxi3Hodi8VuKiQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.49.1': + resolution: {integrity: sha512-z6sHliPqDgJU45kQatAettY9/eVF58qVPaTuejw9YWfSRqid9pXPYeegDCSdyS47KAUgAtm+nC28K3pfF27HWg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-grpc-exporter-base@0.49.1': + resolution: {integrity: sha512-DNDNUWmOqtKTFJAyOyHHKotVox0NQ/09ETX8fUOeEtyNVHoGekAVtBbvIA3AtK+JflP7LC0PTjlLfruPM3Wy6w==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-proto-exporter-base@0.49.1': + resolution: {integrity: sha512-x1qB4EUC7KikUl2iNuxCkV8yRzrSXSyj4itfpIO674H7dhI7Zv37SFaOJTDN+8Z/F50gF2ISFH9CWQ4KCtGm2A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-transformer@0.49.1': + resolution: {integrity: sha512-Z+koA4wp9L9e3jkFacyXTGphSWTbOKjwwXMpb0CxNb0kjTHGUxhYRN8GnkLFsFo5NbZPjP07hwAqeEG/uCratQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.9.0' + + '@opentelemetry/propagator-b3@1.22.0': + resolution: {integrity: sha512-qBItJm9ygg/jCB5rmivyGz1qmKZPsL/sX715JqPMFgq++Idm0x+N9sLQvWFHFt2+ZINnCSojw7FVBgFW6izcXA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/propagator-jaeger@1.22.0': + resolution: {integrity: sha512-pMLgst3QIwrUfepraH5WG7xfpJ8J3CrPKrtINK0t7kBkuu96rn+HDYQ8kt3+0FXvrZI8YJE77MCQwnJWXIrgpA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/resources@1.22.0': + resolution: {integrity: sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/resources@1.25.0': + resolution: {integrity: sha512-iHjydPMYJ+Li1auveJCq2rp5U2h6Mhq8BidiyE0jfVlDTFyR1ny8AfJHfmFzJ/RAM8vT8L7T21kcmGybxZC7lQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.49.1': + resolution: {integrity: sha512-gCzYWsJE0h+3cuh3/cK+9UwlVFyHvj3PReIOCDOmdeXOp90ZjKRoDOJBc3mvk1LL6wyl1RWIivR8Rg9OToyesw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.9.0' + '@opentelemetry/api-logs': '>=0.39.1' + + '@opentelemetry/sdk-metrics@1.22.0': + resolution: {integrity: sha512-k6iIx6H3TZ+BVMr2z8M16ri2OxWaljg5h8ihGJxi/KQWcjign6FEaEzuigXt5bK9wVEhqAcWLCfarSftaNWkkg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.9.0' + + '@opentelemetry/sdk-metrics@1.25.0': + resolution: {integrity: sha512-IF+Sv4VHgBr/BPMKabl+GouJIhEqAOexCHgXVTISdz3q9P9H/uA8ScCF+22gitQ69aFtESbdYOV+Fen5+avQng==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-node@0.49.1': + resolution: {integrity: sha512-feBIT85ndiSHXsQ2gfGpXC/sNeX4GCHLksC4A9s/bfpUbbgbCSl0RvzZlmEpCHarNrkZMwFRi4H0xFfgvJEjrg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.9.0' + + '@opentelemetry/sdk-trace-base@1.22.0': + resolution: {integrity: sha512-pfTuSIpCKONC6vkTpv6VmACxD+P1woZf4q0K46nSUvXFvOFqjBYKFaAMkKD3M1mlKUUh0Oajwj35qNjMl80m1Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/sdk-trace-base@1.25.0': + resolution: {integrity: sha512-6+g2fiRQUG39guCsKVeY8ToeuUf3YUnPkN6DXRA1qDmFLprlLvZm9cS6+chgbW70cZJ406FTtSCDnJwxDC5sGQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.22.0': + resolution: {integrity: sha512-gTGquNz7ue8uMeiWPwp3CU321OstQ84r7PCDtOaCicjbJxzvO8RZMlEC4geOipTeiF88kss5n6w+//A0MhP1lQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.9.0' + + '@opentelemetry/semantic-conventions@1.22.0': + resolution: {integrity: sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==} + engines: {node: '>=14'} + + '@opentelemetry/semantic-conventions@1.25.0': + resolution: {integrity: sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ==} + engines: {node: '>=14'} + + '@petamoriken/float16@3.8.7': + resolution: {integrity: sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==} + + '@pinecone-database/pinecone@2.2.2': + resolution: {integrity: sha512-gbe/4SowHc64pHIm0kBdgY9hVdzsQnnnpcWviwYMB33gOmsL8brvE8fUSpl1dLDvdyXzKcQkzdBsjCDlqgpdMA==} + engines: {node: '>=14.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.2.2': + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@puppeteer/browsers@2.2.3': + resolution: {integrity: sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==} + engines: {node: '>=18'} + hasBin: true + + '@qdrant/js-client-rest@1.9.0': + resolution: {integrity: sha512-YiX/IskbRCoAY2ujyPDI6FBcO0ygAS4pgkGaJ7DcrJFh4SZV2XHs+u0KM7mO72RWJn1eJQFF2PQwxG+401xxJg==} + engines: {node: '>=18.0.0', pnpm: '>=8'} + peerDependencies: + typescript: '>=4.7' + + '@qdrant/openapi-typescript-fetch@1.2.6': + resolution: {integrity: sha512-oQG/FejNpItrxRHoyctYvT3rwGZOnK4jr3JdppO/c78ktDvkWiPXPHNsrDf33K9sZdRb6PR7gi4noIapu5q4HA==} + engines: {node: '>=18.0.0', pnpm: '>=8'} + + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} + cpu: [x64] + os: [win32] + + '@rushstack/eslint-patch@1.10.3': + resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} + + '@samverschueren/stream-to-observable@0.3.1': + resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==} + engines: {node: '>=6'} + peerDependencies: + rxjs: '*' + zen-observable: '*' + peerDependenciesMeta: + rxjs: + optional: true + zen-observable: + optional: true + + '@sevinf/maybe@0.5.0': + resolution: {integrity: sha512-ARhyoYDnY1LES3vYI0fiG6e9esWfTNcXcO6+MPJJXcnyMV3bim4lnFt45VXouV7y82F4x3YH8nOQ6VztuvUiWg==} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinclair/typebox@0.29.6': + resolution: {integrity: sha512-aX5IFYWlMa7tQ8xZr3b2gtVReCvg7f3LEhjir/JAjX2bJCMVJA5tIPv30wTD4KDfcwMd7DDYY3hFDeGmOgtrZQ==} + + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + + '@smithy/abort-controller@3.0.0': + resolution: {integrity: sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==} + engines: {node: '>=16.0.0'} + + '@smithy/config-resolver@3.0.1': + resolution: {integrity: sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg==} + engines: {node: '>=16.0.0'} + + '@smithy/core@2.2.0': + resolution: {integrity: sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg==} + engines: {node: '>=16.0.0'} + + '@smithy/credential-provider-imds@3.1.0': + resolution: {integrity: sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q==} + engines: {node: '>=16.0.0'} + + '@smithy/fetch-http-handler@3.0.1': + resolution: {integrity: sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==} + + '@smithy/hash-node@3.0.0': + resolution: {integrity: sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==} + engines: {node: '>=16.0.0'} + + '@smithy/invalid-dependency@3.0.0': + resolution: {integrity: sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@3.0.0': + resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-content-length@3.0.0': + resolution: {integrity: sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-endpoint@3.0.1': + resolution: {integrity: sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-retry@3.0.3': + resolution: {integrity: sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-serde@3.0.0': + resolution: {integrity: sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-stack@3.0.0': + resolution: {integrity: sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==} + engines: {node: '>=16.0.0'} + + '@smithy/node-config-provider@3.1.0': + resolution: {integrity: sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q==} + engines: {node: '>=16.0.0'} + + '@smithy/node-http-handler@3.0.0': + resolution: {integrity: sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==} + engines: {node: '>=16.0.0'} + + '@smithy/property-provider@3.1.0': + resolution: {integrity: sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q==} + engines: {node: '>=16.0.0'} + + '@smithy/protocol-http@4.0.0': + resolution: {integrity: sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-builder@3.0.0': + resolution: {integrity: sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-parser@3.0.0': + resolution: {integrity: sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==} + engines: {node: '>=16.0.0'} + + '@smithy/service-error-classification@3.0.0': + resolution: {integrity: sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==} + engines: {node: '>=16.0.0'} + + '@smithy/shared-ini-file-loader@3.1.0': + resolution: {integrity: sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg==} + engines: {node: '>=16.0.0'} + + '@smithy/signature-v4@3.0.0': + resolution: {integrity: sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==} + engines: {node: '>=16.0.0'} + + '@smithy/smithy-client@3.1.1': + resolution: {integrity: sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA==} + engines: {node: '>=16.0.0'} + + '@smithy/types@3.0.0': + resolution: {integrity: sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==} + engines: {node: '>=16.0.0'} + + '@smithy/url-parser@3.0.0': + resolution: {integrity: sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==} + + '@smithy/util-base64@3.0.0': + resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-body-length-browser@3.0.0': + resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==} + + '@smithy/util-body-length-node@3.0.0': + resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@3.0.0': + resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-config-provider@3.0.0': + resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-defaults-mode-browser@3.0.3': + resolution: {integrity: sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-defaults-mode-node@3.0.3': + resolution: {integrity: sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-endpoints@2.0.1': + resolution: {integrity: sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-hex-encoding@3.0.0': + resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-middleware@3.0.0': + resolution: {integrity: sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-retry@3.0.0': + resolution: {integrity: sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==} + engines: {node: '>=16.0.0'} + + '@smithy/util-stream@3.0.1': + resolution: {integrity: sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-uri-escape@3.0.0': + resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} + engines: {node: '>=16.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@3.0.0': + resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} + engines: {node: '>=16.0.0'} + + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@total-typescript/ts-reset@0.5.1': + resolution: {integrity: sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@types/diff-match-patch@1.0.36': + resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.4': + resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} + + '@types/long@4.0.2': + resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node-fetch@2.6.11': + resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} + + '@types/node@18.19.34': + resolution: {integrity: sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==} + + '@types/node@20.14.2': + resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/papaparse@5.3.14': + resolution: {integrity: sha512-LxJ4iEFcpqc6METwp9f6BV6VVc43m6MfH0VqFosHvrUgfXiFe6ww7R3itkOQ+TCK6Y+Iv/+RnnvtRZnkc5Kc9g==} + + '@types/pg@8.11.6': + resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} + + '@types/qs@6.9.15': + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/shimmer@1.0.5': + resolution: {integrity: sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@7.11.0': + resolution: {integrity: sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.11.0': + resolution: {integrity: sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.11.0': + resolution: {integrity: sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.11.0': + resolution: {integrity: sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.11.0': + resolution: {integrity: sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/typescript-estree@7.11.0': + resolution: {integrity: sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.11.0': + resolution: {integrity: sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.11.0': + resolution: {integrity: sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitest/expect@2.0.0-beta.3': + resolution: {integrity: sha512-nbspKRdknioSmLK7NxBTtwRoOjPMbCWesnmhyLG8BMPDAXhse8LPiG1kY1hvpC6moCf0BHUEeiJ5rGIEFxzdAw==} + + '@vitest/runner@2.0.0-beta.3': + resolution: {integrity: sha512-kXv1nelRHt7uRAxX7GMfRFB336DmiQ+9n+voEpN5HmSxJw+SE6k8MbzTsULxBKLtjI2BdpwF48UQaKmXP9adDg==} + + '@vitest/snapshot@2.0.0-beta.3': + resolution: {integrity: sha512-39Clmuu7TQjcOBMs+gbWt3T93Ud+gxa3iTaI0DaTgXjQZLu03qeAhYS6iOyw257A6Nt2+TSGZhTlqm3wyYbl2Q==} + + '@vitest/spy@2.0.0-beta.3': + resolution: {integrity: sha512-3qIAJhJ0rgZ5R540G0Xwy/8OYHyydv4A1gx+IA7PA8IQbMTfJenmvvJE6JWDYqn1jit0C17XFCtXxYGrIqKY3w==} + + '@vitest/utils@2.0.0-beta.3': + resolution: {integrity: sha512-zVIp7HwPWooG7WKe44QfknrXS7uAGPp0xpGJxDmD+zCGCRhjI94ugv2AtuI1oe5Yf3uGElIVMrY1eBc1LiwbbQ==} + + '@vue/compiler-core@3.4.27': + resolution: {integrity: sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==} + + '@vue/compiler-dom@3.4.27': + resolution: {integrity: sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==} + + '@vue/compiler-sfc@3.4.27': + resolution: {integrity: sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==} + + '@vue/compiler-ssr@3.4.27': + resolution: {integrity: sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==} + + '@vue/reactivity@3.4.27': + resolution: {integrity: sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==} + + '@vue/runtime-core@3.4.27': + resolution: {integrity: sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==} + + '@vue/runtime-dom@3.4.27': + resolution: {integrity: sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==} + + '@vue/server-renderer@3.4.27': + resolution: {integrity: sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==} + peerDependencies: + vue: 3.4.27 + + '@vue/shared@3.4.27': + resolution: {integrity: sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==} + + '@xenova/transformers@2.17.2': + resolution: {integrity: sha512-lZmHqzrVIkSvZdKZEx7IYY51TK0WDrC8eR0c5IMnBsO8di8are1zzw8BlLhyO2TklZKLN5UffNGs1IJwT6oOqQ==} + + '@xmldom/xmldom@0.8.10': + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + + '@zilliz/milvus2-sdk-node@2.4.2': + resolution: {integrity: sha512-fkPu7XXzfUvHoCnSPVOjqQpWuSnnn9x2NMmmCcIOyRzMeXIsrz4Mf/+M7LUzmT8J9F0Khx65B0rJgCu27YzWQw==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-import-assertions@1.9.0: + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + + aggregate-error@4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + + ai@3.1.30: + resolution: {integrity: sha512-6o3ttMqhO81y+8tibrvH+Z+38e5lM2O50sM8F1YBCYietZzFjkAg0VL/400lruyyzPjcxcGhGdBUBLe83iRxHg==} + engines: {node: '>=18'} + peerDependencies: + openai: ^4.42.0 + react: ^18 || ^19 + solid-js: ^1.7.7 + svelte: ^3.0.0 || ^4.0.0 + vue: ^3.3.4 + zod: ^3.0.0 + peerDependenciesMeta: + openai: + optional: true + react: + optional: true + solid-js: + optional: true + svelte: + optional: true + vue: + optional: true + zod: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.14.0: + resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==} + + ajv@8.16.0: + resolution: {integrity: sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==} + + already@2.2.1: + resolution: {integrity: sha512-qk6RIVMS/R1yTvBzfIL1T76PsIL7DIVCINoLuFw2YXKLpLtsTobqdChMs8m3OhuPS3CEE3+Ra5ibYiqdyogbsQ==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-escapes@3.2.0: + resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} + engines: {node: '>=4'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + + ansi-escapes@6.2.1: + resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} + engines: {node: '>=14.16'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + + ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-observable@0.3.0: + resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==} + engines: {node: '>=6'} + peerDependencies: + rxjs: '*' + zenObservable: '*' + peerDependenciesMeta: + rxjs: + optional: true + zenObservable: + optional: true + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + + array.prototype.toreversed@1.1.2: + resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} + + array.prototype.tosorted@1.1.3: + resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + assemblyai@4.4.5: + resolution: {integrity: sha512-zSOat5+A1De8xolJRIvEJ/KOutTFxxTv8NKvlqnQjeqiKFsPBxeaogXL55j0443IRr1pAoKqDaAeAePzF8ub6w==} + engines: {node: '>=18'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + async-mutex@0.5.0: + resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + + axios@1.7.2: + resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} + + axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + + axobject-query@4.0.0: + resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} + + b4a@1.6.6: + resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bare-events@2.3.1: + resolution: {integrity: sha512-sJnSOTVESURZ61XgEleqmP255T6zTYwHPwE4r6SssIh0U9/uDvfpdoJYpVUerJJZH2fueO+CdT8ZT+OC/7aZDA==} + + bare-fs@2.3.1: + resolution: {integrity: sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==} + + bare-os@2.3.0: + resolution: {integrity: sha512-oPb8oMM1xZbhRQBngTgpcQ5gXw6kjOaRsSWsIeNyRxGed2w/ARyP7ScBYpWR1qfX2E5rS3gBw6OWcSQo+s+kUg==} + + bare-path@2.1.3: + resolution: {integrity: sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==} + + bare-stream@2.0.1: + resolution: {integrity: sha512-ubLyoDqPnUf5o0kSFp709HC0WRZuxVuh4pbte5eY95Xvx5bdvz07c2JFmXBfqqe60q+9PJ8S4X5GRvmcNSKMxg==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + binary-search@1.3.6: + resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + + body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + + boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bson-objectid@2.0.4: + resolution: {integrity: sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==} + + bson@6.7.0: + resolution: {integrity: sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==} + engines: {node: '>=16.20.1'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + bufferutil@4.0.8: + resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} + engines: {node: '>=6.14.2'} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bundle-require@4.2.1: + resolution: {integrity: sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: ~0.21.4 + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callguard@2.0.0: + resolution: {integrity: sha512-I3nd+fuj20FK1qu00ImrbH+II+8ULS6ioYr9igqR1xyqySoqc3DiHEyUM0mkoAdKeLGg2CtGnO8R3VRQX5krpQ==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-keys@7.0.2: + resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} + engines: {node: '>=12'} + + camelcase@4.1.0: + resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} + engines: {node: '>=4'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + + caniuse-lite@1.0.30001626: + resolution: {integrity: sha512-JRW7kAH8PFJzoPCJhLSHgDgKg5348hsQ68aqb+slnzuB5QFERv846oA/mRChmlLAOdEDeOkRn3ynb1gSFnjt3w==} + + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} + + chalk-template@1.1.0: + resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} + engines: {node: '>=14.16'} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + chromadb@1.8.1: + resolution: {integrity: sha512-NpbYydbg4Uqt/9BXKgkZXn0fqpsh2Z1yjhkhKH+rcHMoq0pwI18BFSU2QU7Fk/ZypwGefW2AvqyE/3ZJIgy4QA==} + engines: {node: '>=14.17.0'} + peerDependencies: + '@google/generative-ai': ^0.1.1 + cohere-ai: ^5.0.0 || ^6.0.0 || ^7.0.0 + openai: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + '@google/generative-ai': + optional: true + cohere-ai: + optional: true + openai: + optional: true + + chromium-bidi@0.5.19: + resolution: {integrity: sha512-UA6zL77b7RYCjJkZBsZ0wlvCTD+jTjllZ8f6wdO4buevXgTZYjV+XLB9CiEa2OuuTGGTLnI7eN9I60YxuALGQg==} + peerDependencies: + devtools-protocol: '*' + + ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + + cjs-module-lexer@1.3.1: + resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + clean-stack@4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@2.1.0: + resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} + engines: {node: '>=4'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@0.2.1: + resolution: {integrity: sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==} + engines: {node: '>=0.10.0'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cli-width@2.2.1: + resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} + + cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + + codsen-utils@1.6.4: + resolution: {integrity: sha512-PDyvQ5f2PValmqZZIJATimcokDt4JjIev8cKbZgEOoZm+U1IJDYuLeTcxZPQdep99R/X0RIlQ6ReQgPOVnPbNw==} + engines: {node: '>=14.18.0'} + + cohere-ai@7.9.5: + resolution: {integrity: sha512-tr8LUR3Q46agFpfEwaYwzYO4qAuN0/R/8YroG4bc86LadOacBAabctZUq0zfCdLiL7gB4yWJs4QCzfpRH3rQuw==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + configstore@6.0.0: + resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} + engines: {node: '>=12'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + core-js-compat@3.37.1: + resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + date-fns@1.30.1: + resolution: {integrity: sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==} + + dayjs@1.11.11: + resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decamelize@5.0.1: + resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} + engines: {node: '>=10'} + + decircular@0.1.1: + resolution: {integrity: sha512-V2Vy+QYSXdgxRPmOZKQWCDf1KQNTUP/Eqswv/3W20gz7+6GB1HTosNrWqK3PqstVpFw/Dd/cGTmXSTKPeOiGVg==} + engines: {node: '>=18'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-eql@5.0.1: + resolution: {integrity: sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + del-cli@5.1.0: + resolution: {integrity: sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==} + engines: {node: '>=14.16'} + hasBin: true + + del@7.1.0: + resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==} + engines: {node: '>=14.16'} + + delay@6.0.0: + resolution: {integrity: sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==} + engines: {node: '>=16'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + devtools-protocol@0.0.1286932: + resolution: {integrity: sha512-wu58HMQll9voDjR4NlPyoDEw1syfzaBNHymMMZ/QOXiHRNluOnDgu9hp1yHOKYoMlxCh4lSSiugLITe6Fvu1eA==} + + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + dingbat-to-unicode@1.0.1: + resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + duck@0.1.12: + resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} + + e2b@0.16.1: + resolution: {integrity: sha512-2L1R/REEB+EezD4Q4MmcXXNATjvCYov2lv/69+PY6V95+wl1PZblIMTYAe7USxX6P6sqANxNs+kXqZr6RvXkSw==} + engines: {node: '>=18'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.4.788: + resolution: {integrity: sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA==} + + elegant-spinner@1.0.1: + resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} + engines: {node: '>=0.10.0'} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enhanced-resolve@5.16.1: + resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} + engines: {node: '>=10.13.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.0.19: + resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + esbuild@0.21.4: + resolution: {integrity: sha512-sFMcNNrj+Q0ZDolrp5pDhH0nRPN9hLIM3fRPwgbLYJeSHHgnXSnbV3xYgSVuOeLWH9c73VwmEverVzupIv5xuA==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-goat@4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.6.1: + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + + eslint-module-utils@2.8.1: + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.29.1: + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jest-dom@5.4.0: + resolution: {integrity: sha512-yBqvFsnpS5Sybjoq61cJiUsenRkC9K32hYQBFS9doBR7nbQZZ5FyO+X7MlmfM1C48Ejx/qTuOCgukDUNyzKZ7A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6', yarn: '>=1'} + peerDependencies: + '@testing-library/dom': ^8.0.0 || ^9.0.0 || ^10.0.0 + eslint: ^6.8.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + peerDependenciesMeta: + '@testing-library/dom': + optional: true + + eslint-plugin-jest@28.5.0: + resolution: {integrity: sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==} + engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + + eslint-plugin-jsx-a11y@6.8.0: + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + + eslint-plugin-react@7.34.2: + resolution: {integrity: sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + + eslint-plugin-security@2.1.1: + resolution: {integrity: sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==} + + eslint-plugin-simple-import-sort@12.1.0: + resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==} + peerDependencies: + eslint: '>=5.0.0' + + eslint-plugin-unicorn@52.0.0: + resolution: {integrity: sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.56.0' + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + eventsource-parser@1.1.2: + resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} + engines: {node: '>=14.18'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + expr-eval@2.0.2: + resolution: {integrity: sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==} + + express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-xml-parser@4.2.5: + resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} + hasBin: true + + fast-xml-parser@4.4.0: + resolution: {integrity: sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==} + hasBin: true + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + fetch-h2@3.0.2: + resolution: {integrity: sha512-Lo6UPdMKKc9Ond7yjG2vq0mnocspOLh1oV6+XZdtfdexacvMSz5xm3WoQhTAdoR2+UqPlyMNqcqfecipoD+l/A==} + engines: {node: '>=12'} + + figures@1.7.0: + resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==} + engines: {node: '>=0.10.0'} + + figures@2.0.0: + resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} + engines: {node: '>=4'} + + figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatbuffers@1.12.0: + resolution: {integrity: sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + + follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fs-extra@2.1.2: + resolution: {integrity: sha512-9ztMtDZtSKC78V8mev+k31qaTabbmuH5jatdvPBMikrFHvw5BqlYnQIn/WGK3WHeRooSTkRvLa2IPlaHjPq5Sg==} + + fs-promise@2.0.3: + resolution: {integrity: sha512-oDrTLBQAcRd+p/tSRWvqitKegLPsvqr7aehs5N9ILWFM9az5y5Uh71jKdZ/DTMC4Kel7+GNCQyFCx/IftRv8yg==} + deprecated: Use mz or fs-extra^3.0 with Promise Support + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gaxios@6.6.0: + resolution: {integrity: sha512-bpOZVQV5gthH/jVCSuYuokRo2bTKOcuBiVWpjmTn6C5Agl5zclGfTljuGsQZxwwDBkli+YhZhP4TdlqTnhOezQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.0: + resolution: {integrity: sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==} + engines: {node: '>=14'} + + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + + genkitx-openai@0.10.0: + resolution: {integrity: sha512-99GFTd9DMZua59L6v7LipM0HPPaFaaelGKPsscHOoi7L3V1oc7BBPdvr5XO6Vceasb2Hda13OLeCdu5VIP0Jgg==} + peerDependencies: + '@genkit-ai/ai': ^0.5.0 + '@genkit-ai/core': ^0.5.0 + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} + + get-uri@6.0.3: + resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} + engines: {node: '>= 14'} + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + github-url-from-git@1.5.0: + resolution: {integrity: sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.1: + resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==} + engines: {node: '>=16 || 14 >=14.18'} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + google-auth-library@9.10.0: + resolution: {integrity: sha512-ol+oSa5NbcGdDqA+gZ3G3mev59OHBZksBTxY/tYwjtcp1H/scAFwJfSQU9/1RALoyZ7FslNbke8j4i3ipwlyuQ==} + engines: {node: '>=14'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + guid-typescript@1.0.9: + resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==} + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-object@5.0.1: + resolution: {integrity: sha512-iaRY4jYOow1caHkXW7wotYRjZDQk2nq4U7904anGJj8l4x1SLId+vuR8RpGoywZz9puD769hNFVFLFH9t+baJw==} + engines: {node: '>=18'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@7.0.4: + resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore-walk@6.0.5: + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-in-the-middle@1.7.1: + resolution: {integrity: sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@3.2.0: + resolution: {integrity: sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==} + engines: {node: '>=4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + + index-to-position@0.1.2: + resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} + engines: {node: '>=18'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + infobox-parser@3.6.4: + resolution: {integrity: sha512-d2lTlxKZX7WsYxk9/UPt51nkmZv5tbC75SSw4hfHqZ3LpRAn6ug0oru9xI2X+S78va3aUAze3xl/UqMuwLmJUw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + inquirer-autosubmit-prompt@0.2.0: + resolution: {integrity: sha512-mzNrusCk5L6kSzlN0Ioddn8yzrhYNLli+Sn2ZxMuLechMYAzakiFCIULxsxlQb5YKzthLGfrFACcWoAvM7p04Q==} + + inquirer@6.5.2: + resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} + engines: {node: '>=6.0.0'} + + inquirer@7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + + inquirer@9.2.23: + resolution: {integrity: sha512-kod5s+FBPIDM2xiy9fu+6wdU/SkK5le5GS9lh4FEBjBHqiMgD9lLFbCbuqFNAjNL2ZOy9Wd9F694IOzN9pZHBA==} + engines: {node: '>=18'} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-absolute-url@4.0.1: + resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-any-array@2.0.1: + resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + + is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-in-ci@0.1.0: + resolution: {integrity: sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==} + engines: {node: '>=18'} + hasBin: true + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + + is-installed-globally@1.0.0: + resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} + engines: {node: '>=18'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-npm@6.0.0: + resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-obj@3.0.0: + resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} + engines: {node: '>=12'} + + is-observable@1.1.0: + resolution: {integrity: sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==} + engines: {node: '>=4'} + + is-path-cwd@3.0.0: + resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-relative-url@4.0.0: + resolution: {integrity: sha512-PkzoL1qKAYXNFct5IKdKRH/iBQou/oCC85QhXj6WKtUQBliZ4Yfd3Zk27RHu9KQG8r6zgvAA2AQKC9p+rqTszg==} + engines: {node: '>=14.16'} + + is-scoped@3.0.0: + resolution: {integrity: sha512-ezxLUq30kiTvP0w/5n9tj4qTOKlrA07Oty1hwTQ+lcqw11x6uc8sp7VRb2OVGRzKfCHZ2A22T5Zsau/Q2Akb0g==} + engines: {node: '>=12'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-url-superb@6.1.0: + resolution: {integrity: sha512-LXdhGlYqUPdvEyIhWPEEwYYK3yrUiPcBjmFGlZNv1u5GtIL5qQRf7ddDyPNAvsMFqdzS923FROpTQU97tLe3JQ==} + engines: {node: '>=12'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic-fetch@3.0.0: + resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} + + isomorphic-ws@5.0.0: + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + + issue-regex@4.1.0: + resolution: {integrity: sha512-X3HBmm7+Th+l4/kMtqwcHHgELD0Lfl0Ina6S3+grr+mKmTxsrM84NAO1UuRPIxIbGLIl3TCEu45S1kdu21HYbQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + + jackspeak@3.4.0: + resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} + engines: {node: '>=14'} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-base64@3.7.2: + resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==} + + js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + + js-tiktoken@1.0.12: + resolution: {integrity: sha512-L7wURW1fH9Qaext0VzaUDpFGVQgjkdE3Dgsy9/+yXyGEpBKnylTd0mU0bfbNkKDlXRb6TEsZkwuflu1B8uQbJQ==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsondiffpatch@0.6.0: + resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + jsonfile@2.4.0: + resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} + + 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'} + + jsonrepair@3.8.0: + resolution: {integrity: sha512-89lrxpwp+IEcJ6kwglF0HH3Tl17J08JEpYfXnvvjdp4zV4rjSoGu2NdQHxBs7yTOk3ETjTn9du48pBy8iBqj1w==} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + jwa@2.0.0: + resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + + ky@1.3.0: + resolution: {integrity: sha512-QUViPXlgP6NKA57IAPff/aZSmRA6qs9wKxlEpayBorwRZG+x2LG7jD4kXh8lnH3q/gkUr64NyZ7kwErUEZJmlw==} + engines: {node: '>=18'} + + langchain@0.2.5: + resolution: {integrity: sha512-H5WL0NanCdQ+tzoeEt7Fyz9YGdR3wbfDvfQrJvxAO95istKo5JraRh24dzyvqxM9439xwRMNaMIpMwsyqtWDtQ==} + 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 + '@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 + '@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.11: + resolution: {integrity: sha512-WnKI4g9kU2bHQP136orXr2bcRdgz9iiTBpTN0jWt9IlScUKnJBoD0aa2HOzHURQKeQDnt2JwqVmQ6Depf5uDLQ==} + + langsmith@0.1.30: + resolution: {integrity: sha512-g8f10H1iiRjCweXJjgM3Y9xl6ApCa1OThDvc0BlSDLVrGVPy1on9wT39vAzYkeadC7oG48p7gfpGlYH3kLkJ9Q==} + peerDependencies: + '@langchain/core': '*' + langchain: '*' + openai: '*' + peerDependenciesMeta: + '@langchain/core': + optional: true + langchain: + optional: true + openai: + optional: true + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + latest-version@7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + + lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.2.5: + resolution: {integrity: sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr-input@0.2.1: + resolution: {integrity: sha512-oa8iVG870qJq+OuuMK3DjGqFcwsK1SDu+kULp9kEq09TY231aideIZenr3lFOQdASpAr6asuyJBbX62/a3IIhg==} + engines: {node: '>=6'} + + listr-silent-renderer@1.1.1: + resolution: {integrity: sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==} + engines: {node: '>=4'} + + listr-update-renderer@0.5.0: + resolution: {integrity: sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==} + engines: {node: '>=6'} + peerDependencies: + listr: ^0.14.2 + + listr-verbose-renderer@0.5.0: + resolution: {integrity: sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==} + engines: {node: '>=4'} + + listr2@8.2.1: + resolution: {integrity: sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==} + engines: {node: '>=18.0.0'} + + listr@0.14.3: + resolution: {integrity: sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==} + engines: {node: '>=6'} + + llamaindex@0.3.16: + resolution: {integrity: sha512-k2ltnJ3t1TeR8r9iy3FeuDLPAFBBdjYClfuUtsT6QiSaGYS132nbha+0FbBvrW/5KyXlXCtz/8Can8ObwHybjQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@notionhq/client': ^2.2.15 + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash.zip@4.2.0: + resolution: {integrity: sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@1.0.2: + resolution: {integrity: sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==} + engines: {node: '>=0.10.0'} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + log-update@2.3.0: + resolution: {integrity: sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==} + engines: {node: '>=4'} + + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + + logform@2.6.0: + resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} + engines: {node: '>= 12.0.0'} + + long@4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lop@0.4.1: + resolution: {integrity: sha512-9xyho9why2A2tzm5aIcMWKvzqKsnxrf9B5I+8O30olh6lQU8PH978LqZoI4++37RBgS1Em5i54v1TFs/3wnmXQ==} + + loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + lru-cache@9.1.2: + resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} + engines: {node: 14 || >=16.14} + + magic-bytes.js@1.10.0: + resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} + + magic-string@0.30.10: + resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + mammoth@1.7.2: + resolution: {integrity: sha512-MqWU2hcLf1I5QMKyAbfJCvrLxnv5WztrAQyorfZ+WPq7Hk82vZFmvfR2/64ajIPpM4jlq0TXp1xZvp/FFaL1Ug==} + engines: {node: '>=12.0.0'} + hasBin: true + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + md-utils-ts@2.0.0: + resolution: {integrity: sha512-sMG6JtX0ebcRMHxYTcmgsh0/m6o8hGdQHFE2OgjvflRZlQM51CGGj/uuk056D+12BlCiW0aTpt/AdlDNtgQiew==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + meow@10.1.5: + resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + 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==} + + module-details-from-path@1.0.3: + resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + + mongodb-connection-string-url@3.0.1: + resolution: {integrity: sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==} + + mongodb@6.7.0: + resolution: {integrity: sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + 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.7: + resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} + + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + + new-github-release-url@2.0.0: + resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-abi@3.63.0: + resolution: {integrity: sha512-vAszCsOUrUxjGAmdnM/pq7gUgie0IRteCQMX6d4A534fQCR93EJU5qgzBvU6EkFfK27s0T3HEV3BOyJIr7OMYw==} + engines: {node: '>=10'} + + node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} + hasBin: true + + node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + + normalize-package-data@6.0.1: + resolution: {integrity: sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + + notion-md-crawler@1.0.0: + resolution: {integrity: sha512-mdB6zn/i32qO2C7X7wZLDpWvFryO3bPYMuBfFgmTPomnfEtIejdQJNVaZzw2GapM82lfWZ5dfsZp3s3UL4p1Fg==} + + np@10.0.5: + resolution: {integrity: sha512-Tu270vVvsh92uh6XDXrGS6D94PhzxQYqM8uUxftYVp0B8qXl78dJRYwQ9wfYMOBB9ynlF79eWlUtPUxPzKGddQ==} + engines: {git: '>=2.11.0', node: '>=18', npm: '>=9', pnpm: '>=8', yarn: '>=1.7.0'} + hasBin: true + + npm-name@8.0.0: + resolution: {integrity: sha512-DIuCGcKYYhASAZW6Xh/tiaGMko8IHOHe0n3zOA7SzTi0Yvy00x8L7sa5yNiZ75Ny58O/KeRtNouy8Ut6gPbKiw==} + engines: {node: '>=18'} + + npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-run-all2@6.2.0: + resolution: {integrity: sha512-wA7yVIkthe6qJBfiJ2g6aweaaRlw72itsFGF6HuwCHKwtwAx/4BY1vVpk6bw6lS8RLMsexoasOkd0aYOmsFG7Q==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>= 8'} + hasBin: true + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + num-sort@2.1.0: + resolution: {integrity: sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg==} + engines: {node: '>=8'} + + number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.hasown@1.1.4: + resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} + engines: {node: '>= 0.4'} + + object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + + onetime@2.0.1: + resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} + engines: {node: '>=4'} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + only-allow@1.2.1: + resolution: {integrity: sha512-M7CJbmv7UCopc0neRKdzfoGWaVZC+xC1925GitKH9EAqYFzX9//25Q7oX4+jw0tiCCj+t5l6VZh8UPH23NZkMA==} + hasBin: true + + onnx-proto@4.0.4: + resolution: {integrity: sha512-aldMOB3HRoo6q/phyB6QRQxSt895HNNw82BNyZ2CMh4bjeKv7g/c+VpAFtJuEMVfYLMbRx61hbuqnKceLeDcDA==} + + onnxruntime-common@1.14.0: + resolution: {integrity: sha512-3LJpegM2iMNRX2wUmtYfeX/ytfOzNwAWKSq1HbRrKc9+uqG/FsEA0bbKZl1btQeZaXhC26l44NWpNUeXPII7Ew==} + + onnxruntime-node@1.14.0: + resolution: {integrity: sha512-5ba7TWomIV/9b6NH/1x/8QEeowsb+jBEvFzU6z0T4mNsFwdPqXeFUM7uxC6QeSRkEbWu3qEB0VMjrvzN/0S9+w==} + os: [win32, darwin, linux] + + onnxruntime-web@1.14.0: + resolution: {integrity: sha512-Kcqf43UMfW8mCydVGcX9OMXI2VN17c0p6XvR7IPSZzBf/6lteBzXHvcEVWDPmCKuGombl997HgLqj91F11DzXw==} + + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + + openai-fetch@2.0.3: + resolution: {integrity: sha512-3Kv2lRgld3MYj+TaSgDBb8YnYEVdn601U+I1y0oZs4bCaPINEZXgcQAQAUGFmFVFpG4vU2Jr6ZAKiF5ZlmM5Fg==} + engines: {node: '>=18'} + + openai@4.49.0: + resolution: {integrity: sha512-/UkrBSej5ejZ4vnOFoeFefX7erjp4k3+xoLKkswjLEvgBU9QtCnOUgsfpvHkzTzgDXpqPMCzyQHQXWsgiq2xPw==} + hasBin: true + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + openapi-typescript-fetch@1.1.3: + resolution: {integrity: sha512-smLZPck4OkKMNExcw8jMgrMOGgVGx2N/s6DbKL2ftNl77g5HfoGpZGFy79RBzU/EkaO0OZpwBnslfdBfh7ZcWg==} + engines: {node: '>= 12.0.0', npm: '>= 7.0.0'} + + option@0.2.4: + resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + org-regex@1.0.0: + resolution: {integrity: sha512-7bqkxkEJwzJQUAlyYniqEZ3Ilzjh0yoa62c7gL6Ijxj5bEpPL+8IE1Z0PFj0ywjjXQcdrwR51g9MIcLezR0hKQ==} + engines: {node: '>=8'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + + 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'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + + p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} + + p-memoize@7.1.1: + resolution: {integrity: sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==} + engines: {node: '>=14.16'} + + 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-throttle@6.1.0: + resolution: {integrity: sha512-eQMdGTxk2+047La67wefUtt0tEHh7D+C8Jl7QXoFCuIiNYeQ9zWs2AZiJdIAs72rSXZ06t11me2bgalRNdy3SQ==} + engines: {node: '>=18'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pac-proxy-agent@7.0.1: + resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + papaparse@5.4.1: + resolution: {integrity: sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-json@8.1.0: + resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} + engines: {node: '>=18'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + pdf2json@3.1.3: + resolution: {integrity: sha512-cGP2MIz7v+w/b4vgg0OPKqhT21L/CZ73+RNmXKbKjgtnVJt2e00AqI6NZyMTp6GL6sY+r0NJOZb9gL3g37yuew==} + engines: {node: '>=18.12.1', npm: '>=8.19.2'} + hasBin: true + bundledDependencies: + - '@xmldom/xmldom' + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + + pg-cloudflare@1.1.1: + resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} + + pg-connection-string@2.6.4: + resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-numeric@1.0.2: + resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} + engines: {node: '>=4'} + + pg-pool@3.6.2: + resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==} + peerDependencies: + pg: '>=8.0' + + pg-protocol@1.6.1: + resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + pg-types@4.0.2: + resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} + engines: {node: '>=10'} + + pg@8.12.0: + resolution: {integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + + pgvector@0.1.8: + resolution: {integrity: sha512-mD6aw+XYJrsuLl3Y8s8gHDDfOZQ9ERtfQPdhvjOrC7eOTM7b6sNkxeZxBhHwUdXMfHmyGWIbwU0QbmSnn7pPmg==} + engines: {node: '>= 12'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pinecone-client@2.0.0: + resolution: {integrity: sha512-CxpKuck4zxi/LaGaTrnWQNs9NmXiMB3UtynOhD6dVDoWRKGEXmgRbSFipMUdqGyyQEKMFXzTKvzo4qMHi2Gj8Q==} + engines: {node: '>=18'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pkg-dir@8.0.0: + resolution: {integrity: sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==} + engines: {node: '>=18'} + + platform@1.3.6: + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + portkey-ai@0.1.16: + resolution: {integrity: sha512-EY4FRp6PZSD75Q1o1qc08DfPNTG9FnkUPN3Z1/lEvaq9iFpSO5UekcagUZaKSVhao311qjBjns+kF0rS9ht7iA==} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-array@3.0.2: + resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} + engines: {node: '>=12'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-bytea@3.0.0: + resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} + engines: {node: '>= 6'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-date@2.1.0: + resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} + engines: {node: '>=12'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + postgres-interval@3.0.0: + resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} + engines: {node: '>=12'} + + postgres-range@1.1.4: + resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} + + prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.3.1: + resolution: {integrity: sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + protobufjs@6.11.4: + resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} + hasBin: true + + protobufjs@7.3.0: + resolution: {integrity: sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==} + engines: {node: '>=12.0.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-agent@6.4.0: + resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + + pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pupa@3.1.0: + resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} + engines: {node: '>=12.20'} + + puppeteer-core@22.10.0: + resolution: {integrity: sha512-I54J4Vy4I07UHsgB1QSmuFoF7KNQjJWcvFBPhtY+ezMdBfwgGDr8dzYrJa11aPgP9kxIUHjhktcMmmfJkOAtTw==} + engines: {node: '>=18'} + + qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + + qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + + qs@6.12.1: + resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + quick-lru@7.0.0: + resolution: {integrity: sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg==} + engines: {node: '>=18'} + + rake-modified@1.0.8: + resolution: {integrity: sha512-rj/1t+EyI8Ly52eaCeSy5hoNpdNnDlNQ/+jll2DypR6nkuxotMbaupzwbuMSaXzuSL1I2pYVYy7oPus/Ls49ag==} + + ramda@0.29.1: + resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + ranges-apply@7.0.16: + resolution: {integrity: sha512-4rGJHOyA7qatiMDg3vcETkc/TVBPU86/xZRTXff6o7a2neYLmj0EXUUAlhLVuiWAzTPHDPHOQxtk8EDrIF4ohg==} + engines: {node: '>=14.18.0'} + + ranges-merge@9.0.15: + resolution: {integrity: sha512-hvt4hx0FKIaVfjd1oKx0poL57ljxdL2KHC6bXBrAdsx2iCsH+x7nO/5J0k2veM/isnOcFZKp0ZKkiCjCtzy74Q==} + engines: {node: '>=14.18.0'} + + ranges-push@7.0.15: + resolution: {integrity: sha512-gXpBYQ5Umf3uG6jkJnw5ddok2Xfo5p22rAJBLrqzNKa7qkj3q5AOCoxfRPXEHUVaJutfXc9K9eGXdIzdyQKPkw==} + engines: {node: '>=14.18.0'} + + ranges-sort@6.0.11: + resolution: {integrity: sha512-fhNEG0vGi7bESitNNqNBAfYPdl2efB+1paFlI8BQDCNkruERKuuhG8LkQClDIVqUJLkrmKuOSPQ3xZHqVnVo3Q==} + engines: {node: '>=14.18.0'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-package-up@11.0.0: + resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} + engines: {node: '>=18'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg-up@8.0.0: + resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} + engines: {node: '>=12'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + read-pkg@6.0.0: + resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} + engines: {node: '>=12'} + + read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + redent@4.0.0: + resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} + engines: {node: '>=12'} + + reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-in-the-middle@7.3.0: + resolution: {integrity: sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==} + engines: {node: '>=8.6.0'} + + requireindex@1.2.0: + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + + restore-cursor@2.0.0: + resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} + engines: {node: '>=4'} + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + restore-cursor@5.0.0: + resolution: {integrity: sha512-Hp93f349DvdEqJFHiPyzNzVjT7lDDFtQJWRotQVQNl3CHr4j7oMHStQB9UH/CJSHTrevAZXFvomgzy8lXjrK0w==} + engines: {node: '>=18'} + + 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'} + + rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + + run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + + safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + schema-stream@3.1.0: + resolution: {integrity: sha512-R4PoSFJnMORRGJ5i5BTHRO2Ed3Lf2h8DMofHd5XBU4ZE0lEBCTGRqOXBurjTEO2QntPSYAhv93jLt8PFMqDEPw==} + peerDependencies: + zod: 3.22.4 + + scoped-regex@3.0.0: + resolution: {integrity: sha512-yEsN6TuxZhZ1Tl9iB81frTNS292m0I/IG7+w8lTvfcJQP2x3vnpOoevjBoE3Np5A6KnZM2+RtVenihj9t6NiYg==} + engines: {node: '>=12'} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + semver-diff@4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + + seroval-plugins@1.0.7: + resolution: {integrity: sha512-GO7TkWvodGp6buMEX9p7tNyIkbwlyuAWbI6G9Ec5bhcm7mQdu3JOK1IXbEUwb3FVzSc363GraG/wLW23NSavIw==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.0.7: + resolution: {integrity: sha512-n6ZMQX5q0Vn19Zq7CIKNIo7E75gPkGCFUEqDpa8jgwpYr/vScjqnQ6H09t1uIiZ0ZSK0ypEGvrYK2bhBGWsGdw==} + engines: {node: '>=10'} + + serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} + engines: {node: '>=14.15.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + slice-ansi@0.0.4: + resolution: {integrity: sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==} + engines: {node: '>=0.10.0'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.3: + resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==} + engines: {node: '>= 14'} + + socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + solid-js@1.8.17: + resolution: {integrity: sha512-E0FkUgv9sG/gEBWkHr/2XkBluHb1fkrHywUgA6o6XolPDCJ4g1HaLmQufcBBhiF36ee40q+HpG/vCZu7fLpI3Q==} + + solid-swr-store@0.10.7: + resolution: {integrity: sha512-A6d68aJmRP471aWqKKPE2tpgOiR5fH4qXQNfKIec+Vap+MGQm3tvXlT8n0I8UgJSlNAsSAUuw2VTviH2h3Vv5g==} + engines: {node: '>=10'} + peerDependencies: + solid-js: ^1.2 + swr-store: ^0.10 + + sort-keys@5.0.0: + resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==} + engines: {node: '>=12'} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.18: + resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + sswr@2.1.0: + resolution: {integrity: sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + + streamx@2.18.0: + resolution: {integrity: sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-collapse-leading-whitespace@7.0.7: + resolution: {integrity: sha512-jF9eynJoE6ezTCdYI8Qb02/ij/DlU9ItG93Dty4SWfJeLFrotOr+wH9IRiWHTqO3mjCyqBWEiU3uSTIbxYbAEQ==} + engines: {node: '>=14.18.0'} + + string-left-right@6.0.17: + resolution: {integrity: sha512-nuyIV4D4ivnwT64E0TudmCRg52NfkumuEUilyoOrHb/Z2wEOF5I+9SI6P+veFKqWKZfGpAs6OqKe4nAjujARyw==} + engines: {node: '>=14.18.0'} + + string-strip-html@13.4.8: + resolution: {integrity: sha512-vlcRAtx5DN6zXGUx3EYGFg0/JOQWM65mqLgDaBHviQPP+ovUFzqZ30iQ+674JHWr9wNgnzFGxx9TGipPZMnZXg==} + engines: {node: '>=14.18.0'} + + string-trim-spaces-only@5.0.10: + resolution: {integrity: sha512-MhmjE5jNqb1Ylo+BARPRlsdChGLrnPpAUWrT1VOxo9WhWwKVUU6CbZTfjwKaQPYTGS/wsX/4Zek88FM2rEb5iA==} + engines: {node: '>=14.18.0'} + + string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + + string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + engines: {node: '>=18'} + + string.prototype.matchall@4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + engines: {node: '>= 0.4'} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svelte@4.2.18: + resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} + engines: {node: '>=16'} + + swr-store@0.10.6: + resolution: {integrity: sha512-xPjB1hARSiRaNNlUQvWSVrG5SirCjk2TmaUyzzvk69SZQan9hCJqw/5rG9iL7xElHU784GxRPISClq4488/XVw==} + engines: {node: '>=10'} + + swr@2.2.0: + resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + + swrev@4.0.0: + resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} + + swrv@1.0.4: + resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} + peerDependencies: + vue: '>=3.2.26 < 4' + + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + + tar-fs@3.0.5: + resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} + + tar-fs@3.0.6: + resolution: {integrity: sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + terminal-link@3.0.0: + resolution: {integrity: sha512-flFL3m4wuixmf6IfhFJd1YPiLiMuxEc8uHRM1buzIeZPm22Au2pDqBJQgdo7n1WfPU1ONFGv7YDwpFBmHGF6lg==} + engines: {node: '>=12'} + + text-decoder@1.1.0: + resolution: {integrity: sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==} + + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tiktoken@1.0.15: + resolution: {integrity: sha512-sCsrq/vMWUSEW29CJLNmPvWxlVp7yh2tlkAjpJltIKqp5CKf98ZNpdeHRmAlPVFlGEbswDc6SmI8vz64W/qErw==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinybench@2.8.0: + resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + + tinypool@0.9.0: + resolution: {integrity: sha512-/aMLccuigz3ZZV8pv/LvOVkOzOfcKkz0V2d5JfHhXUSlp0JJ8h2lAjveUZFTKqII9L4iJh4jod5bfZxx3mditw==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + trim-newlines@4.1.1: + resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} + engines: {node: '>=12'} + + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + + tsup@8.1.0: + resolution: {integrity: sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + tsx@4.13.0: + resolution: {integrity: sha512-kNY70P2aLMdVBii1Err5ENxDhQ6Vz2PbQGX68DcvzY2/PWK5NLBO6vI7lPr1/2xG3IKSt2MN+KOAyWDQSRlbCA==} + engines: {node: '>=18.0.0'} + hasBin: true + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + twitter-api-sdk@1.2.1: + resolution: {integrity: sha512-tNQ6DGYucFk94JlnUMsHCkHg5o1wnCdHh71Y2ukygNVssOdD1gNVjOpaojJrdwbEAhoZvcWdGHerCa55F8HKxQ==} + engines: {node: '>=14'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + type-fest@4.19.0: + resolution: {integrity: sha512-CN2l+hWACRiejlnr68vY0/7734Kzu+9+TOslUXbSCQ1ruY9XIHDBSceVXCcHm/oXrdzhtLMMdJEKfemf1yXiZQ==} + engines: {node: '>=16'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typed-emitter@2.1.0: + resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + + underscore@1.13.6: + resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + update-notifier@7.0.0: + resolution: {integrity: sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==} + engines: {node: '>=18'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + urlpattern-polyfill@10.0.0: + resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==} + + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + utf-8-validate@6.0.4: + resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==} + engines: {node: '>=6.14.2'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + uuidv7@0.6.3: + resolution: {integrity: sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite-node@2.0.0-beta.3: + resolution: {integrity: sha512-oOO88OkozvBCyy640b4JFo+g1FAPcYrJcC7JgcuJD3SlgAnGrhD9CvE2ujiG6pxgeSL5U/9wWshGVbBuWsVjxg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.2.12: + resolution: {integrity: sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@2.0.0-beta.3: + resolution: {integrity: sha512-ItxDOo9yzTy4A+BQoUDlegpIbFb4c/KuALBoHogvhBwHkTZwkPVHGkJRsNB4Kj1yvuwV+Mnhdh+PB9TLSN/t4Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.0.0-beta.3 + '@vitest/ui': 2.0.0-beta.3 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vue@3.4.27: + resolution: {integrity: sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url@13.0.0: + resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} + engines: {node: '>=16'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-builtin-type@1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + + widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + + wikipedia@2.1.2: + resolution: {integrity: sha512-RAYaMpXC9/E873RaSEtlEa8dXK4e0p5k98GKOd210MtkE5emm6fcnwD+N6ZA4cuffjDWagvhaQKtp/mGp2BOVQ==} + engines: {node: '>=10'} + + wink-nlp@2.3.0: + resolution: {integrity: sha512-NcMmlsJavRZgaV4dAjsOQPuXG4v3yLRRssEibfx41lhmwTTOCaQGW7czNC73bDKCq7q4vqGTjX3/MFhK3I76TA==} + + winston-transport@4.7.0: + resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} + engines: {node: '>= 12.0.0'} + + winston@3.13.0: + resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==} + engines: {node: '>= 12.0.0'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@3.0.1: + resolution: {integrity: sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==} + engines: {node: '>=4'} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + ws@8.17.0: + resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + xmlbuilder@10.1.1: + resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==} + engines: {node: '>=4.0'} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.4.2: + resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==} + engines: {node: '>= 14'} + hasBin: true + + yaml@2.4.3: + resolution: {integrity: sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + + zod-stream@1.0.3: + resolution: {integrity: sha512-HxK/PZ0faOMgI1Pgjhcwin22StvlwiaYo6R7jWCT3jOFcPa4wGyFLVpeC5TwmpT6YlZhNJfDoB0qJoa+rQLYmQ==} + peerDependencies: + openai: '>=4.24.1' + zod: '>=3.22.4' + + zod-to-json-schema@3.22.5: + resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==} + peerDependencies: + zod: ^3.22.4 + + zod-to-json-schema@3.23.0: + resolution: {integrity: sha512-az0uJ243PxsRIa2x1WmNE/pnuA05gUq/JB8Lwe1EDCCL/Fz9MgjYQ0fPlyc2Tcv6aF2ZA7WM5TWaRZVEFaAIag==} + peerDependencies: + zod: ^3.23.3 + + zod-validation-error@2.1.0: + resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod-validation-error@3.3.0: + resolution: {integrity: sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + +snapshots: + + '@ai-sdk/openai@0.0.24(zod@3.23.8)': + dependencies: + '@ai-sdk/provider': 0.0.10 + '@ai-sdk/provider-utils': 0.0.13(zod@3.23.8) + zod: 3.23.8 + + '@ai-sdk/provider-utils@0.0.13(zod@3.23.8)': + dependencies: + '@ai-sdk/provider': 0.0.10 + eventsource-parser: 1.1.2 + nanoid: 3.3.6 + secure-json-parse: 2.7.0 + optionalDependencies: + zod: 3.23.8 + + '@ai-sdk/provider@0.0.10': + dependencies: + json-schema: 0.4.0 + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@anthropic-ai/sdk@0.21.1(encoding@0.1.13)': + dependencies: + '@types/node': 18.19.34 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + web-streams-polyfill: 3.3.3 + transitivePeerDependencies: + - encoding + + '@aws-crypto/ie11-detection@3.0.0': + dependencies: + tslib: 1.14.1 + optional: true + + '@aws-crypto/sha256-browser@3.0.0': + dependencies: + '@aws-crypto/ie11-detection': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-crypto/supports-web-crypto': 3.0.0 + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-locate-window': 3.568.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + optional: true + + '@aws-crypto/sha256-js@3.0.0': + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.577.0 + tslib: 1.14.1 + optional: true + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.577.0 + tslib: 2.6.2 + + '@aws-crypto/supports-web-crypto@3.0.0': + dependencies: + tslib: 1.14.1 + optional: true + + '@aws-crypto/util@3.0.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + optional: true + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.6.2 + + '@aws-sdk/client-cognito-identity@3.592.0': + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sts': 3.592.0 + '@aws-sdk/core': 3.592.0 + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/middleware-host-header': 3.577.0 + '@aws-sdk/middleware-logger': 3.577.0 + '@aws-sdk/middleware-recursion-detection': 3.577.0 + '@aws-sdk/middleware-user-agent': 3.587.0 + '@aws-sdk/region-config-resolver': 3.587.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@aws-sdk/util-user-agent-browser': 3.577.0 + '@aws-sdk/util-user-agent-node': 3.587.0 + '@smithy/config-resolver': 3.0.1 + '@smithy/core': 2.2.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/hash-node': 3.0.0 + '@smithy/invalid-dependency': 3.0.0 + '@smithy/middleware-content-length': 3.0.0 + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/node-http-handler': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.3 + '@smithy/util-defaults-mode-node': 3.0.3 + '@smithy/util-endpoints': 2.0.1 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + optional: true + + '@aws-sdk/client-sso-oidc@3.592.0': + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sts': 3.592.0 + '@aws-sdk/core': 3.592.0 + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/middleware-host-header': 3.577.0 + '@aws-sdk/middleware-logger': 3.577.0 + '@aws-sdk/middleware-recursion-detection': 3.577.0 + '@aws-sdk/middleware-user-agent': 3.587.0 + '@aws-sdk/region-config-resolver': 3.587.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@aws-sdk/util-user-agent-browser': 3.577.0 + '@aws-sdk/util-user-agent-node': 3.587.0 + '@smithy/config-resolver': 3.0.1 + '@smithy/core': 2.2.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/hash-node': 3.0.0 + '@smithy/invalid-dependency': 3.0.0 + '@smithy/middleware-content-length': 3.0.0 + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/node-http-handler': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.3 + '@smithy/util-defaults-mode-node': 3.0.3 + '@smithy/util-endpoints': 2.0.1 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + optional: true + + '@aws-sdk/client-sso@3.592.0': + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/core': 3.592.0 + '@aws-sdk/middleware-host-header': 3.577.0 + '@aws-sdk/middleware-logger': 3.577.0 + '@aws-sdk/middleware-recursion-detection': 3.577.0 + '@aws-sdk/middleware-user-agent': 3.587.0 + '@aws-sdk/region-config-resolver': 3.587.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@aws-sdk/util-user-agent-browser': 3.577.0 + '@aws-sdk/util-user-agent-node': 3.587.0 + '@smithy/config-resolver': 3.0.1 + '@smithy/core': 2.2.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/hash-node': 3.0.0 + '@smithy/invalid-dependency': 3.0.0 + '@smithy/middleware-content-length': 3.0.0 + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/node-http-handler': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.3 + '@smithy/util-defaults-mode-node': 3.0.3 + '@smithy/util-endpoints': 2.0.1 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + optional: true + + '@aws-sdk/client-sts@3.592.0': + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/core': 3.592.0 + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/middleware-host-header': 3.577.0 + '@aws-sdk/middleware-logger': 3.577.0 + '@aws-sdk/middleware-recursion-detection': 3.577.0 + '@aws-sdk/middleware-user-agent': 3.587.0 + '@aws-sdk/region-config-resolver': 3.587.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@aws-sdk/util-user-agent-browser': 3.577.0 + '@aws-sdk/util-user-agent-node': 3.587.0 + '@smithy/config-resolver': 3.0.1 + '@smithy/core': 2.2.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/hash-node': 3.0.0 + '@smithy/invalid-dependency': 3.0.0 + '@smithy/middleware-content-length': 3.0.0 + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/node-http-handler': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.3 + '@smithy/util-defaults-mode-node': 3.0.3 + '@smithy/util-endpoints': 2.0.1 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + optional: true + + '@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)': + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/core': 3.592.0 + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)) + '@aws-sdk/middleware-host-header': 3.577.0 + '@aws-sdk/middleware-logger': 3.577.0 + '@aws-sdk/middleware-recursion-detection': 3.577.0 + '@aws-sdk/middleware-user-agent': 3.587.0 + '@aws-sdk/region-config-resolver': 3.587.0 + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@aws-sdk/util-user-agent-browser': 3.577.0 + '@aws-sdk/util-user-agent-node': 3.587.0 + '@smithy/config-resolver': 3.0.1 + '@smithy/core': 2.2.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/hash-node': 3.0.0 + '@smithy/invalid-dependency': 3.0.0 + '@smithy/middleware-content-length': 3.0.0 + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/node-http-handler': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.3 + '@smithy/util-defaults-mode-node': 3.0.3 + '@smithy/util-endpoints': 2.0.1 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + optional: true + + '@aws-sdk/core@3.592.0': + dependencies: + '@smithy/core': 2.2.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/signature-v4': 3.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + fast-xml-parser: 4.2.5 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-provider-cognito-identity@3.592.0': + dependencies: + '@aws-sdk/client-cognito-identity': 3.592.0 + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + optional: true + + '@aws-sdk/credential-provider-env@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-provider-http@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/node-http-handler': 3.0.0 + '@smithy/property-provider': 3.1.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/util-stream': 3.0.1 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-provider-ini@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0))': + dependencies: + '@aws-sdk/client-sts': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-env': 3.587.0 + '@aws-sdk/credential-provider-http': 3.587.0 + '@aws-sdk/credential-provider-process': 3.587.0 + '@aws-sdk/credential-provider-sso': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)) + '@aws-sdk/types': 3.577.0 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + optional: true + + '@aws-sdk/credential-provider-ini@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0)': + dependencies: + '@aws-sdk/client-sts': 3.592.0 + '@aws-sdk/credential-provider-env': 3.587.0 + '@aws-sdk/credential-provider-http': 3.587.0 + '@aws-sdk/credential-provider-process': 3.587.0 + '@aws-sdk/credential-provider-sso': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/types': 3.577.0 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + optional: true + + '@aws-sdk/credential-provider-node@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0))': + dependencies: + '@aws-sdk/credential-provider-env': 3.587.0 + '@aws-sdk/credential-provider-http': 3.587.0 + '@aws-sdk/credential-provider-ini': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)) + '@aws-sdk/credential-provider-process': 3.587.0 + '@aws-sdk/credential-provider-sso': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)) + '@aws-sdk/types': 3.577.0 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - '@aws-sdk/client-sts' + - aws-crt + optional: true + + '@aws-sdk/credential-provider-node@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0)': + dependencies: + '@aws-sdk/credential-provider-env': 3.587.0 + '@aws-sdk/credential-provider-http': 3.587.0 + '@aws-sdk/credential-provider-ini': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/credential-provider-process': 3.587.0 + '@aws-sdk/credential-provider-sso': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/types': 3.577.0 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - '@aws-sdk/client-sts' + - aws-crt + optional: true + + '@aws-sdk/credential-provider-process@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-provider-sso@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)': + dependencies: + '@aws-sdk/client-sso': 3.592.0 + '@aws-sdk/token-providers': 3.587.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + optional: true + + '@aws-sdk/credential-provider-web-identity@3.587.0(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0))': + dependencies: + '@aws-sdk/client-sts': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-provider-web-identity@3.587.0(@aws-sdk/client-sts@3.592.0)': + dependencies: + '@aws-sdk/client-sts': 3.592.0 + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/credential-providers@3.592.0': + dependencies: + '@aws-sdk/client-cognito-identity': 3.592.0 + '@aws-sdk/client-sso': 3.592.0 + '@aws-sdk/client-sts': 3.592.0 + '@aws-sdk/credential-provider-cognito-identity': 3.592.0 + '@aws-sdk/credential-provider-env': 3.587.0 + '@aws-sdk/credential-provider-http': 3.587.0 + '@aws-sdk/credential-provider-ini': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/credential-provider-process': 3.587.0 + '@aws-sdk/credential-provider-sso': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0) + '@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.592.0) + '@aws-sdk/types': 3.577.0 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + optional: true + + '@aws-sdk/middleware-host-header@3.577.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/middleware-logger@3.577.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/middleware-recursion-detection@3.577.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/middleware-user-agent@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@aws-sdk/util-endpoints': 3.587.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/region-config-resolver@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/types': 3.0.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/token-providers@3.587.0(@aws-sdk/client-sso-oidc@3.592.0)': + dependencies: + '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/types': 3.577.0 + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/types@3.577.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + + '@aws-sdk/util-endpoints@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/types': 3.0.0 + '@smithy/util-endpoints': 2.0.1 + tslib: 2.6.3 + optional: true + + '@aws-sdk/util-locate-window@3.568.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@aws-sdk/util-user-agent-browser@3.577.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/types': 3.0.0 + bowser: 2.11.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/util-user-agent-node@3.587.0': + dependencies: + '@aws-sdk/types': 3.577.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@babel/code-frame@7.24.6': + dependencies: + '@babel/highlight': 7.24.6 + picocolors: 1.0.1 + + '@babel/helper-string-parser@7.24.7': {} + + '@babel/helper-validator-identifier@7.24.6': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.6': + dependencies: + '@babel/helper-validator-identifier': 7.24.6 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + + '@babel/parser@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/runtime@7.24.6': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4)': + dependencies: + puppeteer-core: 22.10.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@colors/colors@1.6.0': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + + '@datastax/astra-db-ts@1.2.1': + dependencies: + bson-objectid: 2.0.4 + fetch-h2: 3.0.2 + object-hash: 3.0.0 + typed-emitter: 2.1.0 + uuidv7: 0.6.3 + + '@dexaai/dexter@2.1.0': + dependencies: + '@fastify/deepmerge': 1.3.0 + dedent: 1.5.3 + hash-object: 5.0.1 + jsonrepair: 3.8.0 + ky: 1.3.0 + openai-fetch: 2.0.3 + p-map: 7.0.2 + p-throttle: 6.1.0 + parse-json: 8.1.0 + pinecone-client: 2.0.0 + tiktoken: 1.0.15 + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + zod-validation-error: 3.3.0(zod@3.23.8) + transitivePeerDependencies: + - babel-plugin-macros + + '@e2b/code-interpreter@0.0.7(bufferutil@4.0.8)(utf-8-validate@6.0.4)': + dependencies: + e2b: 0.16.1 + isomorphic-ws: 5.0.0(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@esbuild/aix-ppc64@0.21.4': + optional: true + + '@esbuild/android-arm64@0.21.4': + optional: true + + '@esbuild/android-arm@0.21.4': + optional: true + + '@esbuild/android-x64@0.21.4': + optional: true + + '@esbuild/darwin-arm64@0.21.4': + optional: true + + '@esbuild/darwin-x64@0.21.4': + optional: true + + '@esbuild/freebsd-arm64@0.21.4': + optional: true + + '@esbuild/freebsd-x64@0.21.4': + optional: true + + '@esbuild/linux-arm64@0.21.4': + optional: true + + '@esbuild/linux-arm@0.21.4': + optional: true + + '@esbuild/linux-ia32@0.21.4': + optional: true + + '@esbuild/linux-loong64@0.21.4': + optional: true + + '@esbuild/linux-mips64el@0.21.4': + optional: true + + '@esbuild/linux-ppc64@0.21.4': + optional: true + + '@esbuild/linux-riscv64@0.21.4': + optional: true + + '@esbuild/linux-s390x@0.21.4': + optional: true + + '@esbuild/linux-x64@0.21.4': + optional: true + + '@esbuild/netbsd-x64@0.21.4': + optional: true + + '@esbuild/openbsd-x64@0.21.4': + optional: true + + '@esbuild/sunos-x64@0.21.4': + optional: true + + '@esbuild/win32-arm64@0.21.4': + optional: true + + '@esbuild/win32-ia32@0.21.4': + optional: true + + '@esbuild/win32-x64@0.21.4': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.10.0': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.5 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.57.0': {} + + '@fastify/busboy@2.1.1': {} + + '@fastify/deepmerge@1.3.0': {} + + '@fisch0920/eslint-config@1.3.3(eslint@8.57.0)(typescript@5.4.5)': + dependencies: + '@rushstack/eslint-patch': 1.10.3 + '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + eslint-config-prettier: 9.1.0(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-jest: 28.5.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + eslint-plugin-jest-dom: 5.4.0(eslint@8.57.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) + eslint-plugin-react: 7.34.2(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + eslint-plugin-security: 2.1.1 + eslint-plugin-simple-import-sort: 12.1.0(eslint@8.57.0) + eslint-plugin-unicorn: 52.0.0(eslint@8.57.0) + typescript: 5.4.5 + transitivePeerDependencies: + - '@testing-library/dom' + - eslint + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - jest + - supports-color + + '@genkit-ai/ai@0.5.2': + dependencies: + '@genkit-ai/core': 0.5.2 + '@opentelemetry/api': 1.8.0 + '@types/node': 20.14.2 + json5: 2.2.3 + node-fetch: 3.3.2 + zod: 3.23.8 + transitivePeerDependencies: + - supports-color + + '@genkit-ai/core@0.5.2': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.0(@opentelemetry/api@1.9.0) + ajv: 8.16.0 + ajv-formats: 3.0.1(ajv@8.16.0) + async-mutex: 0.5.0 + express: 4.19.2 + json-schema: 0.4.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + transitivePeerDependencies: + - supports-color + + '@google-cloud/vertexai@1.2.0(encoding@0.1.13)': + dependencies: + google-auth-library: 9.10.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + - supports-color + + '@google/generative-ai@0.12.0': {} + + '@grpc/grpc-js@1.10.8': + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.13': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.3.0 + yargs: 17.7.2 + + '@huggingface/inference@2.7.0': + dependencies: + '@huggingface/tasks': 0.10.9 + + '@huggingface/jinja@0.2.2': {} + + '@huggingface/tasks@0.10.9': {} + + '@humanwhocodes/config-array@0.11.14': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.5 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@inquirer/figures@1.0.3': {} + + '@instructor-ai/instructor@1.3.0(openai@4.49.0(encoding@0.1.13))(zod@3.23.8)': + dependencies: + openai: 4.49.0(encoding@0.1.13) + zod: 3.23.8 + zod-stream: 1.0.3(openai@4.49.0(encoding@0.1.13))(zod@3.23.8) + zod-validation-error: 2.1.0(zod@3.23.8) + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@js-sdsl/ordered-map@4.4.2': {} + + '@langchain/core@0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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.30(@langchain/core@0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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: + - langchain + - openai + + '@langchain/core@0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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.30(@langchain/core@0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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: + - langchain + - openai + + '@langchain/openai@0.1.2(encoding@0.1.13)(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))': + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + js-tiktoken: 1.0.12 + openai: 4.49.0(encoding@0.1.13) + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + transitivePeerDependencies: + - encoding + - langchain + + '@langchain/openai@0.1.2(encoding@0.1.13)(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))': + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + js-tiktoken: 1.0.12 + openai: 4.49.0(encoding@0.1.13) + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + transitivePeerDependencies: + - encoding + - langchain + optional: true + + '@langchain/textsplitters@0.0.3(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13))': + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + js-tiktoken: 1.0.12 + transitivePeerDependencies: + - langchain + - openai + + '@langchain/textsplitters@0.0.3(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13))': + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + js-tiktoken: 1.0.12 + transitivePeerDependencies: + - langchain + - openai + optional: true + + '@ljharb/through@2.3.13': + dependencies: + call-bind: 1.0.7 + + '@llamaindex/cloud@0.0.5(node-fetch@3.3.2)': + dependencies: + '@types/qs': 6.9.15 + form-data: 4.0.0 + js-base64: 3.7.7 + qs: 6.12.1 + optionalDependencies: + node-fetch: 3.3.2 + + '@llamaindex/env@0.1.3(@aws-crypto/sha256-js@5.2.0)(pathe@1.1.2)': + dependencies: + '@types/lodash': 4.17.4 + '@types/node': 20.14.2 + optionalDependencies: + '@aws-crypto/sha256-js': 5.2.0 + pathe: 1.1.2 + + '@mistralai/mistralai@0.4.0(encoding@0.1.13)': + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + '@mongodb-js/saslprep@1.1.7': + dependencies: + sparse-bitfield: 3.0.3 + + '@nangohq/node@0.39.33': + dependencies: + axios: 1.7.2 + transitivePeerDependencies: + - debug + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@notionhq/client@2.2.15(encoding@0.1.13)': + dependencies: + '@types/node-fetch': 2.6.11 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + '@opentelemetry/api-logs@0.49.1': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api@1.8.0': {} + + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/context-async-hooks@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/context-async-hooks@1.25.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/core@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.22.0 + + '@opentelemetry/core@1.25.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.25.0 + + '@opentelemetry/exporter-trace-otlp-grpc@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.10.8 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-http@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-proto@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-proto-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-zipkin@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.22.0 + + '@opentelemetry/instrumentation@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.49.1 + '@types/shimmer': 1.0.5 + import-in-the-middle: 1.7.1 + require-in-the-middle: 7.3.0 + semver: 7.6.2 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-grpc-exporter-base@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.10.8 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + protobufjs: 7.3.0 + + '@opentelemetry/otlp-proto-exporter-base@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.49.1(@opentelemetry/api@1.9.0) + protobufjs: 7.3.0 + + '@opentelemetry/otlp-transformer@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.49.1 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.49.1(@opentelemetry/api-logs@0.49.1)(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-b3@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-jaeger@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/resources@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.22.0 + + '@opentelemetry/resources@1.25.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.0 + + '@opentelemetry/sdk-logs@0.49.1(@opentelemetry/api-logs@0.49.1)(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.49.1 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-metrics@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + lodash.merge: 4.6.2 + + '@opentelemetry/sdk-metrics@1.25.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.0(@opentelemetry/api@1.9.0) + lodash.merge: 4.6.2 + + '@opentelemetry/sdk-node@0.49.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.49.1 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-grpc': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-proto': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-zipkin': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.49.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.49.1(@opentelemetry/api-logs@0.49.1)(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.22.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/sdk-trace-base@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.22.0 + + '@opentelemetry/sdk-trace-base@1.25.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.0 + + '@opentelemetry/sdk-trace-node@1.22.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 1.22.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.9.0) + semver: 7.6.2 + + '@opentelemetry/semantic-conventions@1.22.0': {} + + '@opentelemetry/semantic-conventions@1.25.0': {} + + '@petamoriken/float16@3.8.7': {} + + '@pinecone-database/pinecone@2.2.2': + dependencies: + '@sinclair/typebox': 0.29.6 + ajv: 8.14.0 + cross-fetch: 3.1.8(encoding@0.1.13) + encoding: 0.1.13 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@2.2.2': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@puppeteer/browsers@2.2.3': + dependencies: + debug: 4.3.4 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.4.0 + semver: 7.6.0 + tar-fs: 3.0.5 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + '@qdrant/js-client-rest@1.9.0(typescript@5.4.5)': + dependencies: + '@qdrant/openapi-typescript-fetch': 1.2.6 + '@sevinf/maybe': 0.5.0 + typescript: 5.4.5 + undici: 5.28.4 + + '@qdrant/openapi-typescript-fetch@1.2.6': {} + + '@rollup/rollup-android-arm-eabi@4.18.0': + optional: true + + '@rollup/rollup-android-arm64@4.18.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.18.0': + optional: true + + '@rollup/rollup-darwin-x64@4.18.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.18.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.18.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.18.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.18.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.18.0': + optional: true + + '@rushstack/eslint-patch@1.10.3': {} + + '@samverschueren/stream-to-observable@0.3.1(rxjs@6.6.7)': + dependencies: + any-observable: 0.3.0(rxjs@6.6.7) + optionalDependencies: + rxjs: 6.6.7 + transitivePeerDependencies: + - zenObservable + + '@sevinf/maybe@0.5.0': {} + + '@sinclair/typebox@0.27.8': {} + + '@sinclair/typebox@0.29.6': {} + + '@sindresorhus/is@5.6.0': {} + + '@smithy/abort-controller@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/config-resolver@3.0.1': + dependencies: + '@smithy/node-config-provider': 3.1.0 + '@smithy/types': 3.0.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/core@2.2.0': + dependencies: + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-retry': 3.0.3 + '@smithy/middleware-serde': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/util-middleware': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/credential-provider-imds@3.1.0': + dependencies: + '@smithy/node-config-provider': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/fetch-http-handler@3.0.1': + dependencies: + '@smithy/protocol-http': 4.0.0 + '@smithy/querystring-builder': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-base64': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/hash-node@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/invalid-dependency@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.6.2 + + '@smithy/is-array-buffer@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/middleware-content-length@3.0.0': + dependencies: + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/middleware-endpoint@3.0.1': + dependencies: + '@smithy/middleware-serde': 3.0.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-middleware': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/middleware-retry@3.0.3': + dependencies: + '@smithy/node-config-provider': 3.1.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/service-error-classification': 3.0.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-retry': 3.0.0 + tslib: 2.6.3 + uuid: 9.0.1 + optional: true + + '@smithy/middleware-serde@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/middleware-stack@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/node-config-provider@3.1.0': + dependencies: + '@smithy/property-provider': 3.1.0 + '@smithy/shared-ini-file-loader': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/node-http-handler@3.0.0': + dependencies: + '@smithy/abort-controller': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/querystring-builder': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/property-provider@3.1.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/protocol-http@4.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/querystring-builder@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + '@smithy/util-uri-escape': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/querystring-parser@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/service-error-classification@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + optional: true + + '@smithy/shared-ini-file-loader@3.1.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/signature-v4@3.0.0': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-middleware': 3.0.0 + '@smithy/util-uri-escape': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/smithy-client@3.1.1': + dependencies: + '@smithy/middleware-endpoint': 3.0.1 + '@smithy/middleware-stack': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-stream': 3.0.1 + tslib: 2.6.3 + optional: true + + '@smithy/types@3.0.0': + dependencies: + tslib: 2.6.2 + + '@smithy/url-parser@3.0.0': + dependencies: + '@smithy/querystring-parser': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-base64@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-body-length-browser@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/util-body-length-node@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.6.2 + + '@smithy/util-buffer-from@3.0.0': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-config-provider@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/util-defaults-mode-browser@3.0.3': + dependencies: + '@smithy/property-provider': 3.1.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + bowser: 2.11.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-defaults-mode-node@3.0.3': + dependencies: + '@smithy/config-resolver': 3.0.1 + '@smithy/credential-provider-imds': 3.1.0 + '@smithy/node-config-provider': 3.1.0 + '@smithy/property-provider': 3.1.0 + '@smithy/smithy-client': 3.1.1 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-endpoints@2.0.1': + dependencies: + '@smithy/node-config-provider': 3.1.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-hex-encoding@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/util-middleware@3.0.0': + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-retry@3.0.0': + dependencies: + '@smithy/service-error-classification': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-stream@3.0.1': + dependencies: + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/node-http-handler': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + optional: true + + '@smithy/util-uri-escape@3.0.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.6.2 + + '@smithy/util-utf8@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + tslib: 2.6.3 + optional: true + + '@szmarczak/http-timer@5.0.1': + dependencies: + defer-to-connect: 2.0.1 + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@total-typescript/ts-reset@0.5.1': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/diff-match-patch@1.0.36': {} + + '@types/estree@1.0.5': {} + + '@types/http-cache-semantics@4.0.4': {} + + '@types/json5@0.0.29': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.4 + + '@types/lodash@4.17.4': {} + + '@types/long@4.0.2': {} + + '@types/minimist@1.2.5': {} + + '@types/node-fetch@2.6.11': + dependencies: + '@types/node': 18.19.34 + form-data: 4.0.0 + + '@types/node@18.19.34': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.14.2': + dependencies: + undici-types: 5.26.5 + + '@types/normalize-package-data@2.4.4': {} + + '@types/papaparse@5.3.14': + dependencies: + '@types/node': 20.14.2 + + '@types/pg@8.11.6': + dependencies: + '@types/node': 20.14.2 + pg-protocol: 1.6.1 + pg-types: 4.0.2 + + '@types/qs@6.9.15': {} + + '@types/retry@0.12.0': {} + + '@types/shimmer@1.0.5': {} + + '@types/tough-cookie@4.0.5': {} + + '@types/triple-beam@1.3.5': {} + + '@types/uuid@9.0.8': {} + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 20.14.2 + optional: true + + '@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.11.0 + '@typescript-eslint/type-utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.11.0 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/scope-manager': 7.11.0 + '@typescript-eslint/types': 7.11.0 + '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.11.0 + debug: 4.3.5 + eslint: 8.57.0 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.11.0': + dependencies: + '@typescript-eslint/types': 7.11.0 + '@typescript-eslint/visitor-keys': 7.11.0 + + '@typescript-eslint/type-utils@7.11.0(eslint@8.57.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.4.5) + '@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + debug: 4.3.5 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.11.0': {} + + '@typescript-eslint/typescript-estree@7.11.0(typescript@5.4.5)': + dependencies: + '@typescript-eslint/types': 7.11.0 + '@typescript-eslint/visitor-keys': 7.11.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.11.0(eslint@8.57.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 7.11.0 + '@typescript-eslint/types': 7.11.0 + '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.4.5) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.11.0': + dependencies: + '@typescript-eslint/types': 7.11.0 + eslint-visitor-keys: 3.4.3 + + '@ungap/structured-clone@1.2.0': {} + + '@vitest/expect@2.0.0-beta.3': + dependencies: + '@vitest/spy': 2.0.0-beta.3 + '@vitest/utils': 2.0.0-beta.3 + chai: 5.1.1 + + '@vitest/runner@2.0.0-beta.3': + dependencies: + '@vitest/utils': 2.0.0-beta.3 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@2.0.0-beta.3': + dependencies: + magic-string: 0.30.10 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@2.0.0-beta.3': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@2.0.0-beta.3': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 3.1.1 + pretty-format: 29.7.0 + + '@vue/compiler-core@3.4.27': + dependencies: + '@babel/parser': 7.24.7 + '@vue/shared': 3.4.27 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.0 + + '@vue/compiler-dom@3.4.27': + dependencies: + '@vue/compiler-core': 3.4.27 + '@vue/shared': 3.4.27 + + '@vue/compiler-sfc@3.4.27': + dependencies: + '@babel/parser': 7.24.7 + '@vue/compiler-core': 3.4.27 + '@vue/compiler-dom': 3.4.27 + '@vue/compiler-ssr': 3.4.27 + '@vue/shared': 3.4.27 + estree-walker: 2.0.2 + magic-string: 0.30.10 + postcss: 8.4.38 + source-map-js: 1.2.0 + + '@vue/compiler-ssr@3.4.27': + dependencies: + '@vue/compiler-dom': 3.4.27 + '@vue/shared': 3.4.27 + + '@vue/reactivity@3.4.27': + dependencies: + '@vue/shared': 3.4.27 + + '@vue/runtime-core@3.4.27': + dependencies: + '@vue/reactivity': 3.4.27 + '@vue/shared': 3.4.27 + + '@vue/runtime-dom@3.4.27': + dependencies: + '@vue/runtime-core': 3.4.27 + '@vue/shared': 3.4.27 + csstype: 3.1.3 + + '@vue/server-renderer@3.4.27(vue@3.4.27(typescript@5.4.5))': + dependencies: + '@vue/compiler-ssr': 3.4.27 + '@vue/shared': 3.4.27 + vue: 3.4.27(typescript@5.4.5) + + '@vue/shared@3.4.27': {} + + '@xenova/transformers@2.17.2': + dependencies: + '@huggingface/jinja': 0.2.2 + onnxruntime-web: 1.14.0 + sharp: 0.32.6 + optionalDependencies: + onnxruntime-node: 1.14.0 + + '@xmldom/xmldom@0.8.10': {} + + '@zilliz/milvus2-sdk-node@2.4.2': + dependencies: + '@grpc/grpc-js': 1.10.8 + '@grpc/proto-loader': 0.7.13 + '@petamoriken/float16': 3.8.7 + dayjs: 1.11.11 + generic-pool: 3.9.0 + lru-cache: 9.1.2 + protobufjs: 7.3.0 + winston: 3.13.0 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-import-assertions@1.9.0(acorn@8.11.3): + dependencies: + acorn: 8.11.3 + + acorn-jsx@5.3.2(acorn@8.11.3): + dependencies: + acorn: 8.11.3 + + acorn-walk@8.3.2: {} + + acorn@8.11.3: {} + + agent-base@7.1.1: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + agentkeepalive@4.5.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@4.0.1: + dependencies: + clean-stack: 4.2.0 + indent-string: 5.0.0 + + ai@3.1.30(openai@4.49.0(encoding@0.1.13))(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.18)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8): + dependencies: + '@ai-sdk/provider': 0.0.10 + '@ai-sdk/provider-utils': 0.0.13(zod@3.23.8) + eventsource-parser: 1.1.2 + json-schema: 0.4.0 + jsondiffpatch: 0.6.0 + nanoid: 3.3.6 + secure-json-parse: 2.7.0 + solid-swr-store: 0.10.7(solid-js@1.8.17)(swr-store@0.10.6) + sswr: 2.1.0(svelte@4.2.18) + swr: 2.2.0(react@18.3.1) + swr-store: 0.10.6 + swrv: 1.0.4(vue@3.4.27(typescript@5.4.5)) + zod-to-json-schema: 3.22.5(zod@3.23.8) + optionalDependencies: + openai: 4.49.0(encoding@0.1.13) + react: 18.3.1 + solid-js: 1.8.17 + svelte: 4.2.18 + vue: 3.4.27(typescript@5.4.5) + zod: 3.23.8 + + ajv-formats@3.0.1(ajv@8.16.0): + optionalDependencies: + ajv: 8.16.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.14.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.16.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + already@2.2.1: {} + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-escapes@3.2.0: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@5.0.0: + dependencies: + type-fest: 1.4.0 + + ansi-escapes@6.2.1: {} + + ansi-regex@2.1.1: {} + + ansi-regex@3.0.1: {} + + ansi-regex@4.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@2.2.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + any-observable@0.3.0(rxjs@6.6.7): + optionalDependencies: + rxjs: 6.6.7 + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + array-buffer-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + + array-flatten@1.1.1: {} + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + + array-union@2.1.0: {} + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.flat@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.flatmap@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.toreversed@1.1.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.tosorted@1.1.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-shim-unscopables: 1.0.2 + + arraybuffer.prototype.slice@1.0.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + + arrify@1.0.1: {} + + assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4): + dependencies: + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + assertion-error@2.0.1: {} + + ast-types-flow@0.0.8: {} + + ast-types@0.13.4: + dependencies: + tslib: 2.6.2 + + async-mutex@0.5.0: + dependencies: + tslib: 2.6.3 + + async@3.2.5: {} + + asynckit@0.4.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + axe-core@4.7.0: {} + + axios@1.7.2: + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axobject-query@3.2.1: + dependencies: + dequal: 2.0.3 + + axobject-query@4.0.0: + dependencies: + dequal: 2.0.3 + + b4a@1.6.6: {} + + balanced-match@1.0.2: {} + + bare-events@2.3.1: + optional: true + + bare-fs@2.3.1: + dependencies: + bare-events: 2.3.1 + bare-path: 2.1.3 + bare-stream: 2.0.1 + optional: true + + bare-os@2.3.0: + optional: true + + bare-path@2.1.3: + dependencies: + bare-os: 2.3.0 + optional: true + + bare-stream@2.0.1: + dependencies: + streamx: 2.18.0 + optional: true + + base64-js@1.5.1: {} + + basic-ftp@5.0.5: {} + + bignumber.js@9.1.2: {} + + binary-extensions@2.3.0: {} + + binary-search@1.3.6: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.4.7: {} + + body-parser@1.20.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bowser@2.11.0: + optional: true + + boxen@7.1.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.23.0: + dependencies: + caniuse-lite: 1.0.30001626 + electron-to-chromium: 1.4.788 + node-releases: 2.0.14 + update-browserslist-db: 1.0.16(browserslist@4.23.0) + + bson-objectid@2.0.4: {} + + bson@6.7.0: {} + + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bufferutil@4.0.8: + dependencies: + node-gyp-build: 4.8.1 + optional: true + + builtin-modules@3.3.0: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + bundle-require@4.2.1(esbuild@0.21.4): + dependencies: + esbuild: 0.21.4 + load-tsconfig: 0.2.5 + + bytes@3.1.2: {} + + cac@6.7.14: {} + + cacheable-lookup@7.0.0: {} + + cacheable-request@10.2.14: + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.1 + responselike: 3.0.0 + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callguard@2.0.0: {} + + callsites@3.1.0: {} + + camelcase-keys@7.0.2: + dependencies: + camelcase: 6.3.0 + map-obj: 4.3.0 + quick-lru: 5.1.1 + type-fest: 1.4.0 + + camelcase@4.1.0: {} + + camelcase@6.3.0: {} + + camelcase@7.0.1: {} + + caniuse-lite@1.0.30001626: {} + + chai@5.1.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.1 + loupe: 3.1.1 + pathval: 2.0.0 + + chalk-template@1.1.0: + dependencies: + chalk: 5.3.0 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + chardet@0.7.0: {} + + check-error@2.1.1: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chownr@1.1.4: {} + + chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)): + dependencies: + cliui: 8.0.1 + isomorphic-fetch: 3.0.0(encoding@0.1.13) + optionalDependencies: + '@google/generative-ai': 0.12.0 + cohere-ai: 7.9.5(encoding@0.1.13) + openai: 4.49.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + chromium-bidi@0.5.19(devtools-protocol@0.0.1286932): + dependencies: + devtools-protocol: 0.0.1286932 + mitt: 3.0.1 + urlpattern-polyfill: 10.0.0 + zod: 3.22.4 + + ci-info@4.0.0: {} + + cjs-module-lexer@1.3.1: {} + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + clean-stack@4.2.0: + dependencies: + escape-string-regexp: 5.0.0 + + cli-boxes@3.0.0: {} + + cli-cursor@2.1.0: + dependencies: + restore-cursor: 2.0.0 + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + + cli-spinners@2.9.2: {} + + cli-truncate@0.2.1: + dependencies: + slice-ansi: 0.0.4 + string-width: 1.0.2 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.1.0 + + cli-width@2.2.1: {} + + cli-width@3.0.0: {} + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + code-point-at@1.1.0: {} + + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.3 + estree-walker: 3.0.3 + periscopic: 3.1.0 + + codsen-utils@1.6.4: + dependencies: + rfdc: 1.3.1 + + cohere-ai@7.9.5(encoding@0.1.13): + dependencies: + form-data: 4.0.0 + js-base64: 3.7.2 + node-fetch: 2.7.0(encoding@0.1.13) + qs: 6.11.2 + url-join: 4.0.1 + transitivePeerDependencies: + - encoding + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + colorette@2.0.20: {} + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@12.1.0: {} + + commander@4.1.1: {} + + concat-map@0.0.1: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + configstore@6.0.0: + dependencies: + dot-prop: 6.0.1 + graceful-fs: 4.2.11 + unique-string: 3.0.0 + write-file-atomic: 3.0.3 + xdg-basedir: 5.1.0 + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.6.0: {} + + core-js-compat@3.37.1: + dependencies: + browserslist: 4.23.0 + + core-util-is@1.0.3: {} + + cosmiconfig@8.3.6(typescript@5.4.5): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.4.5 + + create-require@1.1.1: {} + + cross-fetch@3.1.8(encoding@0.1.13): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-random-string@4.0.0: + dependencies: + type-fest: 1.4.0 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.0 + + csstype@3.1.3: {} + + damerau-levenshtein@1.0.8: {} + + data-uri-to-buffer@4.0.1: {} + + data-uri-to-buffer@6.0.2: {} + + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + date-fns@1.30.1: {} + + dayjs@1.11.11: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + debug@4.3.5: + dependencies: + ms: 2.1.2 + + decamelize-keys@1.1.1: + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + + decamelize@1.2.0: {} + + decamelize@5.0.1: {} + + decircular@0.1.1: {} + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + dedent@1.5.3: {} + + deep-eql@5.0.1: {} + + deep-extend@0.6.0: {} + + deep-is@0.1.4: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + del-cli@5.1.0: + dependencies: + del: 7.1.0 + meow: 10.1.5 + + del@7.1.0: + dependencies: + globby: 13.2.2 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 3.0.0 + is-path-inside: 4.0.0 + p-map: 5.5.0 + rimraf: 3.0.2 + slash: 4.0.0 + + delay@6.0.0: {} + + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destroy@1.2.0: {} + + detect-libc@2.0.3: {} + + devtools-protocol@0.0.1286932: {} + + diff-match-patch@1.0.5: {} + + diff-sequences@29.6.3: {} + + diff@4.0.2: {} + + dingbat-to-unicode@1.0.1: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dot-prop@6.0.1: + dependencies: + is-obj: 2.0.0 + + dotenv@16.4.5: {} + + duck@0.1.12: + dependencies: + underscore: 1.13.6 + + e2b@0.16.1: + dependencies: + isomorphic-ws: 5.0.0(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) + normalize-path: 3.0.0 + openapi-typescript-fetch: 1.1.3 + path-browserify: 1.0.1 + platform: 1.3.6 + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + optionalDependencies: + bufferutil: 4.0.8 + utf-8-validate: 6.0.4 + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + electron-to-chromium@1.4.788: {} + + elegant-spinner@1.0.1: {} + + emoji-regex@10.3.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enabled@2.0.0: {} + + encodeurl@1.0.2: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.16.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + entities@4.5.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.3: + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-iterator-helpers@1.0.19: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + iterator.prototype: 1.1.2 + safe-array-concat: 1.1.2 + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.0.2: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.2.1: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + + esbuild@0.21.4: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.4 + '@esbuild/android-arm': 0.21.4 + '@esbuild/android-arm64': 0.21.4 + '@esbuild/android-x64': 0.21.4 + '@esbuild/darwin-arm64': 0.21.4 + '@esbuild/darwin-x64': 0.21.4 + '@esbuild/freebsd-arm64': 0.21.4 + '@esbuild/freebsd-x64': 0.21.4 + '@esbuild/linux-arm': 0.21.4 + '@esbuild/linux-arm64': 0.21.4 + '@esbuild/linux-ia32': 0.21.4 + '@esbuild/linux-loong64': 0.21.4 + '@esbuild/linux-mips64el': 0.21.4 + '@esbuild/linux-ppc64': 0.21.4 + '@esbuild/linux-riscv64': 0.21.4 + '@esbuild/linux-s390x': 0.21.4 + '@esbuild/linux-x64': 0.21.4 + '@esbuild/netbsd-x64': 0.21.4 + '@esbuild/openbsd-x64': 0.21.4 + '@esbuild/sunos-x64': 0.21.4 + '@esbuild/win32-arm64': 0.21.4 + '@esbuild/win32-ia32': 0.21.4 + '@esbuild/win32-x64': 0.21.4 + + escalade@3.1.2: {} + + escape-goat@4.0.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-prettier@9.1.0(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0): + dependencies: + debug: 4.3.5 + enhanced-resolve: 5.16.1 + eslint: 8.57.0 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.5 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + dependencies: + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + hasown: 2.0.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest-dom@5.4.0(eslint@8.57.0): + dependencies: + '@babel/runtime': 7.24.6 + eslint: 8.57.0 + requireindex: 1.2.0 + + eslint-plugin-jest@28.5.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5): + dependencies: + '@typescript-eslint/utils': 7.11.0(eslint@8.57.0)(typescript@5.4.5) + eslint: 8.57.0 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): + dependencies: + '@babel/runtime': 7.24.6 + aria-query: 5.3.0 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.19 + eslint: 8.57.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + + eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-plugin-react@7.34.2(eslint@8.57.0): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.2 + array.prototype.toreversed: 1.1.2 + array.prototype.tosorted: 1.1.3 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.19 + eslint: 8.57.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.hasown: 1.1.4 + object.values: 1.2.0 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.11 + + eslint-plugin-security@2.1.1: + dependencies: + safe-regex: 2.1.1 + + eslint-plugin-simple-import-sort@12.1.0(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-plugin-unicorn@52.0.0(eslint@8.57.0): + dependencies: + '@babel/helper-validator-identifier': 7.24.6 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint/eslintrc': 2.1.4 + ci-info: 4.0.0 + clean-regexp: 1.0.0 + core-js-compat: 3.37.1 + eslint: 8.57.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.2 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint@8.57.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.5 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.6.1: + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.5.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.1: {} + + eventsource-parser@1.1.2: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + exit-hook@4.0.0: {} + + expand-template@2.0.3: {} + + expr-eval@2.0.2: {} + + express@4.19.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.2 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + extract-zip@2.0.1: + dependencies: + debug: 4.3.5 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-xml-parser@4.2.5: + dependencies: + strnum: 1.0.5 + optional: true + + fast-xml-parser@4.4.0: + dependencies: + strnum: 1.0.5 + optional: true + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fecha@4.2.3: {} + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fetch-h2@3.0.2: + dependencies: + '@types/tough-cookie': 4.0.5 + already: 2.2.1 + callguard: 2.0.0 + get-stream: 6.0.1 + through2: 4.0.2 + to-arraybuffer: 1.0.1 + tough-cookie: 4.1.4 + + figures@1.7.0: + dependencies: + escape-string-regexp: 1.0.5 + object-assign: 4.1.1 + + figures@2.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.2.0: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up-simple@1.0.0: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatbuffers@1.12.0: {} + + flatted@3.3.1: {} + + fn.name@1.1.0: {} + + follow-redirects@1.15.6: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.1.1: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + form-data-encoder@1.7.2: {} + + form-data-encoder@2.1.4: {} + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fs-constants@1.0.0: {} + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@2.1.2: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 2.4.0 + + fs-promise@2.0.3: + dependencies: + any-promise: 1.3.0 + fs-extra: 2.1.2 + mz: 2.7.0 + thenify-all: 1.6.0 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + + functions-have-names@1.2.3: {} + + gaxios@6.6.0(encoding@0.1.13): + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.4 + is-stream: 2.0.1 + node-fetch: 2.7.0(encoding@0.1.13) + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.0(encoding@0.1.13): + dependencies: + gaxios: 6.6.0(encoding@0.1.13) + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + generic-pool@3.9.0: {} + + genkitx-openai@0.10.0(@genkit-ai/ai@0.5.2)(@genkit-ai/core@0.5.2)(encoding@0.1.13): + dependencies: + '@genkit-ai/ai': 0.5.2 + '@genkit-ai/core': 0.5.2 + openai: 4.49.0(encoding@0.1.13) + zod: 3.23.8 + transitivePeerDependencies: + - encoding + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.2.0: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.0 + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + get-symbol-description@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + + get-tsconfig@4.7.5: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-uri@6.0.3: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.3.5 + fs-extra: 11.2.0 + transitivePeerDependencies: + - supports-color + + github-from-package@0.0.0: {} + + github-url-from-git@1.5.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.1: + dependencies: + foreground-child: 3.1.1 + jackspeak: 3.4.0 + minimatch: 9.0.4 + minipass: 7.1.2 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + globby@13.2.2: + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 4.0.0 + + google-auth-library@9.10.0(encoding@0.1.13): + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.6.0(encoding@0.1.13) + gcp-metadata: 6.1.0(encoding@0.1.13) + gtoken: 7.1.0(encoding@0.1.13) + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + got@12.6.1: + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + + graceful-fs@4.2.10: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gtoken@7.1.0(encoding@0.1.13): + dependencies: + gaxios: 6.6.0(encoding@0.1.13) + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + guid-typescript@1.0.9: {} + + hard-rejection@2.1.0: {} + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.0.2: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + + hash-object@5.0.1: + dependencies: + decircular: 0.1.1 + is-obj: 3.0.0 + sort-keys: 5.0.0 + type-fest: 4.19.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@2.8.9: {} + + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.2.2 + + html-entities@2.5.2: {} + + http-cache-semantics@4.1.1: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@7.0.4: + dependencies: + agent-base: 7.1.1 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + husky@9.0.11: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore-walk@6.0.5: + dependencies: + minimatch: 9.0.4 + + ignore@5.3.1: {} + + immediate@3.0.6: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-in-the-middle@1.7.1: + dependencies: + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + cjs-module-lexer: 1.3.1 + module-details-from-path: 1.0.3 + + import-lazy@4.0.0: {} + + import-local@3.1.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@3.2.0: {} + + indent-string@4.0.0: {} + + indent-string@5.0.0: {} + + index-to-position@0.1.2: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + infobox-parser@3.6.4: + dependencies: + camelcase: 4.1.0 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@2.0.0: {} + + ini@4.1.1: {} + + inquirer-autosubmit-prompt@0.2.0: + dependencies: + chalk: 2.4.2 + inquirer: 6.5.2 + rxjs: 6.6.7 + + inquirer@6.5.2: + dependencies: + ansi-escapes: 3.2.0 + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-width: 2.2.1 + external-editor: 3.1.0 + figures: 2.0.0 + lodash: 4.17.21 + mute-stream: 0.0.7 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 2.1.1 + strip-ansi: 5.2.0 + through: 2.3.8 + + inquirer@7.3.3: + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + + inquirer@9.2.23: + dependencies: + '@inquirer/figures': 1.0.3 + '@ljharb/through': 2.3.13 + ansi-escapes: 4.3.2 + chalk: 5.3.0 + cli-cursor: 3.1.0 + cli-width: 4.1.0 + external-editor: 3.1.0 + lodash: 4.17.21 + mute-stream: 1.0.0 + ora: 5.4.1 + run-async: 3.0.0 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + internal-slot@1.0.7: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + + ipaddr.js@1.9.1: {} + + is-absolute-url@4.0.1: {} + + is-any-array@2.0.1: {} + + is-array-buffer@3.0.4: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.2: {} + + is-async-function@2.0.0: + dependencies: + has-tostringtag: 1.0.2 + + is-bigint@1.0.4: + dependencies: + has-bigints: 1.0.2 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.1.2: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-callable@1.2.7: {} + + is-core-module@2.13.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: + dependencies: + is-typed-array: 1.1.13 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.0.2: + dependencies: + call-bind: 1.0.7 + + is-fullwidth-code-point@1.0.0: + dependencies: + number-is-nan: 1.0.1 + + is-fullwidth-code-point@2.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-in-ci@0.1.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-installed-globally@0.4.0: + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + + is-installed-globally@1.0.0: + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + + is-interactive@1.0.0: {} + + is-interactive@2.0.0: {} + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-npm@6.0.0: {} + + is-number-object@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-obj@3.0.0: {} + + is-observable@1.1.0: + dependencies: + symbol-observable: 1.2.0 + + is-path-cwd@3.0.0: {} + + is-path-inside@3.0.3: {} + + is-path-inside@4.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@4.1.0: {} + + is-promise@2.2.2: {} + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + + is-regex@1.1.4: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-relative-url@4.0.0: + dependencies: + is-absolute-url: 4.0.1 + + is-scoped@3.0.0: + dependencies: + scoped-regex: 3.0.0 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.3: + dependencies: + call-bind: 1.0.7 + + is-stream@1.1.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-string@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-symbol@1.0.4: + dependencies: + has-symbols: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.15 + + is-typedarray@1.0.0: {} + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@1.3.0: {} + + is-url-superb@6.1.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.0.2: + dependencies: + call-bind: 1.0.7 + + is-weakset@2.0.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isomorphic-fetch@3.0.0(encoding@0.1.13): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - encoding + + isomorphic-ws@5.0.0(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)): + dependencies: + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + + issue-regex@4.1.0: {} + + iterator.prototype@1.1.2: + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + + jackspeak@3.4.0: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + joycon@3.1.1: {} + + js-base64@3.7.2: {} + + js-base64@3.7.7: {} + + js-tiktoken@1.0.12: + dependencies: + base64-js: 1.5.1 + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsbn@1.1.0: {} + + jsesc@0.5.0: {} + + jsesc@3.0.2: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.1.2 + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@3.0.2: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsondiffpatch@0.6.0: + dependencies: + '@types/diff-match-patch': 1.0.36 + chalk: 5.3.0 + diff-match-patch: 1.0.5 + + jsonfile@2.4.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonpointer@5.0.1: {} + + jsonrepair@3.8.0: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + jwa@2.0.0: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.0 + safe-buffer: 5.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + kuler@2.0.0: {} + + ky@1.3.0: {} + + langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)): + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + '@langchain/openai': 0.1.2(encoding@0.1.13)(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))) + '@langchain/textsplitters': 0.0.3(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + binary-extensions: 2.3.0 + js-tiktoken: 1.0.12 + js-yaml: 4.1.0 + jsonpointer: 5.0.1 + langchainhub: 0.0.11 + langsmith: 0.1.30(@langchain/core@0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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.4.3 + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + optionalDependencies: + '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0(@aws-sdk/client-sso-oidc@3.592.0)) + '@browserbasehq/sdk': 1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) + '@notionhq/client': 2.2.15(encoding@0.1.13) + '@pinecone-database/pinecone': 2.2.2 + assemblyai: 4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4) + axios: 1.7.2 + chromadb: 1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)) + fast-xml-parser: 4.4.0 + ignore: 5.3.1 + mammoth: 1.7.2 + mongodb: 6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3) + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - encoding + - openai + + langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)): + dependencies: + '@langchain/core': 0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + '@langchain/openai': 0.1.2(encoding@0.1.13)(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))) + '@langchain/textsplitters': 0.0.3(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + binary-extensions: 2.3.0 + js-tiktoken: 1.0.12 + js-yaml: 4.1.0 + jsonpointer: 5.0.1 + langchainhub: 0.0.11 + langsmith: 0.1.30(@langchain/core@0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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.4.3 + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + optionalDependencies: + '@browserbasehq/sdk': 1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) + '@notionhq/client': 2.2.15(encoding@0.1.13) + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - encoding + - openai + optional: true + + langchainhub@0.0.11: {} + + ? langsmith@0.1.30(@langchain/core@0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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: + '@langchain/core': 0.2.6(langchain@0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + langchain: 0.2.5(@aws-sdk/credential-provider-node@3.592.0)(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(assemblyai@4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4))(axios@1.7.2)(chromadb@1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)))(encoding@0.1.13)(fast-xml-parser@4.4.0)(ignore@5.3.1)(mammoth@1.7.2)(mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3))(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) + openai: 4.49.0(encoding@0.1.13) + + langsmith@0.1.30(@langchain/core@0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)))(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(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: + '@langchain/core': 0.2.6(langchain@0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.49.0(encoding@0.1.13)) + langchain: 0.2.5(@browserbasehq/sdk@1.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(@notionhq/client@2.2.15(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13))(ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) + openai: 4.49.0(encoding@0.1.13) + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + latest-version@7.0.0: + dependencies: + package-json: 8.1.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + + lilconfig@3.1.1: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.2.5: + dependencies: + chalk: 5.3.0 + commander: 12.1.0 + debug: 4.3.5 + execa: 8.0.1 + lilconfig: 3.1.1 + listr2: 8.2.1 + micromatch: 4.0.7 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.4.2 + transitivePeerDependencies: + - supports-color + + listr-input@0.2.1: + dependencies: + inquirer: 7.3.3 + inquirer-autosubmit-prompt: 0.2.0 + rxjs: 6.6.7 + through: 2.3.8 + + listr-silent-renderer@1.1.1: {} + + listr-update-renderer@0.5.0(listr@0.14.3): + dependencies: + chalk: 1.1.3 + cli-truncate: 0.2.1 + elegant-spinner: 1.0.1 + figures: 1.7.0 + indent-string: 3.2.0 + listr: 0.14.3 + log-symbols: 1.0.2 + log-update: 2.3.0 + strip-ansi: 3.0.1 + + listr-verbose-renderer@0.5.0: + dependencies: + chalk: 2.4.2 + cli-cursor: 2.1.0 + date-fns: 1.30.1 + figures: 2.0.0 + + listr2@8.2.1: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.1 + wrap-ansi: 9.0.0 + + listr@0.14.3: + dependencies: + '@samverschueren/stream-to-observable': 0.3.1(rxjs@6.6.7) + is-observable: 1.1.0 + is-promise: 2.2.2 + is-stream: 1.1.0 + listr-silent-renderer: 1.1.1 + listr-update-renderer: 0.5.0(listr@0.14.3) + listr-verbose-renderer: 0.5.0 + p-map: 2.1.0 + rxjs: 6.6.7 + transitivePeerDependencies: + - zen-observable + - zenObservable + + llamaindex@0.3.16(@aws-sdk/credential-providers@3.592.0)(@notionhq/client@2.2.15(encoding@0.1.13))(bufferutil@4.0.8)(encoding@0.1.13)(node-fetch@3.3.2)(socks@2.8.3)(typescript@5.4.5)(utf-8-validate@6.0.4): + dependencies: + '@anthropic-ai/sdk': 0.21.1(encoding@0.1.13) + '@aws-crypto/sha256-js': 5.2.0 + '@datastax/astra-db-ts': 1.2.1 + '@google-cloud/vertexai': 1.2.0(encoding@0.1.13) + '@google/generative-ai': 0.12.0 + '@grpc/grpc-js': 1.10.8 + '@huggingface/inference': 2.7.0 + '@llamaindex/cloud': 0.0.5(node-fetch@3.3.2) + '@llamaindex/env': 0.1.3(@aws-crypto/sha256-js@5.2.0)(pathe@1.1.2) + '@mistralai/mistralai': 0.4.0(encoding@0.1.13) + '@notionhq/client': 2.2.15(encoding@0.1.13) + '@pinecone-database/pinecone': 2.2.2 + '@qdrant/js-client-rest': 1.9.0(typescript@5.4.5) + '@types/lodash': 4.17.4 + '@types/papaparse': 5.3.14 + '@types/pg': 8.11.6 + '@xenova/transformers': 2.17.2 + '@zilliz/milvus2-sdk-node': 2.4.2 + ajv: 8.16.0 + assemblyai: 4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4) + chromadb: 1.8.1(@google/generative-ai@0.12.0)(cohere-ai@7.9.5(encoding@0.1.13))(encoding@0.1.13)(openai@4.49.0(encoding@0.1.13)) + cohere-ai: 7.9.5(encoding@0.1.13) + js-tiktoken: 1.0.12 + lodash: 4.17.21 + magic-bytes.js: 1.10.0 + mammoth: 1.7.2 + md-utils-ts: 2.0.0 + mongodb: 6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3) + notion-md-crawler: 1.0.0(encoding@0.1.13) + openai: 4.49.0(encoding@0.1.13) + papaparse: 5.4.1 + pathe: 1.1.2 + pdf2json: 3.1.3 + pg: 8.12.0 + pgvector: 0.1.8 + portkey-ai: 0.1.16 + rake-modified: 1.0.8 + string-strip-html: 13.4.8 + wikipedia: 2.1.2 + wink-nlp: 2.3.0 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - bufferutil + - debug + - encoding + - gcp-metadata + - kerberos + - mongodb-client-encryption + - node-fetch + - pg-native + - snappy + - socks + - supports-color + - typescript + - utf-8-validate + + load-tsconfig@0.2.5: {} + + locate-character@3.0.0: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.camelcase@4.3.0: {} + + lodash.merge@4.6.2: {} + + lodash.sortby@4.7.0: {} + + lodash.zip@4.2.0: {} + + lodash@4.17.21: {} + + log-symbols@1.0.2: + dependencies: + chalk: 1.1.3 + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-symbols@6.0.0: + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + + log-update@2.3.0: + dependencies: + ansi-escapes: 3.2.0 + cli-cursor: 2.1.0 + wrap-ansi: 3.0.1 + + log-update@6.0.0: + dependencies: + ansi-escapes: 6.2.1 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + logform@2.6.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 + + long@4.0.0: {} + + long@5.2.3: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lop@0.4.1: + dependencies: + duck: 0.1.12 + option: 0.2.4 + underscore: 1.13.6 + + loupe@3.1.1: + dependencies: + get-func-name: 2.0.2 + + lowercase-keys@3.0.0: {} + + lru-cache@10.2.2: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + lru-cache@9.1.2: {} + + magic-bytes.js@1.10.0: {} + + magic-string@0.30.10: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + make-error@1.3.6: {} + + mammoth@1.7.2: + dependencies: + '@xmldom/xmldom': 0.8.10 + argparse: 1.0.10 + base64-js: 1.5.1 + bluebird: 3.4.7 + dingbat-to-unicode: 1.0.1 + jszip: 3.10.1 + lop: 0.4.1 + path-is-absolute: 1.0.1 + underscore: 1.13.6 + xmlbuilder: 10.1.1 + + map-obj@1.0.1: {} + + map-obj@4.3.0: {} + + md-utils-ts@2.0.0: {} + + mdn-data@2.0.30: {} + + media-typer@0.3.0: {} + + memory-pager@1.5.0: {} + + memorystream@0.3.1: {} + + meow@10.1.5: + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 7.0.2 + decamelize: 5.0.1 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 8.0.0 + redent: 4.0.0 + trim-newlines: 4.1.1 + type-fest: 1.4.0 + yargs-parser: 20.2.9 + + meow@13.2.0: {} + + merge-descriptors@1.0.1: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-fn@1.2.0: {} + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + mimic-response@3.1.0: {} + + mimic-response@4.0.0: {} + + min-indent@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.4: + dependencies: + brace-expansion: 2.0.1 + + minimist-options@4.1.0: + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mitt@3.0.1: {} + + mkdirp-classic@0.5.3: {} + + 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 + + module-details-from-path@1.0.3: {} + + mongodb-connection-string-url@3.0.1: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 13.0.0 + + mongodb@6.7.0(@aws-sdk/credential-providers@3.592.0)(socks@2.8.3): + dependencies: + '@mongodb-js/saslprep': 1.1.7 + bson: 6.7.0 + mongodb-connection-string-url: 3.0.1 + optionalDependencies: + '@aws-sdk/credential-providers': 3.592.0 + socks: 2.8.3 + + ms@2.0.0: {} + + ms@2.1.2: {} + + ms@2.1.3: {} + + mustache@4.2.0: {} + + mute-stream@0.0.7: {} + + mute-stream@0.0.8: {} + + mute-stream@1.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.6: {} + + nanoid@3.3.7: {} + + napi-build-utils@1.0.2: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + netmask@2.0.2: {} + + new-github-release-url@2.0.0: + dependencies: + type-fest: 2.19.0 + + node-abi@3.63.0: + dependencies: + semver: 7.6.2 + + node-addon-api@6.1.0: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-gyp-build@4.8.1: + optional: true + + node-releases@2.0.14: {} + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-package-data@3.0.3: + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.13.1 + semver: 7.6.2 + validate-npm-package-license: 3.0.4 + + normalize-package-data@6.0.1: + dependencies: + hosted-git-info: 7.0.2 + is-core-module: 2.13.1 + semver: 7.6.2 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize-url@8.0.1: {} + + notion-md-crawler@1.0.0(encoding@0.1.13): + dependencies: + '@notionhq/client': 2.2.15(encoding@0.1.13) + md-utils-ts: 2.0.0 + transitivePeerDependencies: + - encoding + + np@10.0.5(typescript@5.4.5): + dependencies: + chalk: 5.3.0 + chalk-template: 1.1.0 + cosmiconfig: 8.3.6(typescript@5.4.5) + del: 7.1.0 + escape-goat: 4.0.0 + escape-string-regexp: 5.0.0 + execa: 8.0.1 + exit-hook: 4.0.0 + github-url-from-git: 1.5.0 + hosted-git-info: 7.0.2 + ignore-walk: 6.0.5 + import-local: 3.1.0 + inquirer: 9.2.23 + is-installed-globally: 1.0.0 + is-interactive: 2.0.0 + is-scoped: 3.0.0 + issue-regex: 4.1.0 + listr: 0.14.3 + listr-input: 0.2.1 + log-symbols: 6.0.0 + meow: 13.2.0 + new-github-release-url: 2.0.0 + npm-name: 8.0.0 + onetime: 7.0.0 + open: 10.1.0 + p-memoize: 7.1.1 + p-timeout: 6.1.2 + path-exists: 5.0.0 + pkg-dir: 8.0.0 + read-package-up: 11.0.0 + read-pkg: 9.0.1 + rxjs: 7.8.1 + semver: 7.6.2 + symbol-observable: 4.0.0 + terminal-link: 3.0.0 + update-notifier: 7.0.0 + transitivePeerDependencies: + - typescript + - zen-observable + - zenObservable + + npm-name@8.0.0: + dependencies: + is-scoped: 3.0.0 + is-url-superb: 6.1.0 + ky: 1.3.0 + lodash.zip: 4.2.0 + org-regex: 1.0.0 + p-map: 7.0.2 + registry-auth-token: 5.0.2 + registry-url: 6.0.1 + validate-npm-package-name: 5.0.1 + + npm-normalize-package-bin@3.0.1: {} + + npm-run-all2@6.2.0: + dependencies: + ansi-styles: 6.2.1 + cross-spawn: 7.0.3 + memorystream: 0.3.1 + minimatch: 9.0.4 + pidtree: 0.6.0 + read-package-json-fast: 3.0.2 + shell-quote: 1.8.1 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + num-sort@2.1.0: {} + + number-is-nan@1.0.1: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.1: {} + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + object.entries@1.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + + object.hasown@1.1.4: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + object.values@1.2.0: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + obuf@1.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + + onetime@2.0.1: + dependencies: + mimic-fn: 1.2.0 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + only-allow@1.2.1: + dependencies: + which-pm-runs: 1.1.0 + + onnx-proto@4.0.4: + dependencies: + protobufjs: 6.11.4 + + onnxruntime-common@1.14.0: {} + + onnxruntime-node@1.14.0: + dependencies: + onnxruntime-common: 1.14.0 + optional: true + + onnxruntime-web@1.14.0: + dependencies: + flatbuffers: 1.12.0 + guid-typescript: 1.0.9 + long: 4.0.0 + onnx-proto: 4.0.4 + onnxruntime-common: 1.14.0 + platform: 1.3.6 + + open@10.1.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + + openai-fetch@2.0.3: + dependencies: + ky: 1.3.0 + + openai@4.49.0(encoding@0.1.13): + dependencies: + '@types/node': 18.19.34 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + web-streams-polyfill: 3.3.3 + transitivePeerDependencies: + - encoding + + openapi-types@12.1.3: {} + + openapi-typescript-fetch@1.1.3: {} + + option@0.2.4: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + org-regex@1.0.0: {} + + os-tmpdir@1.0.2: {} + + p-cancelable@3.0.0: {} + + p-finally@1.0.0: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@5.0.0: + dependencies: + yocto-queue: 1.0.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-map@5.5.0: + dependencies: + aggregate-error: 4.0.1 + + p-map@7.0.2: {} + + p-memoize@7.1.1: + dependencies: + mimic-fn: 4.0.0 + type-fest: 3.13.1 + + 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-throttle@6.1.0: {} + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-timeout@6.1.2: {} + + p-try@2.2.0: {} + + pac-proxy-agent@7.0.1: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.1 + debug: 4.3.5 + get-uri: 6.0.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.3 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + package-json@8.1.1: + dependencies: + got: 12.6.1 + registry-auth-token: 5.0.2 + registry-url: 6.0.1 + semver: 7.6.2 + + pako@1.0.11: {} + + papaparse@5.4.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-json@8.1.0: + dependencies: + '@babel/code-frame': 7.24.6 + index-to-position: 0.1.2 + type-fest: 4.19.0 + + parseurl@1.3.3: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.2.2 + minipass: 7.1.2 + + path-to-regexp@0.1.7: {} + + path-type@4.0.0: {} + + pathe@1.1.2: {} + + pathval@2.0.0: {} + + pdf2json@3.1.3: {} + + pend@1.2.0: {} + + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + + pg-cloudflare@1.1.1: + optional: true + + pg-connection-string@2.6.4: {} + + pg-int8@1.0.1: {} + + pg-numeric@1.0.2: {} + + pg-pool@3.6.2(pg@8.12.0): + dependencies: + pg: 8.12.0 + + pg-protocol@1.6.1: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg-types@4.0.2: + dependencies: + pg-int8: 1.0.1 + pg-numeric: 1.0.2 + postgres-array: 3.0.2 + postgres-bytea: 3.0.0 + postgres-date: 2.1.0 + postgres-interval: 3.0.0 + postgres-range: 1.1.4 + + pg@8.12.0: + dependencies: + pg-connection-string: 2.6.4 + pg-pool: 3.6.2(pg@8.12.0) + pg-protocol: 1.6.1 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.1.1 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + pgvector@0.1.8: {} + + picocolors@1.0.1: {} + + picomatch@2.3.1: {} + + pidtree@0.6.0: {} + + pinecone-client@2.0.0: + dependencies: + ky: 1.3.0 + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-dir@8.0.0: + dependencies: + find-up-simple: 1.0.0 + + platform@1.3.6: {} + + pluralize@8.0.0: {} + + portkey-ai@0.1.16: + dependencies: + agentkeepalive: 4.5.0 + + possible-typed-array-names@1.0.0: {} + + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): + dependencies: + lilconfig: 3.1.1 + yaml: 2.4.3 + optionalDependencies: + postcss: 8.4.38 + ts-node: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) + + postcss@8.4.38: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + postgres-array@2.0.0: {} + + postgres-array@3.0.2: {} + + postgres-bytea@1.0.0: {} + + postgres-bytea@3.0.0: + dependencies: + obuf: 1.1.2 + + postgres-date@1.0.7: {} + + postgres-date@2.1.0: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + postgres-interval@3.0.0: {} + + postgres-range@1.1.4: {} + + prebuild-install@7.1.2: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.63.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + + prelude-ls@1.2.1: {} + + prettier@3.3.1: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + proto-list@1.2.4: {} + + protobufjs@6.11.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + '@types/node': 20.14.2 + long: 4.0.0 + + protobufjs@7.3.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.14.2 + long: 5.2.3 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@6.4.0: + dependencies: + agent-base: 7.1.1 + debug: 4.3.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.3 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + psl@1.9.0: {} + + pump@3.0.0: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@2.3.1: {} + + pupa@3.1.0: + dependencies: + escape-goat: 4.0.0 + + puppeteer-core@22.10.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): + dependencies: + '@puppeteer/browsers': 2.2.3 + chromium-bidi: 0.5.19(devtools-protocol@0.0.1286932) + debug: 4.3.4 + devtools-protocol: 0.0.1286932 + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + qs@6.11.0: + dependencies: + side-channel: 1.0.6 + + qs@6.11.2: + dependencies: + side-channel: 1.0.6 + + qs@6.12.1: + dependencies: + side-channel: 1.0.6 + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + queue-tick@1.0.1: {} + + quick-lru@5.1.1: {} + + quick-lru@7.0.0: {} + + rake-modified@1.0.8: + dependencies: + fs-promise: 2.0.3 + lodash: 4.17.21 + + ramda@0.29.1: {} + + range-parser@1.2.1: {} + + ranges-apply@7.0.16: + dependencies: + ranges-merge: 9.0.15 + tiny-invariant: 1.3.3 + + ranges-merge@9.0.15: + dependencies: + ranges-push: 7.0.15 + ranges-sort: 6.0.11 + + ranges-push@7.0.15: + dependencies: + codsen-utils: 1.6.4 + ranges-sort: 6.0.11 + string-collapse-leading-whitespace: 7.0.7 + string-trim-spaces-only: 5.0.10 + + ranges-sort@6.0.11: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + react-is@16.13.1: {} + + react-is@18.3.1: {} + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + read-package-json-fast@3.0.2: + dependencies: + json-parse-even-better-errors: 3.0.2 + npm-normalize-package-bin: 3.0.1 + + read-package-up@11.0.0: + dependencies: + find-up-simple: 1.0.0 + read-pkg: 9.0.1 + type-fest: 4.19.0 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg-up@8.0.0: + dependencies: + find-up: 5.0.0 + read-pkg: 6.0.0 + type-fest: 1.4.0 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + read-pkg@6.0.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 3.0.3 + parse-json: 5.2.0 + type-fest: 1.4.0 + + read-pkg@9.0.1: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.1 + parse-json: 8.1.0 + type-fest: 4.19.0 + unicorn-magic: 0.1.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + redent@4.0.0: + dependencies: + indent-string: 5.0.0 + strip-indent: 4.0.0 + + reflect.getprototypeof@1.0.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + which-builtin-type: 1.1.3 + + regenerator-runtime@0.14.1: {} + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + registry-auth-token@5.0.2: + dependencies: + '@pnpm/npm-conf': 2.2.2 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + regjsparser@0.10.0: + dependencies: + jsesc: 0.5.0 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-in-the-middle@7.3.0: + dependencies: + debug: 4.3.5 + module-details-from-path: 1.0.3 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + requireindex@1.2.0: {} + + requires-port@1.0.0: {} + + resolve-alpn@1.2.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + responselike@3.0.0: + dependencies: + lowercase-keys: 3.0.0 + + restore-cursor@2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.7 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + restore-cursor@5.0.0: + dependencies: + onetime: 6.0.0 + signal-exit: 4.1.0 + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rfdc@1.3.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup@4.18.0: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 + fsevents: 2.3.3 + + run-applescript@7.0.0: {} + + run-async@2.4.1: {} + + run-async@3.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@6.6.7: + dependencies: + tslib: 1.14.1 + + rxjs@7.8.1: + dependencies: + tslib: 2.6.2 + + safe-array-concat@1.1.2: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.0.3: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + + safe-regex@2.1.1: + dependencies: + regexp-tree: 0.1.27 + + safe-stable-stringify@2.4.3: {} + + safer-buffer@2.1.2: {} + + schema-stream@3.1.0(zod@3.23.8): + dependencies: + ramda: 0.29.1 + zod: 3.23.8 + + scoped-regex@3.0.0: {} + + secure-json-parse@2.7.0: {} + + semver-diff@4.0.0: + dependencies: + semver: 7.6.2 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.0: + dependencies: + lru-cache: 6.0.0 + + semver@7.6.2: {} + + send@0.18.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + seroval-plugins@1.0.7(seroval@1.0.7): + dependencies: + seroval: 1.0.7 + + seroval@1.0.7: {} + + serve-static@1.15.0: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sharp@0.32.6: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + node-addon-api: 6.1.0 + prebuild-install: 7.1.2 + semver: 7.6.2 + simple-get: 4.0.1 + tar-fs: 3.0.6 + tunnel-agent: 0.6.0 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.8.1: {} + + shimmer@1.2.1: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + slash@3.0.0: {} + + slash@4.0.0: {} + + slice-ansi@0.0.4: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.3: + dependencies: + agent-base: 7.1.1 + debug: 4.3.5 + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + + socks@2.8.3: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + + solid-js@1.8.17: + dependencies: + csstype: 3.1.3 + seroval: 1.0.7 + seroval-plugins: 1.0.7(seroval@1.0.7) + + solid-swr-store@0.10.7(solid-js@1.8.17)(swr-store@0.10.6): + dependencies: + solid-js: 1.8.17 + swr-store: 0.10.6 + + sort-keys@5.0.0: + dependencies: + is-plain-obj: 4.1.0 + + source-map-js@1.2.0: {} + + source-map@0.6.1: + optional: true + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.18 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.18 + + spdx-license-ids@3.0.18: {} + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + sprintf-js@1.1.3: {} + + sswr@2.1.0(svelte@4.2.18): + dependencies: + svelte: 4.2.18 + swrev: 4.0.0 + + stack-trace@0.0.10: {} + + stackback@0.0.2: {} + + statuses@2.0.1: {} + + std-env@3.7.0: {} + + streamx@2.18.0: + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + text-decoder: 1.1.0 + optionalDependencies: + bare-events: 2.3.1 + + string-argv@0.3.2: {} + + string-collapse-leading-whitespace@7.0.7: {} + + string-left-right@6.0.17: + dependencies: + codsen-utils: 1.6.4 + rfdc: 1.3.1 + + string-strip-html@13.4.8: + dependencies: + '@types/lodash-es': 4.17.12 + codsen-utils: 1.6.4 + html-entities: 2.5.2 + lodash-es: 4.17.21 + ranges-apply: 7.0.16 + ranges-push: 7.0.15 + string-left-right: 6.0.17 + + string-trim-spaces-only@5.0.10: {} + + string-width@1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + + string-width@2.1.1: + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.1.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + + string.prototype.matchall@4.0.11: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + regexp.prototype.flags: 1.5.2 + set-function-name: 2.0.2 + side-channel: 1.0.6 + + string.prototype.trim@1.2.9: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + string.prototype.trimend@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@4.0.0: + dependencies: + ansi-regex: 3.0.1 + + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-bom@3.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-indent@4.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + strnum@1.0.5: + optional: true + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@2.0.0: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svelte@4.2.18: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + '@types/estree': 1.0.5 + acorn: 8.11.3 + aria-query: 5.3.0 + axobject-query: 4.0.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.10 + periscopic: 3.1.0 + + swr-store@0.10.6: + dependencies: + dequal: 2.0.3 + + swr@2.2.0(react@18.3.1): + dependencies: + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) + + swrev@4.0.0: {} + + swrv@1.0.4(vue@3.4.27(typescript@5.4.5)): + dependencies: + vue: 3.4.27(typescript@5.4.5) + + symbol-observable@1.2.0: {} + + symbol-observable@4.0.0: {} + + tapable@2.2.1: {} + + tar-fs@2.1.1: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + + tar-fs@3.0.5: + dependencies: + pump: 3.0.0 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 2.3.1 + bare-path: 2.1.3 + + tar-fs@3.0.6: + dependencies: + pump: 3.0.0 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 2.3.1 + bare-path: 2.1.3 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar-stream@3.1.7: + dependencies: + b4a: 1.6.6 + fast-fifo: 1.3.2 + streamx: 2.18.0 + + terminal-link@3.0.0: + dependencies: + ansi-escapes: 5.0.0 + supports-hyperlinks: 2.3.0 + + text-decoder@1.1.0: + dependencies: + b4a: 1.6.6 + + text-hex@1.0.0: {} + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + through@2.3.8: {} + + tiktoken@1.0.15: {} + + tiny-invariant@1.3.3: {} + + tinybench@2.8.0: {} + + tinypool@0.9.0: {} + + tinyspy@2.2.1: {} + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-arraybuffer@1.0.1: {} + + to-fast-properties@2.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tr46@4.1.1: + dependencies: + punycode: 2.3.1 + + tree-kill@1.2.2: {} + + trim-newlines@4.1.1: {} + + triple-beam@1.4.1: {} + + ts-api-utils@1.3.0(typescript@5.4.5): + dependencies: + typescript: 5.4.5 + + ts-interface-checker@0.1.13: {} + + ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.14.2 + acorn: 8.11.3 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.4.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@1.14.1: {} + + tslib@2.6.2: {} + + tslib@2.6.3: {} + + tsup@8.1.0(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5): + dependencies: + bundle-require: 4.2.1(esbuild@0.21.4) + cac: 6.7.14 + chokidar: 3.6.0 + debug: 4.3.5 + esbuild: 0.21.4 + execa: 5.1.1 + globby: 11.1.0 + joycon: 3.1.1 + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) + resolve-from: 5.0.0 + rollup: 4.18.0 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.4.38 + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + - ts-node + + tsx@4.13.0: + dependencies: + esbuild: 0.21.4 + get-tsconfig: 4.7.5 + optionalDependencies: + fsevents: 2.3.3 + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + + twitter-api-sdk@1.2.1(encoding@0.1.13): + dependencies: + abort-controller: 3.0.0 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-fest@1.4.0: {} + + type-fest@2.19.0: {} + + type-fest@3.13.1: {} + + type-fest@4.19.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + + typed-array-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-byte-offset@1.0.2: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-length@1.0.6: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + + typed-emitter@2.1.0: + optionalDependencies: + rxjs: 7.8.1 + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript@5.4.5: {} + + unbox-primitive@1.0.2: + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + + underscore@1.13.6: {} + + undici-types@5.26.5: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + unicorn-magic@0.1.0: {} + + unique-string@3.0.0: + dependencies: + crypto-random-string: 4.0.0 + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + update-browserslist-db@1.0.16(browserslist@4.23.0): + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.1 + + update-notifier@7.0.0: + dependencies: + boxen: 7.1.1 + chalk: 5.3.0 + configstore: 6.0.0 + import-lazy: 4.0.0 + is-in-ci: 0.1.0 + is-installed-globally: 0.4.0 + is-npm: 6.0.0 + latest-version: 7.0.0 + pupa: 3.1.0 + semver: 7.6.2 + semver-diff: 4.0.0 + xdg-basedir: 5.1.0 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-join@4.0.1: {} + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + urlpattern-polyfill@10.0.0: {} + + use-sync-external-store@1.2.2(react@18.3.1): + dependencies: + react: 18.3.1 + + utf-8-validate@6.0.4: + dependencies: + node-gyp-build: 4.8.1 + optional: true + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@9.0.1: {} + + uuidv7@0.6.3: {} + + v8-compile-cache-lib@3.0.1: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@5.0.1: {} + + vary@1.1.2: {} + + vite-node@2.0.0-beta.3(@types/node@20.14.2): + dependencies: + cac: 6.7.14 + debug: 4.3.5 + pathe: 1.1.2 + picocolors: 1.0.1 + vite: 5.2.12(@types/node@20.14.2) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + vite@5.2.12(@types/node@20.14.2): + dependencies: + esbuild: 0.21.4 + postcss: 8.4.38 + rollup: 4.18.0 + optionalDependencies: + '@types/node': 20.14.2 + fsevents: 2.3.3 + + vitest@2.0.0-beta.3(@types/node@20.14.2): + dependencies: + '@vitest/expect': 2.0.0-beta.3 + '@vitest/runner': 2.0.0-beta.3 + '@vitest/snapshot': 2.0.0-beta.3 + '@vitest/spy': 2.0.0-beta.3 + '@vitest/utils': 2.0.0-beta.3 + chai: 5.1.1 + debug: 4.3.5 + execa: 8.0.1 + magic-string: 0.30.10 + pathe: 1.1.2 + picocolors: 1.0.1 + std-env: 3.7.0 + tinybench: 2.8.0 + tinypool: 0.9.0 + vite: 5.2.12(@types/node@20.14.2) + vite-node: 2.0.0-beta.3(@types/node@20.14.2) + why-is-node-running: 2.2.2 + optionalDependencies: + '@types/node': 20.14.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + vue@3.4.27(typescript@5.4.5): + dependencies: + '@vue/compiler-dom': 3.4.27 + '@vue/compiler-sfc': 3.4.27 + '@vue/runtime-dom': 3.4.27 + '@vue/server-renderer': 3.4.27(vue@3.4.27(typescript@5.4.5)) + '@vue/shared': 3.4.27 + optionalDependencies: + typescript: 5.4.5 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + web-streams-polyfill@3.3.3: {} + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + webidl-conversions@7.0.0: {} + + whatwg-fetch@3.6.20: {} + + whatwg-url@13.0.0: + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + which-boxed-primitive@1.0.2: + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + which-builtin-type@1.1.3: + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + + which-pm-runs@1.1.0: {} + + which-typed-array@1.1.15: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.2.2: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + widest-line@4.0.1: + dependencies: + string-width: 5.1.2 + + wikipedia@2.1.2: + dependencies: + axios: 1.7.2 + infobox-parser: 3.6.4 + transitivePeerDependencies: + - debug + + wink-nlp@2.3.0: {} + + winston-transport@4.7.0: + dependencies: + logform: 2.6.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.13.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.0 + + word-wrap@1.2.5: {} + + wrap-ansi@3.0.1: + dependencies: + string-width: 2.1.1 + strip-ansi: 4.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.1.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): + optionalDependencies: + bufferutil: 4.0.8 + utf-8-validate: 6.0.4 + + xdg-basedir@5.1.0: {} + + xmlbuilder@10.1.1: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@4.0.0: {} + + yaml@2.4.2: {} + + yaml@2.4.3: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.0.0: {} + + zod-stream@1.0.3(openai@4.49.0(encoding@0.1.13))(zod@3.23.8): + dependencies: + openai: 4.49.0(encoding@0.1.13) + schema-stream: 3.1.0(zod@3.23.8) + zod: 3.23.8 + zod-to-json-schema: 3.23.0(zod@3.23.8) + + zod-to-json-schema@3.22.5(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod-to-json-schema@3.23.0(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod-validation-error@2.1.0(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod-validation-error@3.3.0(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod@3.22.4: {} + + zod@3.23.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 000000000..8cef1c0ab --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'examples' diff --git a/readme.md b/readme.md new file mode 100644 index 000000000..bc7727f12 --- /dev/null +++ b/readme.md @@ -0,0 +1,208 @@ +

+ Agentic +

+ +

+ AI agent stdlib that works with any LLM and TypeScript AI SDK +

+ +

+ Build Status + NPM + MIT License + Prettier Code Formatting +

+ +# Agentic + +> [!WARNING] +> TODO: this project is not published yet and is an active WIP. + +The goal of this project is to create a **set of standard AI functions / tools** which are **optimized for both normal TS-usage as well as LLM-based apps** and that work with all of the major AI SDKs (LangChain, LlamaIndex, Vercel AI SDK, OpenAI SDK, etc). + +For example, stdlib clients like `WeatherClient` can be used as normal TS classes: + +```ts +import { WeatherClient } from '@agentic/stdlib' + +const weather = new WeatherClient() // (requires `WEATHER_API_KEY` env var) + +const result = await weather.getCurrentWeather({ + q: 'San Francisco' +}) +console.log(result) +``` + +Or you can use them as LLM-based tools where the LLM decides when and how to invoke the underlying functions for you. + +This works across all of the major AI SDKs via adaptors. Here's an example using [Vercel's AI SDK](https://github.com/vercel/ai): + +```ts +// sdk-specific imports +import { openai } from '@ai-sdk/openai' +import { generateText } from 'ai' +import { createAISDKTools } from '@agentic/stdlib/ai-sdk' + +// sdk-agnostic imports +import { WeatherClient } from '@agentic/stdlib' + +const weather = new WeatherClient() + +const result = await generateText({ + model: openai('gpt-4o'), + // this is the key line which uses the `@agentic/stdlib/ai-sdk` adaptor + tools: createAISDKTools(weather), + toolChoice: 'required', + prompt: 'What is the weather in San Francisco?' +}) + +console.log(result.toolResults[0]) +``` + +You can use our standard library of thoroughly tested AI functions with your favorite AI SDK – without having to write any glue code! + +Here's a slightly more complex example which uses multiple clients and selects a subset of their functions using the `AIFunctionSet.pick` method: + +```ts +// sdk-specific imports +import { ChatModel, createAIRunner } from '@dexaai/dexter' +import { createDexterFunctions } from '@agentic/stdlib/dexter' + +// sdk-agnostic imports +import { PerigonClient, SerperClient } from '@agentic/stdlib' + +async function main() { + // Perigon is a news API and Serper is a Google search API + const perigon = new PerigonClient() + const serper = new SerperClient() + + const runner = createAIRunner({ + chatModel: new ChatModel({ + params: { model: 'gpt-4o', temperature: 0 } + }), + functions: createDexterFunctions( + perigon.functions.pick('search_news_stories'), + serper + ), + systemMessage: `You are a helpful assistant. Be as concise as possible.` + }) + + const result = await runner( + 'Summarize the latest news stories about the upcoming US election.' + ) + console.log(result) +} +``` + +Here we've exposed 2 functions to the LLM, `search_news_stories` (which comes from the `PerigonClient.searchStories` method) and `serper_google_search` (which implicitly comes from the `SerperClient.search` method). + +All of the SDK adaptors like `createDexterFunctions` accept very flexible in what they accept. `AIFunctionLike` objects include: + +- `AIFunctionSet` - Sets of AI functions (like `perigon.functions.pick('search_news_stories')` or `perigon.functions` or `serper.functions`) +- `AIFunctionsProvider` - Client classes which expose an `AIFunctionSet` via the `.functions` property (like `perigon` or `serper`) +- `AIFunction` - Individual functions (like `perigon.functions.get('search_news_stories')` or `serper.functions.get('serper_google_search')` or AI functions created directly via the `createAIFunction` utility function) + +You can pass as many of these `AIFunctionLike` objects as you'd like and you can manipulate them as `AIFunctionSet` sets via `.pick`, `.omit`, `.get`, `.map`, etc. + +All heavy third-party imports are isolated as _optional peer dependencies_ to keep the main `@agentic/stdlib` package as lightweight as possible. + +## Services + +| Service | Client | Description | +| ------------------------------------------------------------------------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Bing](https://www.microsoft.com/en-us/bing/apis/bing-web-search-api) | `BingClient` | Bing web search. | +| [Calculator](https://github.com/silentmatt/expr-eval) | `calculator` | Basic calculator for simple mathematical expressions. | +| [Clearbit](https://dashboard.clearbit.com/docs) | `ClearbitClient` | Resolving and enriching people and company datae. | +| [Dexa](https://dexa.ai) | `DexaClient` | Answers questions from the world's best podcasters. | +| [Diffbot](https://docs.diffbot.com) | `DiffbotClient` | Web page classification and scraping; person and company data enrichment. | +| [E2B](https://e2b.dev) | `e2b` | Hosted Python code intrepreter sandbox which is really useful for data analysis, flexible code execution, and advanced reasoning on-the-fly. | +| [Exa](https://docs.exa.ai) | `ExaClient` | Web search tailored for LLMs. | +| [Firecrawl](https://www.firecrawl.dev) | `FirecrawlClient` | Website scraping and sanitization. | +| [Midjourney](https://www.imagineapi.dev) | `MidjourneyClient` | Unofficial Midjourney client for generative images. | +| [Novu](https://novu.co) | `NovuClient` | Sending notifications (email, SMS, in-app, push, etc). | +| [People Data Labs](https://www.peopledatalabs.com) | `PeopleDataLabsClient` | People & company data (WIP). | +| [Perigon](https://www.goperigon.com/products/news-api) | `PerigonClient` | Real-time news API and web content data from 140,000+ sources. Structured and enriched by AI, primed for LLMs. | +| [Polygon](https://polygon.io) | `PolygonClient` | Stock market and company financial data. | +| [PredictLeads](https://predictleads.com) | `PredictLeadsClient` | In-depth company data including signals like fundraising events, hiring news, product launches, technologies used, etc. | +| [Proxycurl](https://nubela.co/proxycurl) | `ProxycurlClient` | People and company data from LinkedIn & Crunchbase. | +| Scraper | `ScraperClient` | Scrapes URLs into clean html/markdown/text content (TODO: currently closed beta). | +| [Searxng](https://docs.searxng.org) | `SearxngClient` | OSS meta search engine capable of searching across many providers like Reddit, Google, Brave, Arxiv, Genius, IMDB, Rotten Tomatoes, Wikidata, Wolfram Alpha, YouTube, GitHub, [etc](https://docs.searxng.org/user/configured_engines.html#configured-engines). | +| [SerpAPI](https://serpapi.com/search-api) | `SerpAPIClient` | Lightweight wrapper around SerpAPI for Google search. | +| [Serper](https://serper.dev) | `SerperClient` | Lightweight wrapper around Serper for Google search. | +| [Slack](https://api.slack.com/docs) | `SlackClient` | Send and receive Slack messages. | +| [Tavily](https://tavily.com) | `TavilyClient` | Web search API tailored for LLMs. 🔥 | +| [Twilio](https://www.twilio.com/docs/conversations/api) | `TwilioClient` | Twilio conversation API to send and receive SMS messages. | +| [Twitter](https://developer.x.com/en/docs/twitter-api) | `TwitterClient` | Basic Twitter API methods for fetching users, tweets, and searching recent tweets. Includes support for plan-aware rate-limiting. Uses [Nango](https://www.nango.dev) for OAuth support. | +| [WeatherAPI](https://www.weatherapi.com) | `WeatherClient` | Basic access to current weather data based on location. | +| [Wikipedia](https://www.mediawiki.org/wiki/API) | `WikipediaClient` | Wikipedia page search and summaries. | +| [Wolfram Alpha](https://products.wolframalpha.com/llm-api/documentation) | `WolframAlphaClient` | Wolfram Alpha LLM API client for answering computational, mathematical, and scientific questions. | + +Note that many of these clients expose multiple AI functions. + +## Compound Tools + +- `SearchAndCrawl` + +## AI SDKs + +- OpenAI SDK + - no need for an adaptor; use `AIFunctionSet.specs` or `AIFunctionSet.toolSpecs` +- Vercel AI SDK + - `import { createAISDKTools } from '@agentic/stdlib/ai-sdk'` +- LangChain + - `import { createLangChainTools } from '@agentic/stdlib/langchain'` +- LlamaIndex + - `import { createLlamaIndexTools } from '@agentic/stdlib/llamaindex'` +- Firebase Genkit + - `import { createGenkitTools } from '@agentic/stdlib/genkit'` +- Dexa Dexter + - `import { createDexterFunctions } from '@agentic/stdlib/dexter'` + +## Client Goals + +- clients should be as minimal as possible +- clients should use `ky` and `zod` where possible +- clients should have a strongly-typed TS DX +- clients should expose select methods via the `@aiFunction(...)` decorator + - `inputSchema` zod schemas should be as minimal as possible with descriptions prompt engineered specifically for use with LLMs +- clients and AIFunctions should be composable via `AIFunctionSet` +- clients should work with all major TS AI SDKs + - SDK adaptors should be as lightweight as possible and be optional peer dependencies of `@agentic/stdlib` + +## TODO + +- rename this repo to agentic +- sdks + - modelfusion +- services + - browserbase + - [phantombuster](https://phantombuster.com) + - perplexity + - valtown + - replicate + - huggingface + - [skyvern](https://github.com/Skyvern-AI/skyvern) + - pull from [langchain](https://github.com/langchain-ai/langchainjs/tree/main/langchain) + - provide a converter for langchain `DynamicStructuredTool` + - pull from [nango](https://docs.nango.dev/integrations/overview) + - pull from [activepieces](https://github.com/activepieces/activepieces/tree/main/packages/pieces/community) + - general openapi support ala [workgpt](https://github.com/team-openpm/workgpt) +- compound tools / chains / flows / runnables + - market maps +- incorporate [zod-validation-error](https://github.com/causaly/zod-validation-error) +- investigate [autotool](https://github.com/run-llama/LlamaIndexTS/tree/main/packages/autotool) +- investigate [data connectors](https://github.com/mendableai/data-connectors) + +## Contributors + +- [Travis Fischer](https://x.com/transitive_bs) +- [Kevin Raheja](https://x.com/crabfisher) +- [David Zhang](https://x.com/dzhng) +- [Philipp Burckhardt](https://x.com/burckhap) +- [Riley Tomasek](https://x.com/rileytomasek) + +## License + +MIT © [Travis Fischer](https://x.com/transitive_bs) + +To stay up to date or learn more, follow [@transitive_bs](https://x.com/transitive_bs) on Twitter. diff --git a/src/__snapshots__/parse-structured-output.test.ts.snap b/src/__snapshots__/parse-structured-output.test.ts.snap new file mode 100644 index 000000000..c32098daf --- /dev/null +++ b/src/__snapshots__/parse-structured-output.test.ts.snap @@ -0,0 +1,133 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`parseArrayOutput - handles arrays surrounded by text correctly > should return ["a", "b", "c"] for "Array: ["a", "b", "c"]. That's all!" 1`] = ` +[ + "a", + "b", + "c", +] +`; + +exports[`parseArrayOutput - handles arrays surrounded by text correctly > should return [{"a": 1}, {"b": 2}] for "This is the array [{"a": 1}, {"b": 2}] in the text" 1`] = ` +[ + { + "a": 1, + }, + { + "b": 2, + }, +] +`; + +exports[`parseArrayOutput - handles arrays surrounded by text correctly > should return [1, 2, 3] for "The array is [1,2,3]" 1`] = ` +[ + 1, + 2, + 3, +] +`; + +exports[`parseArrayOutput - handles valid arrays correctly > should return ["a", "b", "c"] for "["a", "b", "c"] 1`] = ` +[ + "a", + "b", + "c", +] +`; + +exports[`parseArrayOutput - handles valid arrays correctly > should return [{"a": 1}, {"b": 2}] for [{"a": 1}, {"b": 2}] 1`] = ` +[ + { + "a": 1, + }, + { + "b": 2, + }, +] +`; + +exports[`parseArrayOutput - handles valid arrays correctly > should return [1, 2, 3] for "[1,2,3]" 1`] = ` +[ + 1, + 2, + 3, +] +`; + +exports[`parseBooleanOutput - handles \`false\` outputs correctly > should return false for "FALSE" 1`] = `false`; + +exports[`parseBooleanOutput - handles \`false\` outputs correctly > should return false for "False" 1`] = `false`; + +exports[`parseBooleanOutput - handles \`false\` outputs correctly > should return false for "false!" 1`] = `false`; + +exports[`parseBooleanOutput - handles \`true\` outputs correctly > should return true for "TRUE" 1`] = `true`; + +exports[`parseBooleanOutput - handles \`true\` outputs correctly > should return true for "True" 1`] = `true`; + +exports[`parseBooleanOutput - handles \`true\` outputs correctly > should return true for "true." 1`] = `true`; + +exports[`parseNumberOutput - handles float outputs correctly > should return -5.5 for " -5.5 " 1`] = `-5.5`; + +exports[`parseNumberOutput - handles float outputs correctly > should return 42.42 for "42.42" 1`] = `42.42`; + +exports[`parseNumberOutput - handles integer outputs correctly > should return -5 for " -5 " 1`] = `-5`; + +exports[`parseNumberOutput - handles integer outputs correctly > should return 42 for "42" 1`] = `42`; + +exports[`parseObjectOutput - handles JSON array of objects > should return first object {"a":1,"b":2} for [{"a":1,"b":2},{"c":3,"d":4}] 1`] = ` +{ + "a": 1, + "b": 2, +} +`; + +exports[`parseObjectOutput - handles objects surrounded by text correctly > should return {"a":1,"b":2,"c":3} for "The object is {"a":1,"b":2,"c":3}" 1`] = ` +{ + "a": 1, + "b": 2, + "c": 3, +} +`; + +exports[`parseObjectOutput - handles objects surrounded by text correctly > should return {"name":"John","age":30,"city":"New York"} for "Object: {"name":"John","age":30,"city":"New York"}. That's all!" 1`] = ` +{ + "age": 30, + "city": "New York", + "name": "John", +} +`; + +exports[`parseObjectOutput - handles valid objects correctly > should return {"a":1,"b":2,"c":3} for {"a":1,"b":2,"c":3} 1`] = ` +{ + "a": 1, + "b": 2, + "c": 3, +} +`; + +exports[`parseObjectOutput - handles valid objects correctly > should return {"name":"John","age":30,"city":"New York"} for {"name":"John","age":30,"city":"New York"} 1`] = ` +{ + "age": 30, + "city": "New York", + "name": "John", +} +`; + +exports[`parseStructuredOutput - handles arrays correctly > should parse and return [1, 2, 3] for "[1, 2, 3]" 1`] = ` +[ + 1, + 2, + 3, +] +`; + +exports[`parseStructuredOutput - handles booleans correctly > should parse and return true for "True" 1`] = `true`; + +exports[`parseStructuredOutput - handles numbers correctly > should parse and return 123.45 for "123.45" 1`] = `123.45`; + +exports[`parseStructuredOutput - handles objects correctly > should parse and return {"a": 1, "b": "two"} for "{"a": 1, "b": "two"}" 1`] = ` +{ + "a": 1, + "b": "two", +} +`; diff --git a/src/__snapshots__/utils.test.ts.snap b/src/__snapshots__/utils.test.ts.snap new file mode 100644 index 000000000..78e47ee2e --- /dev/null +++ b/src/__snapshots__/utils.test.ts.snap @@ -0,0 +1,15 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`sanitizeSearchParams 1`] = `"a=1&c=13"`; + +exports[`sanitizeSearchParams 2`] = `"a=1&a=2&a=3"`; + +exports[`sanitizeSearchParams 3`] = `"b=a&b=b&foo=true"`; + +exports[`sanitizeSearchParams 4`] = `"b=false&b=true&b=false"`; + +exports[`sanitizeSearchParams 5`] = `"flag=foo&flag=bar&flag=baz&token=test"`; + +exports[`sanitizeSearchParams 6`] = `""`; + +exports[`sanitizeSearchParams 7`] = `""`; diff --git a/src/_utils.ts b/src/_utils.ts new file mode 100644 index 000000000..81c492626 --- /dev/null +++ b/src/_utils.ts @@ -0,0 +1,44 @@ +import 'dotenv/config' + +import defaultKy, { + type AfterResponseHook, + type BeforeRequestHook, + type KyInstance +} from 'ky' + +const AGENTIC_TEST_MOCK_HEADER = 'x-agentic-test-mock' + +function defaultBeforeRequest(request: Request): Response { + return new Response( + JSON.stringify({ + url: request.url, + method: request.method, + headers: request.headers + }), + { + status: 200, + headers: { + 'Content-Type': 'application/json', + [AGENTIC_TEST_MOCK_HEADER]: '1' + } + } + ) +} + +export function mockKyInstance( + ky: KyInstance = defaultKy, + { + beforeRequest = defaultBeforeRequest, + afterResponse + }: { + beforeRequest?: BeforeRequestHook + afterResponse?: AfterResponseHook + } = {} +): KyInstance { + return ky.extend({ + hooks: { + beforeRequest: beforeRequest ? [beforeRequest] : [], + afterResponse: afterResponse ? [afterResponse] : [] + } + }) +} diff --git a/src/ai-function-set.ts b/src/ai-function-set.ts new file mode 100644 index 000000000..1c3d21867 --- /dev/null +++ b/src/ai-function-set.ts @@ -0,0 +1,106 @@ +import type * as types from './types.ts' +import { AIFunctionsProvider } from './fns.js' + +/** + * A set of AI functions intended to make it easier to work with large sets of + * AI functions across different clients. + * + * This class mimics a built-in `Set`, but with additional utility + * methods like `pick`, `omit`, and `map`. + * + * Function names are case-insensitive to make it easier to match them with + * possible LLM hallucinations. + */ +export class AIFunctionSet implements Iterable { + protected readonly _map: Map + + constructor(aiFunctionLikeObjects?: types.AIFunctionLike[]) { + const fns = aiFunctionLikeObjects?.flatMap((fn) => + fn instanceof AIFunctionsProvider + ? [...fn.functions] + : fn instanceof AIFunctionSet + ? [...fn] + : [fn] + ) + + this._map = new Map( + fns ? fns.map((fn) => [transformName(fn.spec.name), fn]) : null + ) + } + + get size(): number { + return this._map.size + } + + add(fn: types.AIFunction): this { + this._map.set(transformName(fn.spec.name), fn) + return this + } + + get(name: string): types.AIFunction | undefined { + return this._map.get(transformName(name)) + } + + set(name: string, fn: types.AIFunction): this { + this._map.set(transformName(name), fn) + return this + } + + has(name: string): boolean { + return this._map.has(transformName(name)) + } + + clear(): void { + this._map.clear() + } + + delete(name: string): boolean { + return this._map.delete(transformName(name)) + } + + pick(...keys: string[]): AIFunctionSet { + const keysToIncludeSet = new Set(keys.map(transformName)) + return new AIFunctionSet( + Array.from(this).filter((fn) => + keysToIncludeSet.has(transformName(fn.spec.name)) + ) + ) + } + + omit(...keys: string[]): AIFunctionSet { + const keysToExcludeSet = new Set(keys.map(transformName)) + return new AIFunctionSet( + Array.from(this).filter( + (fn) => !keysToExcludeSet.has(transformName(fn.spec.name)) + ) + ) + } + + map(fn: (fn: types.AIFunction) => T): T[] { + return [...this.entries].map(fn) + } + + get specs(): types.AIFunctionSpec[] { + return this.map((fn) => fn.spec) + } + + get toolSpecs(): types.AIToolSpec[] { + return this.map((fn) => ({ + type: 'function' as const, + function: fn.spec + })) + } + + get entries(): IterableIterator { + return this._map.values() + } + + [Symbol.iterator](): Iterator { + return this.entries + } +} + +function transformName(name: string): string { + // TODO: decamalize? + return name.toLowerCase() +} diff --git a/src/assert.ts b/src/assert.ts new file mode 100644 index 000000000..01d92535c --- /dev/null +++ b/src/assert.ts @@ -0,0 +1,32 @@ +/** + * Slightly modified version of [tiny-invariant](https://github.com/alexreardon/tiny-invariant). + * + * `assert` is used to [assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions) that the `condition` is [truthy](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy). + * + * 💥 `assert` will `throw` an `Error` if the `condition` is [falsey](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy) + * + * @example + * + * ```ts + * const value: Person | null = { name: 'Alex' }; + * assert(value, 'Expected value to be a person'); + * // type of `value`` has been narrowed to `Person` + * ``` + */ +export function assert( + condition: any, + /** + * Can provide a string, or a function that returns a string for cases where + * the message takes a fair amount of effort to compute. + */ + message?: string | (() => string) +): asserts condition { + if (condition) { + return + } + + const providedMessage: string | undefined = + typeof message === 'function' ? message() : message + + throw new Error(providedMessage ?? 'Assertion failed') +} diff --git a/src/create-ai-function.test.ts b/src/create-ai-function.test.ts new file mode 100644 index 000000000..94c3a62b0 --- /dev/null +++ b/src/create-ai-function.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from 'vitest' +import { z } from 'zod' + +import { createAIFunction } from './create-ai-function.js' + +const fullName = createAIFunction( + { + name: 'fullName', + description: 'Returns the full name of a person.', + inputSchema: z.object({ + first: z.string(), + last: z.string() + }) + }, + async ({ first, last }) => { + return `${first} ${last}` + } +) + +describe('createAIFunction()', () => { + it('exposes OpenAI function calling spec', () => { + expect(fullName.spec.name).toEqual('fullName') + expect(fullName.spec.description).toEqual( + 'Returns the full name of a person.' + ) + expect(fullName.spec.parameters).toEqual({ + properties: { + first: { type: 'string' }, + last: { type: 'string' } + }, + required: ['first', 'last'], + type: 'object', + additionalProperties: false + }) + }) + + it('executes the function', async () => { + expect(await fullName('{"first": "John", "last": "Doe"}')).toEqual( + 'John Doe' + ) + }) +}) diff --git a/src/create-ai-function.ts b/src/create-ai-function.ts new file mode 100644 index 000000000..c2988829f --- /dev/null +++ b/src/create-ai-function.ts @@ -0,0 +1,72 @@ +import type { z } from 'zod' + +import type * as types from './types.js' +import { parseStructuredOutput } from './parse-structured-output.js' +import { assert } from './utils.js' +import { zodToJsonSchema } from './zod-to-json-schema.js' + +/** + * Create a function meant to be used with OpenAI tool or function calling. + * + * The returned function will parse the arguments string and call the + * implementation function with the parsed arguments. + * + * The `spec` property of the returned function is the spec for adding the + * function to the OpenAI API `functions` property. + */ +export function createAIFunction, Return>( + spec: { + /** Name of the function. */ + name: string + /** Description of the function. */ + description?: string + /** Zod schema for the arguments string. */ + inputSchema: InputSchema + }, + /** Implementation of the function to call with the parsed arguments. */ + implementation: (params: z.infer) => types.MaybePromise +): types.AIFunction { + assert(spec.name, 'createAIFunction missing required "spec.name"') + assert( + spec.inputSchema, + 'createAIFunction missing required "spec.inputSchema"' + ) + assert(implementation, 'createAIFunction missing required "implementation"') + assert( + typeof implementation === 'function', + 'createAIFunction "implementation" must be a function' + ) + + /** Parse the arguments string, optionally reading from a message. */ + const parseInput = (input: string | types.Msg) => { + if (typeof input === 'string') { + return parseStructuredOutput(input, spec.inputSchema) + } else { + const args = input.function_call?.arguments + assert( + args, + `Missing required function_call.arguments for function ${spec.name}` + ) + return parseStructuredOutput(args, spec.inputSchema) + } + } + + // Call the implementation function with the parsed arguments. + const aiFunction: types.AIFunction = ( + input: string | types.Msg + ) => { + const parsedInput = parseInput(input) + return implementation(parsedInput) + } + + aiFunction.inputSchema = spec.inputSchema + aiFunction.parseInput = parseInput + aiFunction.spec = { + name: spec.name, + description: spec.description?.trim() ?? '', + parameters: zodToJsonSchema(spec.inputSchema) + } + aiFunction.impl = implementation + + return aiFunction +} diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 000000000..d6e43f6ae --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,5 @@ +export class RetryableError extends Error {} + +export class ParseError extends RetryableError {} + +export class TimeoutError extends Error {} diff --git a/src/fns.ts b/src/fns.ts new file mode 100644 index 000000000..7f420da50 --- /dev/null +++ b/src/fns.ts @@ -0,0 +1,106 @@ +import type { z } from 'zod' + +import type * as types from './types.js' +import { AIFunctionSet } from './ai-function-set.js' +import { createAIFunction } from './create-ai-function.js' +import { assert } from './utils.js' + +export interface PrivateAIFunctionMetadata { + name: string + description: string + inputSchema: z.AnyZodObject + methodName: string +} + +// Polyfill for `Symbol.metadata` +// https://github.com/microsoft/TypeScript/issues/53461 +declare global { + interface SymbolConstructor { + readonly metadata: unique symbol + } +} + +;(Symbol as any).metadata ??= Symbol.for('Symbol.metadata') + +const _metadata = Object.create(null) + +if (typeof Symbol === 'function' && Symbol.metadata) { + Object.defineProperty(globalThis, Symbol.metadata, { + enumerable: true, + configurable: true, + writable: true, + value: _metadata + }) +} + +export abstract class AIFunctionsProvider { + private _functions?: AIFunctionSet + + get functions(): AIFunctionSet { + if (!this._functions) { + const metadata = this.constructor[Symbol.metadata] + assert(metadata) + const invocables = + (metadata?.invocables as PrivateAIFunctionMetadata[]) ?? [] + // console.log({ metadata, invocables }) + + const aiFunctions = invocables.map((invocable) => { + const impl = (this as any)[invocable.methodName] + assert(impl) + + return createAIFunction(invocable, impl) + }) + + this._functions = new AIFunctionSet(aiFunctions) + } + + return this._functions + } +} + +export function aiFunction< + This extends AIFunctionsProvider, + InputSchema extends z.SomeZodObject, + OptionalArgs extends Array, + Return extends types.MaybePromise +>({ + name, + description, + inputSchema +}: { + name?: string + description: string + inputSchema: InputSchema +}) { + return ( + _targetMethod: ( + this: This, + input: z.infer, + ...optionalArgs: OptionalArgs + ) => Return, + context: ClassMethodDecoratorContext< + This, + ( + this: This, + input: z.infer, + ...optionalArgs: OptionalArgs + ) => Return + > + ) => { + const methodName = String(context.name) + if (!context.metadata.invocables) { + context.metadata.invocables = [] + } + + ;(context.metadata.invocables as PrivateAIFunctionMetadata[]).push({ + name: name ?? methodName, + description, + inputSchema, + methodName + }) + + context.addInitializer(function () { + ;(this as any)[methodName] = (this as any)[methodName].bind(this) + }) + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..f5e89ccd0 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,12 @@ +export * from './ai-function-set.js' +export * from './create-ai-function.js' +export * from './errors.js' +export * from './fns.js' +export * from './message.js' +export * from './nango.js' +export * from './parse-structured-output.js' +export * from './services/index.js' +export * from './tools/search-and-crawl.js' +export type * from './types.js' +export * from './utils.js' +export * from './zod-to-json-schema.js' diff --git a/src/message.test.ts b/src/message.test.ts new file mode 100644 index 000000000..3da4301f9 --- /dev/null +++ b/src/message.test.ts @@ -0,0 +1,55 @@ +import type * as OpenAI from 'openai-fetch' +import { describe, expect, expectTypeOf, it } from 'vitest' + +import type * as types from './types.js' +import { Msg } from './message.js' + +describe('Msg', () => { + it('creates a message and fixes indentation', () => { + const msgContent = ` + Hello, World! + ` + const msg = Msg.system(msgContent) + expect(msg.role).toEqual('system') + expect(msg.content).toEqual('Hello, World!') + }) + + it('supports disabling indentation fixing', () => { + const msgContent = ` + Hello, World! + ` + const msg = Msg.system(msgContent, { cleanContent: false }) + expect(msg.content).toEqual('\n Hello, World!\n ') + }) + + it('handles tool calls request', () => { + const msg = Msg.toolCall([ + { + id: 'fake-tool-call-id', + type: 'function', + function: { + arguments: '{"prompt": "Hello, World!"}', + name: 'hello' + } + } + ]) + expectTypeOf(msg).toMatchTypeOf() + expect(Msg.isToolCall(msg)).toBe(true) + }) + + it('handles tool call response', () => { + const msg = Msg.toolResult('Hello, World!', 'fake-tool-call-id') + expectTypeOf(msg).toMatchTypeOf() + expect(Msg.isToolResult(msg)).toBe(true) + }) + + it('prompt message types should interop with openai-fetch message types', () => { + expectTypeOf({} as OpenAI.ChatMessage).toMatchTypeOf() + expectTypeOf({} as types.Msg).toMatchTypeOf() + expectTypeOf({} as types.Msg.System).toMatchTypeOf() + expectTypeOf({} as types.Msg.User).toMatchTypeOf() + expectTypeOf({} as types.Msg.Assistant).toMatchTypeOf() + expectTypeOf({} as types.Msg.FuncCall).toMatchTypeOf() + expectTypeOf({} as types.Msg.FuncResult).toMatchTypeOf() + }) +}) diff --git a/src/message.ts b/src/message.ts new file mode 100644 index 000000000..6202c252b --- /dev/null +++ b/src/message.ts @@ -0,0 +1,344 @@ +import type { Jsonifiable } from 'type-fest' + +import { cleanStringForModel, stringifyForModel } from './utils.js' + +/** + * Generic/default OpenAI message without any narrowing applied. + */ +export interface Msg { + /** + * The contents of the message. `content` is required for all messages, and + * may be null for assistant messages with function calls. + */ + content: string | null + + /** + * The role of the messages author. One of `system`, `user`, `assistant`, + * 'tool', or `function`. + */ + role: Msg.Role + + /** + * The name and arguments of a function that should be called, as generated + * by the model. + */ + function_call?: Msg.Call.Function + + /** + * The tool calls generated by the model, such as function calls. + */ + tool_calls?: Msg.Call.Tool[] + + /** + * Tool call that this message is responding to. + */ + tool_call_id?: string + + /** + * The name of the author of this message. `name` is required if role is + * `function`, and it should be the name of the function whose response is in the + * `content`. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of + * 64 characters. + */ + name?: string +} + +/** Narrowed OpenAI Message types. */ +export namespace Msg { + /** Possible roles for a message. */ + export type Role = 'system' | 'user' | 'assistant' | 'function' | 'tool' + + export namespace Call { + /** + * The name and arguments of a function that should be called, as generated + * by the model. + */ + export type Function = { + /** + * The arguments to call the function with, as generated by the model in + * JSON format. + */ + arguments: string + + /** The name of the function to call. */ + name: string + } + + /** The tool calls generated by the model, such as function calls. */ + export type Tool = { + /** The ID of the tool call. */ + id: string + + /** The type of the tool. Currently, only `function` is supported. */ + type: 'function' + + /** The function that the model called. */ + function: Call.Function + } + } + + /** Message with text content for the system. */ + export type System = { + role: 'system' + content: string + name?: string + } + + /** Message with text content from the user. */ + export type User = { + role: 'user' + name?: string + content: string + } + + /** Message with text content from the assistant. */ + export type Assistant = { + role: 'assistant' + name?: string + content: string + } + + /** Message with arguments to call a function. */ + export type FuncCall = { + role: 'assistant' + name?: string + content: null + function_call: Call.Function + } + + /** Message with the result of a function call. */ + export type FuncResult = { + role: 'function' + name: string + content: string + } + + /** Message with arguments to call one or more tools. */ + export type ToolCall = { + role: 'assistant' + name?: string + content: null + tool_calls: Call.Tool[] + } + + /** Message with the result of a tool call. */ + export type ToolResult = { + role: 'tool' + tool_call_id: string + content: string + } +} + +/** Utility functions for creating and checking message types. */ +export namespace Msg { + /** Create a system message. Cleans indentation and newlines by default. */ + export function system( + content: string, + opts?: { + /** Custom name for the message. */ + name?: string + /** Whether to clean extra newlines and indentation. Defaults to true. */ + cleanContent?: boolean + } + ): Msg.System { + const { name, cleanContent = true } = opts ?? {} + return { + role: 'system', + content: cleanContent ? cleanStringForModel(content) : content, + ...(name ? { name } : {}) + } + } + + /** Create a user message. Cleans indentation and newlines by default. */ + export function user( + content: string, + opts?: { + /** Custom name for the message. */ + name?: string + /** Whether to clean extra newlines and indentation. Defaults to true. */ + cleanContent?: boolean + } + ): Msg.User { + const { name, cleanContent = true } = opts ?? {} + return { + role: 'user', + content: cleanContent ? cleanStringForModel(content) : content, + ...(name ? { name } : {}) + } + } + + /** Create an assistant message. Cleans indentation and newlines by default. */ + export function assistant( + content: string, + opts?: { + /** Custom name for the message. */ + name?: string + /** Whether to clean extra newlines and indentation. Defaults to true. */ + cleanContent?: boolean + } + ): Msg.Assistant { + const { name, cleanContent = true } = opts ?? {} + return { + role: 'assistant', + content: cleanContent ? cleanStringForModel(content) : content, + ...(name ? { name } : {}) + } + } + + /** Create a function call message with argumets. */ + export function funcCall( + function_call: { + /** Name of the function to call. */ + name: string + /** Arguments to pass to the function. */ + arguments: string + }, + opts?: { + /** The name descriptor for the message.(message.name) */ + name?: string + } + ): Msg.FuncCall { + return { + ...opts, + role: 'assistant', + content: null, + function_call + } + } + + /** Create a function result message. */ + export function funcResult( + content: Jsonifiable, + name: string + ): Msg.FuncResult { + const contentString = stringifyForModel(content) + return { role: 'function', content: contentString, name } + } + + /** Create a function call message with argumets. */ + export function toolCall( + tool_calls: Msg.Call.Tool[], + opts?: { + /** The name descriptor for the message.(message.name) */ + name?: string + } + ): Msg.ToolCall { + return { + ...opts, + role: 'assistant', + content: null, + tool_calls + } + } + + /** Create a tool call result message. */ + export function toolResult( + content: Jsonifiable, + tool_call_id: string, + opts?: { + /** The name of the tool which was called */ + name?: string + } + ): Msg.ToolResult { + const contentString = stringifyForModel(content) + return { ...opts, role: 'tool', tool_call_id, content: contentString } + } + + /** Get the narrowed message from an EnrichedResponse. */ + export function getMessage( + // @TODO + response: any + // response: ChatModel.EnrichedResponse + ): Msg.Assistant | Msg.FuncCall | Msg.ToolCall { + const msg = response.choices[0].message as Msg + return narrowResponseMessage(msg) + } + + /** Narrow a message received from the API. It only responds with role=assistant */ + export function narrowResponseMessage( + msg: Msg + ): Msg.Assistant | Msg.FuncCall | Msg.ToolCall { + if (msg.content === null && msg.tool_calls != null) { + return Msg.toolCall(msg.tool_calls) + } else if (msg.content === null && msg.function_call != null) { + return Msg.funcCall(msg.function_call) + } else if (msg.content !== null) { + return Msg.assistant(msg.content) + } else { + // @TODO: probably don't want to error here + console.log('Invalid message', msg) + throw new Error('Invalid message') + } + } + + /** Check if a message is a system message. */ + export function isSystem(message: Msg): message is Msg.System { + return message.role === 'system' + } + /** Check if a message is a user message. */ + export function isUser(message: Msg): message is Msg.User { + return message.role === 'user' + } + /** Check if a message is an assistant message. */ + export function isAssistant(message: Msg): message is Msg.Assistant { + return message.role === 'assistant' && message.content !== null + } + /** Check if a message is a function call message with arguments. */ + export function isFuncCall(message: Msg): message is Msg.FuncCall { + return message.role === 'assistant' && message.function_call != null + } + /** Check if a message is a function result message. */ + export function isFuncResult(message: Msg): message is Msg.FuncResult { + return message.role === 'function' && message.name != null + } + /** Check if a message is a tool calls message. */ + export function isToolCall(message: Msg): message is Msg.ToolCall { + return message.role === 'assistant' && message.tool_calls != null + } + /** Check if a message is a tool call result message. */ + export function isToolResult(message: Msg): message is Msg.ToolResult { + return message.role === 'tool' && !!message.tool_call_id + } + + /** Narrow a ChatModel.Message to a specific type. */ + export function narrow(message: Msg.System): Msg.System + export function narrow(message: Msg.User): Msg.User + export function narrow(message: Msg.Assistant): Msg.Assistant + export function narrow(message: Msg.FuncCall): Msg.FuncCall + export function narrow(message: Msg.FuncResult): Msg.FuncResult + export function narrow(message: Msg.ToolCall): Msg.ToolCall + export function narrow(message: Msg.ToolResult): Msg.ToolResult + export function narrow( + message: Msg + ): + | Msg.System + | Msg.User + | Msg.Assistant + | Msg.FuncCall + | Msg.FuncResult + | Msg.ToolCall + | Msg.ToolResult { + if (isSystem(message)) { + return message + } + if (isUser(message)) { + return message + } + if (isAssistant(message)) { + return message + } + if (isFuncCall(message)) { + return message + } + if (isFuncResult(message)) { + return message + } + if (isToolCall(message)) { + return message + } + if (isToolResult(message)) { + return message + } + throw new Error('Invalid message type') + } +} diff --git a/src/nango.ts b/src/nango.ts new file mode 100644 index 000000000..3dbb0e6ae --- /dev/null +++ b/src/nango.ts @@ -0,0 +1,47 @@ +import { type Connection, Nango } from '@nangohq/node' + +import { getEnv } from './utils.js' + +// This is intentionally left as a global singleton to avoid re-creating the +// Nango connection instance on successive calls in serverless environments. +let _nango: Nango | null = null + +export function getNango(): Nango { + if (!_nango) { + const secretKey = getEnv('NANGO_SECRET_KEY')?.trim() + if (!secretKey) { + throw new Error(`Missing required "NANGO_SECRET_KEY"`) + } + + _nango = new Nango({ secretKey }) + } + + return _nango +} + +export function validateNangoConnectionOAuthScopes({ + connection, + scopes +}: { + connection: Connection + scopes: string[] +}) { + const connectionScopes = new Set( + connection.credentials.raw.scope.split(' ') + ) + const missingScopes = new Set() + + for (const scope of scopes) { + if (!connectionScopes.has(scope)) { + missingScopes.add(scope) + } + } + + if (missingScopes.size > 0) { + throw new Error( + `Nango connection ${connection.id} is missing required OAuth scopes: ${[ + ...missingScopes.values() + ].join(', ')}` + ) + } +} diff --git a/src/parse-structured-output.test.ts b/src/parse-structured-output.test.ts new file mode 100644 index 000000000..63ffe61e4 --- /dev/null +++ b/src/parse-structured-output.test.ts @@ -0,0 +1,273 @@ +import { assert, expect, test } from 'vitest' +import { z } from 'zod' + +import { + extractJSONFromString, + parseArrayOutput, + parseBooleanOutput, + parseNumberOutput, + parseObjectOutput, + parseStructuredOutput +} from './parse-structured-output.js' + +test('extractJSONFromString should extract JSON object from string', () => { + let jsonStr = 'Some text {"name":"John Doe"} more text' + let result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { name: 'John Doe' }) + + jsonStr = + 'Some text {"name":"John Doe","age":42,"address":{"street":"Main Street","number":42}} more text' + result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { + name: 'John Doe', + age: 42, + address: { street: 'Main Street', number: 42 } + }) + + jsonStr = 'foo {"name":"John Doe","school":"St. John\'s"} bar' + result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { name: 'John Doe', school: "St. John's" }) +}) + +test('extractJSONFromString should extract an invalid JSON object from string', () => { + let jsonStr = 'Some text {"name":\'John Doe\'} more text' + let result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { name: 'John Doe' }) + + jsonStr = 'Some text {"name":"John Doe","age":42,} more text' + result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { name: 'John Doe', age: 42 }) +}) + +test('extractJSONFromString should extract multiple JSON objects from string', () => { + let jsonStr = 'Some text {"name":"John Doe"} more text {"name":"Jane Doe"}' + let result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { name: 'John Doe' }) + assert.deepEqual(result[1], { name: 'Jane Doe' }) + + jsonStr = + 'Some text {"name":"John Doe","age":42,"address":{"street":"Main Street","number":42}} more text {"name":"Jane Doe","age":42,"address":{"street":"Main Street","number":42}}' + result = extractJSONFromString(jsonStr, 'object') + assert.deepEqual(result[0], { + name: 'John Doe', + age: 42, + address: { street: 'Main Street', number: 42 } + }) + assert.deepEqual(result[1], { + name: 'Jane Doe', + age: 42, + address: { street: 'Main Street', number: 42 } + }) +}) + +test('extractJSONFromString should extract JSON array from string', () => { + let jsonString = 'Some text [1,2,3] more text' + let result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result[0], [1, 2, 3]) + + jsonString = 'Some text ["foo","bar","\'quoted\'"] more text' + result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result[0], ['foo', 'bar', "'quoted'"]) +}) + +test('extractJSONFromString should extract an invalid JSON array from string', () => { + let jsonString = 'Some text [1,2,3,] more text' + let result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result[0], [1, 2, 3]) + + jsonString = "Some text ['foo','bar'] more text" + result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result[0], ['foo', 'bar']) +}) + +test('extractJSONFromString should extract multiple JSON arrays from string', () => { + const jsonString = 'Some text [1,2,3] more text [4,5,6]' + const result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result[0], [1, 2, 3]) + assert.deepEqual(result[1], [4, 5, 6]) +}) + +test('extractJSONFromString should return an empty array if no JSON object is found', () => { + const jsonString = 'Some text' + const result = extractJSONFromString(jsonString, 'object') + assert.deepEqual(result, []) +}) + +test('extractJSONFromString should return an empty array if no JSON array is found', () => { + const jsonString = 'Some text' + const result = extractJSONFromString(jsonString, 'array') + assert.deepEqual(result, []) +}) + +test('parseArrayOutput - handles valid arrays correctly', () => { + const output1 = parseArrayOutput('[1,2,3]') + const output2 = parseArrayOutput('["a", "b", "c"]') + const output3 = parseArrayOutput('[{"a": 1}, {"b": 2}]') + + expect(output1).toMatchSnapshot('should return [1, 2, 3] for "[1,2,3]"') + expect(output2).toMatchSnapshot( + 'should return ["a", "b", "c"] for "["a", "b", "c"]' + ) + expect(output3).toMatchSnapshot( + 'should return [{"a": 1}, {"b": 2}] for [{"a": 1}, {"b": 2}]' + ) +}) + +test('parseArrayOutput - handles arrays surrounded by text correctly', () => { + const output1 = parseArrayOutput('The array is [1,2,3]') + const output2 = parseArrayOutput('Array: ["a", "b", "c"]. That\'s all!') + const output3 = parseArrayOutput( + 'This is the array [{"a": 1}, {"b": 2}] in the text' + ) + + expect(output1).toMatchSnapshot( + 'should return [1, 2, 3] for "The array is [1,2,3]"' + ) + expect(output2).toMatchSnapshot( + 'should return ["a", "b", "c"] for "Array: ["a", "b", "c"]. That\'s all!"' + ) + expect(output3).toMatchSnapshot( + 'should return [{"a": 1}, {"b": 2}] for "This is the array [{"a": 1}, {"b": 2}] in the text"' + ) +}) + +test('parseArrayOutput - throws error for invalid arrays', () => { + assert.throws(() => { + parseArrayOutput('not a valid array') + }) +}) + +test('parseObjectOutput - handles valid objects correctly', () => { + const output1 = parseObjectOutput('{"a":1,"b":2,"c":3}') + const output2 = parseObjectOutput( + '{"name":"John","age":30,"city":"New York"}' + ) + + expect(output1).toMatchSnapshot( + 'should return {"a":1,"b":2,"c":3} for {"a":1,"b":2,"c":3}' + ) + expect(output2).toMatchSnapshot( + 'should return {"name":"John","age":30,"city":"New York"} for {"name":"John","age":30,"city":"New York"}' + ) +}) + +test('parseObjectOutput - handles objects surrounded by text correctly', () => { + const output1 = parseObjectOutput('The object is {"a":1,"b":2,"c":3}') + const output2 = parseObjectOutput( + 'Object: {"name":"John","age":30,"city":"New York"}. That\'s all!' + ) + + expect(output1).toMatchSnapshot( + 'should return {"a":1,"b":2,"c":3} for "The object is {"a":1,"b":2,"c":3}"' + ) + expect(output2).toMatchSnapshot( + 'should return {"name":"John","age":30,"city":"New York"} for "Object: {"name":"John","age":30,"city":"New York"}. That\'s all!"' + ) +}) + +test('parseObjectOutput - handles JSON array of objects', () => { + const output = parseObjectOutput('[{"a":1,"b":2},{"c":3,"d":4}]') + + expect(output).toMatchSnapshot( + 'should return first object {"a":1,"b":2} for [{"a":1,"b":2},{"c":3,"d":4}]' + ) +}) + +test('parseObjectOutput - throws error for invalid objects', () => { + assert.throws(() => { + parseObjectOutput('not a valid object') + }) +}) + +test('parseBooleanOutput - handles `true` outputs correctly', () => { + const output1 = parseBooleanOutput('True') + const output2 = parseBooleanOutput('TRUE') + const output3 = parseBooleanOutput('true.') + + expect(output1).toMatchSnapshot('should return true for "True"') + expect(output2).toMatchSnapshot('should return true for "TRUE"') + expect(output3).toMatchSnapshot('should return true for "true."') +}) + +test('parseBooleanOutput - handles `false` outputs correctly', () => { + const output1 = parseBooleanOutput('False') + const output2 = parseBooleanOutput('FALSE') + const output3 = parseBooleanOutput('false!') + + expect(output1).toMatchSnapshot('should return false for "False"') + expect(output2).toMatchSnapshot('should return false for "FALSE"') + expect(output3).toMatchSnapshot('should return false for "false!"') +}) + +test('parseBooleanOutput - throws error for invalid outputs', () => { + assert.throws(() => { + parseBooleanOutput('NotBooleanValue') + }) +}) + +test('parseNumberOutput - handles integer outputs correctly', () => { + const output1 = parseNumberOutput('42', z.number().int()) + const output2 = parseNumberOutput(' -5 ', z.number().int()) + + expect(output1).toMatchSnapshot('should return 42 for "42"') + expect(output2).toMatchSnapshot('should return -5 for " -5 "') +}) + +test('parseNumberOutput - handles float outputs correctly', () => { + const output1 = parseNumberOutput('42.42', z.number()) + const output2 = parseNumberOutput(' -5.5 ', z.number()) + + expect(output1).toMatchSnapshot('should return 42.42 for "42.42"') + expect(output2).toMatchSnapshot('should return -5.5 for " -5.5 "') +}) + +test('parseNumberOutput - throws error for invalid outputs', () => { + assert.throws(() => { + parseNumberOutput('NotANumber', z.number()) + }) +}) + +test('parseStructuredOutput - handles arrays correctly', () => { + const arraySchema = z.array(z.number()) + const output = '[1, 2, 3]' + const result = parseStructuredOutput(output, arraySchema) + + expect(result).toMatchSnapshot( + 'should parse and return [1, 2, 3] for "[1, 2, 3]"' + ) +}) + +test('parseStructuredOutput - handles objects correctly', () => { + const objectSchema = z.object({ a: z.number(), b: z.string() }) + const output = '{"a": 1, "b": "two"}' + const result = parseStructuredOutput(output, objectSchema) + + expect(result).toMatchSnapshot( + 'should parse and return {"a": 1, "b": "two"} for "{"a": 1, "b": "two"}"' + ) +}) + +test('parseStructuredOutput - handles booleans correctly', () => { + const booleanSchema = z.boolean() + const output = 'True' + const result = parseStructuredOutput(output, booleanSchema) + + expect(result).toMatchSnapshot('should parse and return true for "True"') +}) + +test('parseStructuredOutput - handles numbers correctly', () => { + const numberSchema = z.number() + const output = '123.45' + const result = parseStructuredOutput(output, numberSchema) + + expect(result).toMatchSnapshot('should parse and return 123.45 for "123.45"') +}) + +test('parseStructuredOutput - throws error for invalid data', () => { + const numberSchema = z.number() + const output = 'not a number' + + assert.throws(() => { + parseStructuredOutput(output, numberSchema) + }) +}) diff --git a/src/parse-structured-output.ts b/src/parse-structured-output.ts new file mode 100644 index 000000000..f93bd471d --- /dev/null +++ b/src/parse-structured-output.ts @@ -0,0 +1,283 @@ +import type { JsonValue } from 'type-fest' +import { jsonrepair, JSONRepairError } from 'jsonrepair' +import { z, type ZodType } from 'zod' + +import { ParseError } from './errors.js' + +export type SafeParseResult = + | { + success: true + data: T + error?: never + } + | { + success: false + data?: never + error: string + } + +/** + * Parses a string which is expected to contain a structured JSON value. + * + * The JSON value is fuzzily parsed in order to support common issues like + * missing commas, trailing commas, and unquoted keys. + * + * The JSON value is then parsed against a `zod` schema to enforce the shape of + * the output. + * + * @param output - string to parse + * @param outputSchema - zod schema + * + * @returns parsed output + */ +export function parseStructuredOutput( + output: string, + outputSchema: ZodType +): T { + let result + if (outputSchema instanceof z.ZodArray) { + result = parseArrayOutput(output) + } else if (outputSchema instanceof z.ZodObject) { + result = parseObjectOutput(output) + } else if (outputSchema instanceof z.ZodBoolean) { + result = parseBooleanOutput(output) + } else if (outputSchema instanceof z.ZodNumber) { + result = parseNumberOutput(output, outputSchema) + } else { + // Default to string output... + result = output + } + + // TODO: fix typescript issue here with recursive types + const safeResult = (outputSchema.safeParse as any)(result) + + if (!safeResult.success) { + throw new ParseError(safeResult.error) + } + + return safeResult.data +} + +export function safeParseStructuredOutput( + output: string, + outputSchema: ZodType +): SafeParseResult { + try { + const data = parseStructuredOutput(output, outputSchema) + return { + success: true, + data + } + } catch (err: any) { + return { + success: false, + error: err.message + } + } +} + +/** + * Checks if character at the specified index in a string is escaped. + * + * @param str - string to check + * @param i - index of the character to check + * @returns whether the character is escaped + */ +function isEscaped(str: string, i: number): boolean { + return i > 0 && str[i - 1] === '\\' && !(i > 1 && str[i - 2] === '\\') +} + +/** + * Extracts JSON objects or arrays from a string. + * + * @param input - string to extract JSON from + * @param jsonStructureType - type of JSON structure to extract + * @returns array of extracted JSON objects or arrays + */ +export function extractJSONFromString( + input: string, + jsonStructureType: 'object' | 'array' +) { + const startChar = jsonStructureType === 'object' ? '{' : '[' + const endChar = jsonStructureType === 'object' ? '}' : ']' + const extractedJSONValues: JsonValue[] = [] + let nestingLevel = 0 + let startIndex = 0 + const isInsideQuoted = { '"': false, "'": false } + + for (let i = 0; i < input.length; i++) { + const ch = input.charAt(i) + switch (ch) { + case '"': + case "'": + if (!isInsideQuoted[ch === '"' ? "'" : '"'] && !isEscaped(input, i)) { + isInsideQuoted[ch] = !isInsideQuoted[ch] + } + + break + + default: + if (!isInsideQuoted['"'] && !isInsideQuoted["'"]) { + switch (ch) { + case startChar: + if (nestingLevel === 0) { + startIndex = i + } + + nestingLevel += 1 + + break + + case endChar: + nestingLevel -= 1 + if (nestingLevel === 0) { + const candidate = input.slice(startIndex, i + 1) + const parsed = JSON.parse(jsonrepair(candidate)) + if (parsed && typeof parsed === 'object') { + extractedJSONValues.push(parsed as JsonValue) + } + } else if (nestingLevel < 0) { + throw new ParseError( + `Invalid JSON string: unexpected ${endChar} at position ${i}` + ) + } + } + } + } + } + + if (nestingLevel !== 0) { + throw new ParseError( + 'Invalid JSON string: unmatched ' + startChar + ' or ' + endChar + ) + } + + return extractedJSONValues +} + +const BOOLEAN_OUTPUTS: Record = { + true: true, + false: false, + t: true, + f: false, + yes: true, + no: false, + y: true, + n: false, + '1': true, + '0': false +} + +/** + * Parses an array output from a string. + * + * @param output - string to parse + * @returns parsed array + */ +export function parseArrayOutput(output: string): Array { + try { + const arrayOutput = extractJSONFromString(output, 'array') + if (arrayOutput.length === 0) { + throw new ParseError(`Invalid JSON array: ${output}`) + } + + const parsedOutput = arrayOutput[0] + if (!Array.isArray(parsedOutput)) { + throw new ParseError( + `Invalid JSON array: ${JSON.stringify(parsedOutput)}` + ) + } + + return parsedOutput + } catch (err: any) { + if (err instanceof JSONRepairError) { + throw new ParseError(err.message, { cause: err }) + } else if (err instanceof SyntaxError) { + throw new ParseError(`Invalid JSON array: ${err.message}`, { cause: err }) + } else { + throw err + } + } +} + +/** + * Parses an object output from a string. + * + * @param output - string to parse + * @returns parsed object + */ +export function parseObjectOutput(output: string) { + try { + const arrayOutput = extractJSONFromString(output, 'object') + if (arrayOutput.length === 0) { + throw new ParseError(`Invalid JSON object: ${output}`) + } + + let parsedOutput = arrayOutput[0] + if (Array.isArray(parsedOutput)) { + // TODO + parsedOutput = parsedOutput[0] + } else if (typeof parsedOutput !== 'object') { + throw new ParseError( + `Invalid JSON object: ${JSON.stringify(parsedOutput)}` + ) + } + + return parsedOutput + } catch (err: any) { + if (err instanceof JSONRepairError) { + throw new ParseError(err.message, { cause: err }) + } else if (err instanceof SyntaxError) { + throw new ParseError(`Invalid JSON object: ${err.message}`, { + cause: err + }) + } else { + throw err + } + } +} + +/** + * Parses a boolean output from a string. + * + * @param output - string to parse + * @returns parsed boolean + */ +export function parseBooleanOutput(output: string): boolean { + output = output + .toLowerCase() + .trim() + .replace(/[!.?]+$/, '') + + const booleanOutput = BOOLEAN_OUTPUTS[output] + + if (booleanOutput === undefined) { + throw new ParseError(`Invalid boolean output: ${output}`) + } else { + return booleanOutput + } +} + +/** + * Parses a number output from a string. + * + * @param output - string to parse + * @param outputSchema - zod number schema + * @returns parsed number + */ +export function parseNumberOutput( + output: string, + outputSchema: z.ZodNumber +): number { + output = output.trim() + + const numberOutput = outputSchema.isInt + ? Number.parseInt(output) + : Number.parseFloat(output) + + if (Number.isNaN(numberOutput)) { + throw new ParseError(`Invalid number output: ${output}`) + } + + return numberOutput +} diff --git a/src/reset.d.ts b/src/reset.d.ts new file mode 100644 index 000000000..69fc8bf0a --- /dev/null +++ b/src/reset.d.ts @@ -0,0 +1 @@ +import '@total-typescript/ts-reset' diff --git a/src/sdks/ai-sdk.ts b/src/sdks/ai-sdk.ts new file mode 100644 index 000000000..7edaa5fe6 --- /dev/null +++ b/src/sdks/ai-sdk.ts @@ -0,0 +1,23 @@ +import { tool } from 'ai' + +import type { AIFunctionLike } from '../types.js' +import { AIFunctionSet } from '../ai-function-set.js' + +/** + * Converts a set of Agentic stdlib AI functions to an object compatible with + * the Vercel AI SDK's `tools` parameter. + */ +export function createAISDKTools(...aiFunctionLikeTools: AIFunctionLike[]) { + const fns = new AIFunctionSet(aiFunctionLikeTools) + + return Object.fromEntries( + fns.map((fn) => [ + fn.spec.name, + tool({ + description: fn.spec.description, + parameters: fn.inputSchema, + execute: fn.impl + }) + ]) + ) +} diff --git a/src/sdks/dexter.ts b/src/sdks/dexter.ts new file mode 100644 index 000000000..8e8df06f7 --- /dev/null +++ b/src/sdks/dexter.ts @@ -0,0 +1,25 @@ +import { createAIFunction } from '@dexaai/dexter' + +import type { AIFunctionLike } from '../types.js' +import { AIFunctionSet } from '../ai-function-set.js' + +/** + * Converts a set of Agentic stdlib AI functions to an array of Dexter- + * compatible AI functions. + */ +export function createDexterFunctions( + ...aiFunctionLikeTools: AIFunctionLike[] +) { + const fns = new AIFunctionSet(aiFunctionLikeTools) + + return fns.map((fn) => + createAIFunction( + { + name: fn.spec.name, + description: fn.spec.description, + argsSchema: fn.inputSchema + }, + fn.impl + ) + ) +} diff --git a/src/sdks/genkit.ts b/src/sdks/genkit.ts new file mode 100644 index 000000000..a9c454ba5 --- /dev/null +++ b/src/sdks/genkit.ts @@ -0,0 +1,25 @@ +import { defineTool } from '@genkit-ai/ai' +import { z } from 'zod' + +import type { AIFunctionLike } from '../types.js' +import { AIFunctionSet } from '../ai-function-set.js' + +/** + * Converts a set of Agentic stdlib AI functions to an array of Genkit- + * compatible tools. + */ +export function createGenkitTools(...aiFunctionLikeTools: AIFunctionLike[]) { + const fns = new AIFunctionSet(aiFunctionLikeTools) + + return fns.map((fn) => + defineTool( + { + name: fn.spec.name, + description: fn.spec.description, + inputSchema: fn.inputSchema, + outputSchema: z.any() + }, + fn.impl + ) + ) +} diff --git a/src/sdks/langchain.ts b/src/sdks/langchain.ts new file mode 100644 index 000000000..f1b0cf45d --- /dev/null +++ b/src/sdks/langchain.ts @@ -0,0 +1,27 @@ +import { DynamicStructuredTool } from '@langchain/core/tools' + +import type { AIFunctionLike } from '../types.js' +import { AIFunctionSet } from '../ai-function-set.js' +import { stringifyForModel } from '../utils.js' + +/** + * Converts a set of Agentic stdlib AI functions to an array of LangChain- + * compatible tools. + */ +export function createLangChainTools(...aiFunctionLikeTools: AIFunctionLike[]) { + const fns = new AIFunctionSet(aiFunctionLikeTools) + + return fns.map( + (fn) => + new DynamicStructuredTool({ + name: fn.spec.name, + description: fn.spec.description, + schema: fn.inputSchema, + func: async (input) => { + const result = await Promise.resolve(fn.impl(input)) + // LangChain tools require the output to be a string + return stringifyForModel(result) + } + }) + ) +} diff --git a/src/sdks/llamaindex.ts b/src/sdks/llamaindex.ts new file mode 100644 index 000000000..82c8a386c --- /dev/null +++ b/src/sdks/llamaindex.ts @@ -0,0 +1,22 @@ +import { FunctionTool } from 'llamaindex' + +import type { AIFunctionLike } from '../types.js' +import { AIFunctionSet } from '../ai-function-set.js' + +/** + * Converts a set of Agentic stdlib AI functions to an array of LlamaIndex- + * compatible tools. + */ +export function createLlamaIndexTools( + ...aiFunctionLikeTools: AIFunctionLike[] +) { + const fns = new AIFunctionSet(aiFunctionLikeTools) + + return fns.map((fn) => + FunctionTool.from(fn.impl, { + name: fn.spec.name, + description: fn.spec.description, + parameters: fn.spec.parameters as any + }) + ) +} diff --git a/src/services/bing-client.ts b/src/services/bing-client.ts new file mode 100644 index 000000000..e48c3704b --- /dev/null +++ b/src/services/bing-client.ts @@ -0,0 +1,310 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, omit } from '../utils.js' + +export namespace bing { + export const API_BASE_URL = 'https://api.bing.microsoft.com' + + export interface SearchQuery { + q: string + mkt?: string + offset?: number + count?: number + safeSearch?: 'Off' | 'Moderate' | 'Strict' + textDecorations?: boolean + textFormat?: 'Raw' | 'HTML' + } + + export interface SearchResponse { + _type: string + entities: Entities + images: Images + places: Places + queryContext: QueryContext + rankingResponse: RankingResponse + relatedSearches: RelatedSearches + videos: Videos + webPages: WebPages + } + + interface Entities { + value: EntitiesValue[] + } + + interface EntitiesValue { + bingId: string + contractualRules: PurpleContractualRule[] + description: string + entityPresentationInfo: EntityPresentationInfo + id: string + image: Image + name: string + webSearchUrl: string + } + + interface PurpleContractualRule { + _type: string + license?: DeepLink + licenseNotice?: string + mustBeCloseToContent: boolean + targetPropertyName: string + text?: string + url?: string + } + + interface DeepLink { + name: string + url: string + } + + interface EntityPresentationInfo { + entityScenario: string + entityTypeHints: string[] + } + + interface Image { + height: number + hostPageUrl: string + name: string + provider: Provider[] + sourceHeight: number + sourceWidth: number + thumbnailUrl: string + width: number + } + + interface Provider { + _type: string + url: string + } + + interface Images { + id: string + isFamilyFriendly: boolean + readLink: string + value: ImagesValue[] + webSearchUrl: string + } + + interface ImagesValue { + contentSize: string + contentUrl: string + encodingFormat: string + height: number + hostPageDisplayUrl: string + hostPageUrl: string + name: string + thumbnail: Thumbnail + thumbnailUrl: string + webSearchUrl: string + width: number + } + + interface Thumbnail { + height: number + width: number + } + + interface Places { + value: PlacesValue[] + } + + interface PlacesValue { + _type: string + address: Address + entityPresentationInfo: EntityPresentationInfo + id: string + name: string + telephone: string + url: string + webSearchUrl: string + } + + interface Address { + addressCountry: string + addressLocality: string + addressRegion: string + neighborhood: string + postalCode: string + } + + interface QueryContext { + askUserForLocation: boolean + originalQuery: string + } + + interface RankingResponse { + mainline: Mainline + sidebar: Mainline + } + + interface Mainline { + items: Item[] + } + + interface Item { + answerType: string + resultIndex?: number + value?: ItemValue + } + + interface ItemValue { + id: string + } + + interface RelatedSearches { + id: string + value: RelatedSearchesValue[] + } + + interface RelatedSearchesValue { + displayText: string + text: string + webSearchUrl: string + } + + interface Videos { + id: string + isFamilyFriendly: boolean + readLink: string + scenario: string + value: VideosValue[] + webSearchUrl: string + } + + interface VideosValue { + allowHttpsEmbed: boolean + allowMobileEmbed: boolean + contentUrl: string + creator: Creator + datePublished: Date + description: string + duration: string + embedHtml: string + encodingFormat: EncodingFormat + height: number + hostPageDisplayUrl: string + hostPageUrl: string + isAccessibleForFree: boolean + isSuperfresh: boolean + motionThumbnailUrl: string + name: string + publisher: Creator[] + thumbnail: Thumbnail + thumbnailUrl: string + viewCount: number + webSearchUrl: string + width: number + } + + interface Creator { + name: string + } + + enum EncodingFormat { + Mp4 = 'mp4' + } + + interface WebPages { + totalEstimatedMatches: number + value: WebPagesValue[] + webSearchUrl: string + } + + interface WebPagesValue { + dateLastCrawled: Date + deepLinks?: DeepLink[] + displayUrl: string + id: string + isFamilyFriendly: boolean + isNavigational: boolean + language: string + name: string + snippet: string + thumbnailUrl?: string + url: string + contractualRules?: FluffyContractualRule[] + } + + interface FluffyContractualRule { + _type: string + license: DeepLink + licenseNotice: string + mustBeCloseToContent: boolean + targetPropertyIndex: number + targetPropertyName: string + } +} + +/** + * Bing web search client. + * + * @see https://www.microsoft.com/en-us/bing/apis/bing-web-search-api + */ +export class BingClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('BING_API_KEY'), + apiBaseUrl = bing.API_BASE_URL, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'BingClient missing required "apiKey" (defaults to "BING_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl + }) + } + + @aiFunction({ + name: 'bing_web_search', + description: + 'Searches the web using the Bing search engine to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.', + inputSchema: z.object({ + q: z.string().describe('search query') + }) + }) + async search(queryOrOpts: string | bing.SearchQuery) { + const defaultQuery: Partial = { + mkt: 'en-US' + } + + const searchParams = + typeof queryOrOpts === 'string' + ? { + ...defaultQuery, + q: queryOrOpts + } + : { + ...defaultQuery, + ...queryOrOpts + } + + // console.log(searchParams) + const res = await this.ky + .get('v7.0/search', { + headers: { + 'Ocp-Apim-Subscription-Key': this.apiKey + }, + searchParams + }) + .json() + + return omit(res, 'rankingResponse') + } +} diff --git a/src/services/clearbit-client.ts b/src/services/clearbit-client.ts new file mode 100644 index 000000000..a04b5761a --- /dev/null +++ b/src/services/clearbit-client.ts @@ -0,0 +1,676 @@ +import defaultKy from 'ky' +import pThrottle from 'p-throttle' + +import type { DeepNullable, KyInstance } from '../types.js' +import { assert, delay, getEnv, throttleKy } from '../utils.js' + +export namespace clearbit { + // Allow up to 600 requests per minute by default. + export const throttle = pThrottle({ + limit: 600, + interval: 60 * 1000 + }) + + export interface CompanyEnrichmentOptions { + domain: string + webhook_url?: string + company_name?: string + linkedin?: string + twitter?: string + facebook?: string + } + + export type CompanyNullableProps = { + name: string + legalName: string + domain: string + domainAliases: string[] + site: { + phoneNumbers: string[] + emailAddresses: string[] + } + category: { + sector: string + industryGroup: string + industry: string + subIndustry: string + gicsCode: string + sicCode: string + sic4Codes: string[] + naicsCode: string + naics6Codes: string[] + naics6Codes2022: string[] + } + tags: string[] + description: string + foundedYear: number + location: string + timeZone: string + utcOffset: number + geo: { + streetNumber: string + streetName: string + subPremise: string + streetAddress: string + city: string + postalCode: string + state: string + stateCode: string + country: string + countryCode: string + lat: number + lng: number + } + logo: string + facebook: { + handle: string + likes: number + } + linkedin: { + handle: string + } + twitter: { + handle: string + id: string + bio: string + followers: number + following: number + location: string + site: string + avatar: string + } + crunchbase: { + handle: string + } + emailProvider: boolean + type: string + ticker: string + identifiers: { + usEIN: string + usCIK: string + } + phone: string + metrics: { + alexaUsRank: number + alexaGlobalRank: number + trafficRank: string + employees: number + employeesRange: string + marketCap: string + raised: number + annualRevenue: string + estimatedAnnualRevenue: string + fiscalYearEnd: string + } + indexedAt: string + tech: string[] + techCategories: string[] + parent: { + domain: string + } + ultimateParent: { + domain: string + } + } + + export type EmailLookupResponse = DeepNullable<{ + id: string + name: { + fullName: string + givenName: string + familyName: string + } + email: string + location: string + timeZone: string + utcOffset: number + geo: { + city: string + state: string + stateCode: string + country: string + countryCode: string + lat: number + lng: number + } + bio: string + site: string + avatar: string + employment: { + domain: string + name: string + title: string + role: string + subRole: string + seniority: string + } + facebook: { + handle: string + } + github: { + handle: string + id: string + avatar: string + company: string + blog: string + followers: number + following: number + } + twitter: { + handle: string + id: string + bio: string + followers: number + following: number + statuses: number + favorites: number + location: string + site: string + avatar: string + } + linkedin: { + handle: string + } + googleplus: { + handle: null + } + gravatar: { + handle: string + urls: { + value: string + title: string + }[] + avatar: string + avatars: { + url: string + type: string + }[] + } + fuzzy: boolean + emailProvider: boolean + indexedAt: string + phone: string + activeAt: string + inactiveAt: string + }> + + export type CompanyResponse = { + id: string + } & DeepNullable + + export interface CompanySearchOptions { + /** + * See clearbit docs: https://dashboard.clearbit.com/docs?shell#discovery-api-tech-queries + * Examples: + * tech:google_apps + * or:(twitter_followers:10000~ type:nonprofit) + */ + query: string + page?: number + page_size?: number + limit?: number + sort?: string + } + + export interface CompanySearchResponse { + total: number + page: number + results: CompanyResponse[] + } + + export interface BasicCompanyResponse { + domain: string + logo: string + name: string + } + + export interface PeopleSearchOptionsV2 { + domains?: string[] + names?: string[] + roles?: string[] + seniorities?: string[] + titles?: string[] + locations?: string[] + employees_ranges?: string[] + company_tags?: string[] + company_tech?: string[] + company_types?: string[] + industries?: string[] + revenue_ranges?: string[] + linkedin_profile_handles?: string[] + page?: number + page_size?: number + suppression?: string + } + + // Prospector types + export interface ProspectorResponseV2 { + page: number + page_size: number + total: number + results: PersonAttributesV2[] + } + + export interface EmploymentAttributes { + company: string + domain: string + linkedin: string + title: string + role: string + subRole: string + seniority: string + startDate: string + endDate: string + present: boolean + highlight: boolean + } + + export interface EmailAttributes { + address: string + type: string + } + + export interface PhoneAttributes { + number: string + type: string + } + + interface Name { + givenName: string + familyName: string + fullName: string + } + + export type PersonAttributesV2 = { + id: string + } & DeepNullable<{ + name: Name + avatar: string + location: string + linkedin: string + employments: EmploymentAttributes[] + emails: EmailAttributes[] + phones: PhoneAttributes[] + }> + + export type PeopleSearchOptionsV1 = { + domain: string + role?: string + roles?: string[] + seniority?: string + seniorities?: string[] + title?: string + titles?: string[] + city?: string + cities?: string[] + state?: string + states?: string[] + country?: string + countries?: string[] + name?: string + query?: string + page?: number + page_size?: number + suppression?: string + email?: boolean + } + + export interface Company { + name: string + } + + export interface PeopleSearchResponseV1 { + id: string + name: Name + title: string + role: string + subRole: string + seniority: string + company: Company + email: string + verified: boolean + phone: string + } + + export interface ProspectorResponseV1 { + page: number + page_size: number + total: number + results: PeopleSearchResponseV1[] + } + + export interface GeoIP { + city: string + state: string + stateCode: string + country: string + countryCode: string + } + + export interface CompanyRevealResponse { + ip: string + fuzzy: boolean + domain: string + type: string + company?: CompanyResponse + geoIP: GeoIP + confidenceScore: 'very_high' | 'high' | 'medium' | 'low' + role: string + seniority: string + } +} + +/** + * The Clearbit API helps with resolving and enriching people and company data. + * + * @see https://dashboard.clearbit.com/docs + */ +export class ClearbitClient { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly _maxPageSize = 100 + + static readonly PersonRoles = [ + 'communications', + 'customer_service', + 'education', + 'engineering', + 'finance', + 'health_professional', + 'human_resources', + 'information_technology', + 'leadership', + 'legal', + 'marketing', + 'operations', + 'product', + 'public_relations', + 'real_estate', + 'recruiting', + 'research', + 'sales' + ] + + static readonly SenioritiesV2 = [ + 'Executive', + 'VP', + 'Owner', + 'Partner', + 'Director', + 'Manager', + 'Senior', + 'Entry' + ] + + static readonly Seniorities = ['executive', 'director', 'manager'] + + static readonly SubIndustries = [ + 'Automotive', + 'Consumer Discretionary', + 'Consumer Goods', + 'Consumer Electronics', + 'Household Appliances', + 'Photography', + 'Sporting Goods', + 'Apparel, Accessories & Luxury Goods', + 'Textiles', + 'Textiles, Apparel & Luxury Goods', + 'Consumer Services', + 'Education Services', + 'Specialized Consumer Services', + 'Casinos & Gaming', + 'Hotels, Restaurants & Leisure', + 'Leisure Facilities', + 'Restaurants', + 'Education', + 'Family Services', + 'Legal Services', + 'Advertising', + 'Broadcasting', + 'Media', + 'Movies & Entertainment', + 'Public Relations', + 'Publishing', + 'Distributors', + 'Retailing', + 'Home Improvement Retail', + 'Homefurnishing Retail', + 'Specialty Retail', + 'Consumer Staples', + 'Food Retail', + 'Beverages', + 'Agricultural Products', + 'Food', + 'Food Production', + 'Packaged Foods & Meats', + 'Tobacco', + 'Cosmetics', + 'Oil & Gas', + 'Banking & Mortgages', + 'Accounting', + 'Finance', + 'Financial Services', + 'Asset Management & Custody Banks', + 'Diversified Capital Markets', + 'Fundraising', + 'Investment Banking & Brokerage', + 'Payments', + 'Insurance', + 'Real Estate', + 'Eyewear', + 'Health & Wellness', + 'Health Care', + 'Health Care Services', + 'Biotechnology', + 'Life Sciences Tools & Services', + 'Pharmaceuticals', + 'Aerospace & Defense', + 'Capital Goods', + 'Civil Engineering', + 'Construction', + 'Construction & Engineering', + 'Mechanical Engineering', + 'Electrical', + 'Electrical Equipment', + 'Industrials & Manufacturing', + 'Industrial Machinery', + 'Machinery', + 'Trading Companies & Distributors', + 'Business Supplies', + 'Commercial Printing', + 'Corporate & Business', + 'Architecture', + 'Automation', + 'Consulting', + 'Design', + 'Human Resource & Employment Services', + 'Professional Services', + 'Research & Consulting Services', + 'Industrials', + 'Shipping & Logistics', + 'Airlines', + 'Marine', + 'Ground Transportation', + 'Transportation', + 'Semiconductors', + 'Cloud Services', + 'Internet', + 'Internet Software & Services', + 'Data Processing & Outsourced Services', + 'Graphic Design', + 'Communications', + 'Computer Networking', + 'Nanotechnology', + 'Computer Hardware', + 'Technology Hardware, Storage & Peripherals', + 'Building Materials', + 'Chemicals', + 'Commodity Chemicals', + 'Containers & Packaging', + 'Gold', + 'Metals & Mining', + 'Paper Products', + 'Integrated Telecommunication Services', + 'Wireless Telecommunication Services', + 'Renewable Energy', + 'Energy', + 'Utilities' + ] + + constructor({ + apiKey = getEnv('CLEARBIT_API_KEY'), + timeoutMs = 30_000, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + timeoutMs?: number + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'ClearbitClient missing required "apiKey" (defaults to "CLEARBIT_API_KEY")' + ) + + this.apiKey = apiKey + + const throttledKy = throttle ? throttleKy(ky, clearbit.throttle) : ky + + this.ky = throttledKy.extend({ + timeout: timeoutMs, + headers: { + // Authorization: `Basic ${Buffer.from(`${apiKey}:`).toString('base64')}` + Authorization: `Bearer ${apiKey}` + } + }) + } + + async companyEnrichment(options: clearbit.CompanyEnrichmentOptions) { + return this.ky + .get('https://company-stream.clearbit.com/v2/companies/find', { + searchParams: { ...options } + }) + .json() + } + + async companySearch(options: clearbit.CompanySearchOptions) { + return this.ky + .get('https://discovery.clearbit.com/v1/companies/search', { + searchParams: { ...options } + }) + .json() + } + + async companyAutocomplete(name: string) { + return this.ky + .get('https://autocomplete.clearbit.com/v1/companies/suggest', { + searchParams: { query: name } + }) + .json() + } + + async prospectorPeopleV2(options: clearbit.PeopleSearchOptionsV2) { + return this.ky + .get('https://prospector.clearbit.com/v2/people/search', { + // @ts-expect-error location is a string[] and searchparams shows a TS error heres + searchParams: { + ...options, + page_size: Math.min( + this._maxPageSize, + options.page_size || this._maxPageSize + ) + } + }) + .json() + } + + async prospectorPeopleV1(options: clearbit.PeopleSearchOptionsV1) { + return this.ky + .get('https://prospector.clearbit.com/v1/people/search', { + // @ts-expect-error location is a string[] and searchparams shows a TS error heres + searchParams: { + email: false, + ...options, + page_size: Math.min( + this._maxPageSize, + options.page_size || this._maxPageSize + ) + } + }) + .json() + } + + // TODO Status code = 202 means the response was queued. + // Implement webhook when needed. The polling works well, in most cases we need + // to try again once to get a 200 response. + async emailLookup({ + email, + maxRetries = 2 + }: { + email: string + maxRetries?: number + }): Promise { + const url = 'https://person.clearbit.com/v2/people/find' + let response = await this.ky.get(url, { + searchParams: { email } + }) + + if (response.status !== 202 || !maxRetries) { + return response.json() + } + + if (maxRetries && response.status === 202) { + let count = 0 + let running = true + while (running && count < maxRetries) { + console.log(`Email Lookup was queued, retry ${count + 1}.`) + await delay(1000) + response = await this.ky.get(url, { + searchParams: { email } + }) + count++ + running = response.status === 202 + } + return response.json() + } + + throw new Error('clearbit email lookup error 202', { cause: response }) + } + + async nameToDomain(name: string) { + return this.ky + .get('https://company.clearbit.com/v1/domains/find', { + searchParams: { name } + }) + .json() + .catch((_) => undefined) + } + + async revealCompanyFromIP(ip: string) { + return this.ky + .get('https://reveal.clearbit.com/v1/companies/find', { + searchParams: { ip } + }) + .json() + .catch((_) => undefined) + } + + static filterEmploymentProspectorV2( + companyName: string, + employments: Array | null> | null + ) { + if (employments && employments.length > 0) { + // We filter by employment endDate because some people could have multiple + // jobs at the same time. + // Here we want to filter by people that actively works at a specific company. + return employments + .filter((item) => !item?.endDate) + .some((item) => + item?.company?.toLowerCase().includes(companyName.toLowerCase()) + ) + } + + return false + } +} diff --git a/src/services/dexa-client.ts b/src/services/dexa-client.ts new file mode 100644 index 000000000..62f89554d --- /dev/null +++ b/src/services/dexa-client.ts @@ -0,0 +1,65 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { Msg } from '../message.js' +import { assert, getEnv } from '../utils.js' + +export namespace dexa { + export const AskDexaOptionsSchema = z.object({ + question: z.string().describe('The question to ask Dexa.') + }) + export type AskDexaOptions = z.infer +} + +/** + * Dexa provides answers from the world's best podcasters. + * + * @note The Dexa API is not yet publicly available. + * @see https://dexa.ai + */ +export class DexaClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('DEXA_API_KEY'), + apiBaseUrl = getEnv('DEXA_API_BASE_URL') ?? 'https://dexa.ai', + timeoutMs = 60_000, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + timeoutMs?: number + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'DexaClient missing required "apiKey" (defaults to "DEXA_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ prefixUrl: this.apiBaseUrl, timeout: timeoutMs }) + } + + @aiFunction({ + name: 'ask_dexa', + description: + 'Answers questions based on knowledge of trusted experts and podcasters. Example experts include: Andrew Huberman, Tim Ferriss, Lex Fridman, Peter Attia, Seth Godin, Rhonda Patrick, Rick Rubin, and more.', + inputSchema: dexa.AskDexaOptionsSchema + }) + async askDexa(opts: dexa.AskDexaOptions) { + return this.ky + .post('api/ask-dexa', { + json: { + secret: this.apiKey, + messages: [Msg.user(opts.question)] + } + }) + .json() + } +} diff --git a/src/services/diffbot-client.ts b/src/services/diffbot-client.ts new file mode 100644 index 000000000..6e2db91d4 --- /dev/null +++ b/src/services/diffbot-client.ts @@ -0,0 +1,810 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { + assert, + getEnv, + omit, + sanitizeSearchParams, + throttleKy +} from '../utils.js' + +export namespace diffbot { + export const API_BASE_URL = 'https://api.diffbot.com' + export const KNOWLEDGE_GRAPH_API_BASE_URL = 'https://kg.diffbot.com' + + // Allow up to 5 requests per second by default. + // https://docs.diffbot.com/reference/rate-limits + export const throttle = pThrottle({ + limit: 5, + interval: 1000, + strict: true + }) + + export interface ExtractOptions { + /** Specify optional fields to be returned from any fully-extracted pages, e.g.: &fields=querystring,links. See available fields within each API's individual documentation pages. + * @see https://docs.diffbot.com/reference/extract-optional-fields + */ + fields?: string[] + + /** (*Undocumented*) Pass paging=false to disable automatic concatenation of multiple-page articles. (By default, Diffbot will concatenate up to 20 pages of a single article.) */ + paging?: boolean + + /** Pass discussion=false to disable automatic extraction of comments or reviews from pages identified as articles or products. This will not affect pages identified as discussions. */ + discussion?: boolean + + /** Sets a value in milliseconds to wait for the retrieval/fetch of content from the requested URL. The default timeout for the third-party response is 30 seconds (30000). */ + timeout?: number + + /** Used to specify the IP address of a custom proxy that will be used to fetch the target page, instead of Diffbot's default IPs/proxies. (Ex: &proxy=168.212.226.204) */ + proxy?: string + + /** Used to specify the authentication parameters that will be used with the proxy specified in the &proxy parameter. (Ex: &proxyAuth=username:password) */ + proxyAuth?: string + + /** `none` will instruct Extract to not use proxies, even if proxies have been enabled for this particular URL globally. */ + useProxy?: string + + /** @see https://docs.diffbot.com/reference/extract-custom-javascript */ + customJs?: string + + /** @see https://docs.diffbot.com/reference/extract-custom-headers */ + customHeaders?: Record + } + + export interface ExtractAnalyzeOptions extends ExtractOptions { + /** URL of the web page to process */ + url: string + + /** By default the Analyze API will fully extract all pages that match an existing Automatic API -- articles, products or image pages. Set mode to a specific page-type (e.g., mode=article) to extract content only from that specific page-type. All other pages will simply return the default Analyze fields. */ + mode?: string + + /** Force any non-extracted pages (those with a type of "other") through a specific API. For example, to route all "other" pages through the Article API, pass &fallback=article. Pages that utilize this functionality will return a fallbackType field at the top-level of the response and a originalType field within each extracted object, both of which will indicate the fallback API used. */ + fallback?: string + } + + export interface ExtractArticleOptions extends ExtractOptions { + /** URL of the web page to process */ + url: string + + /** Set the maximum number of automatically-generated tags to return. By default a maximum of ten tags will be returned. */ + maxTags?: number + + /** Set the minimum relevance score of tags to return, between 0.0 and 1.0. By default only tags with a score equal to or above 0.5 will be returned. */ + tagConfidence?: number + + /** Used to request the output of the Diffbot Natural Language API in the field naturalLanguage. Example: &naturalLanguage=entities,facts,categories,sentiment. */ + naturalLanguage?: string[] + } + + export interface ExtractResponse { + request: DiffbotRequest + objects: DiffbotObject[] + } + + export type ExtractArticleResponse = ExtractResponse + + export interface ExtractAnalyzeResponse extends ExtractResponse { + type: string + title: string + humanLanguage: string + } + + export interface DiffbotObject { + date: string + sentiment: number + images: Image[] + author: string + estimatedDate: string + publisherRegion: string + icon: string + diffbotUri: string + siteName: string + type: string + title: string + tags: Tag[] + publisherCountry: string + humanLanguage: string + authorUrl: string + pageUrl: string + html: string + text: string + categories?: ObjectCategory[] + authors: Author[] + breadcrumb?: Breadcrumb[] + items?: ListItem[] + meta?: any + } + + export interface ListItem { + title: string + link: string + summary: string + image?: string + } + + export interface Author { + name: string + link: string + } + + export interface ObjectCategory { + score: number + name: string + id: string + } + + export interface Breadcrumb { + link: string + name: string + } + + export interface Image { + url: string + diffbotUri: string + + naturalWidth: number + naturalHeight: number + width: number + height: number + + isCached?: boolean + primary?: boolean + } + + export interface Tag { + score: number + sentiment: number + count: number + label: string + uri: string + rdfTypes: string[] + } + + export interface DiffbotRequest { + pageUrl: string + api: string + version: number + } + + export interface KnowledgeGraphSearchOptions { + type?: 'query' | 'text' | 'queryTextFallback' | 'crawl' + query: string + col?: string + from?: number + size?: number + + // NOTE: we only support `json`, so these options are not needed + // We can always convert from json to another format if needed. + // format?: 'json' | 'jsonl' | 'csv' | 'xls' | 'xlsx' + // exportspec?: string + // exportseparator?: string + // exportfile?: string + + filter?: string + jsonmode?: 'extended' | 'id' + nonCanonicalFacts?: boolean + noDedupArticles?: boolean + cluster?: 'all' | 'best' | 'dedupe' + report?: boolean + } + + export interface KnowledgeGraphEnhanceOptions { + type: EntityType + + id?: string + name?: string + url?: string + phone?: string + email?: string + employer?: string + title?: string + school?: string + location?: string + ip?: string + customId?: string + + size?: number + threshold?: number + + refresh?: boolean + search?: boolean + useCache?: boolean + + filter?: string + jsonmode?: 'extended' | 'id' + nonCanonicalFacts?: boolean + } + + export interface KnowledgeGraphResponse { + data: KnowledgeGraphNode[] + version: number + hits: number + results: number + kgversion: string + diffbot_type: string + facet?: boolean + errors?: any[] + } + + export interface KnowledgeGraphNode { + score: number + esscore?: number + entity: KnowledgeGraphEntity + entity_ctx: any + errors: string[] + callbackQuery: string + upperBound: number + lowerBound: number + count: number + value: string + uri: string + } + + export interface KnowledgeGraphEntity { + id: string + diffbotUri: string + type?: string + name: string + images: Image[] + origins: string[] + nbOrigins?: number + + gender?: Gender + githubUri?: string + importance?: number + description?: string + homepageUri?: string + allNames?: string[] + skills?: Skill[] + crawlTimestamp?: number + summary?: string + image?: string + types?: string[] + nbIncomingEdges?: number + allUris?: string[] + employments?: Employment[] + locations?: Location[] + location?: Location + allOriginHashes?: string[] + nameDetail?: NameDetail + } + + export type EntityType = 'Organization' | 'Place' + + export const EnhanceEntityOptionsSchema = z.object({ + type: z.enum(['Person', 'Organization']), + id: z + .string() + .optional() + .describe('Diffbot ID of the entity to enhance if known'), + name: z + .union([z.string(), z.array(z.string())]) + .optional() + .describe('Name of the entity'), + url: z + .array(z.string()) + .optional() + .describe('Origin or homepage URL of the entity'), + phone: z.string().optional().describe('Phone number of the entity'), + email: z.string().optional().describe('Email of the entity'), + employer: z + .string() + .optional() + .describe("Name of the entity's employer (for Person entities)"), + title: z + .string() + .optional() + .describe('Title of the entity (for Person entities)'), + school: z + .string() + .optional() + .describe('School of the entity (for Person entities)'), + location: z.string().optional().describe('Location of the entity'), + ip: z.string().optional().describe('IP address of the entity'), + customId: z.string().optional().describe('User-defined ID for correlation'), + threshold: z.number().optional().describe('Similarity threshold'), + refresh: z + .boolean() + .optional() + .describe( + 'If set, will attempt to refresh the entity data by recrawling the source URLs.' + ), + search: z + .boolean() + .optional() + .describe( + 'If set, will attempt to search the web for the entity and merge the results into its knowledge base.' + ), + size: z + .number() + .int() + .positive() + .max(100) + .optional() + .describe('Number of results to return') + }) + export type EnhanceEntityOptions = z.infer + + export interface EnhanceEntityResponse { + version: number + hits: number + kgversion: string + request_ctx: RequestCtx + data: EnhanceEntityResponseDatum[] + errors: any[] + } + + export interface RequestCtx { + query: Query + query_ctx: QueryCtx + } + + export interface Query { + type: string + name: string[] + } + + export interface QueryCtx { + search: string + } + + export interface EnhanceEntityResponseDatum { + score: number + esscore: number + entity: Entity + errors: any[] + } + + export interface Entity { + name: string + type: EntityType + id: string + summary?: string + description?: string + homepageUri?: string + twitterUri?: string + linkedInUri?: string + githubUri?: string + crunchbaseUri?: string + googlePlusUri?: string + facebookUri?: string + angellistUri?: string + wikipediaUri?: string + diffbotUri?: string + origin?: string + origins?: string[] + allUris?: string[] + + // extra metadata + nbOrigins?: number + nbIncomingEdges?: number + nbFollowers?: number + educations?: Education[] + nationalities?: Nationality[] + allNames?: string[] + skills?: Skill[] + children?: Children[] + height?: number + image?: string + images?: Image[] + allOriginHashes?: string[] + nameDetail?: NameDetail + parents?: Parent[] + gender?: Gender + importance?: number + wikipediaPageviewsLastQuarterGrowth?: number + wikipediaPageviewsLastYear?: number + wikipediaPageviewsLastYearGrowth?: number + wikipediaPageviews?: number + wikipediaPageviewsLastQuarter?: number + wikipediaPageviewsGrowth?: number + birthPlace?: BirthPlace + types?: string[] + unions?: Union[] + languages?: Language[] + employments?: Employment[] + birthDate?: DateTime + religion?: Religion + awards?: Award[] + netWorth?: NetWorth + allDescriptions?: string[] + locations?: Location[] + location?: Location + interests?: Interest[] + emailAddresses?: any + age?: number + crawlTimestamp?: number + } + + export interface Education { + institution: Institution + isCurrent?: boolean + major?: Major + degree?: Degree + from?: DateTime + to?: DateTime + } + + export interface Institution { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Major {} + + export interface Degree { + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface DateTime { + str: string + precision: number + timestamp: number + } + + export interface Nationality { + name: string + type: string + } + + export interface Skill { + name: string + diffbotUri?: string + targetDiffbotId?: string + } + + export interface Children { + summary: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Image { + url: string + primary?: boolean + } + + export interface NameDetail { + firstName: string + lastName: string + middleName?: string[] + } + + export interface Parent { + summary: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + image?: string + } + + export interface Gender { + normalizedValue: string + } + + export interface BirthPlace { + country: Country + isCurrent: boolean + address: string + city: City + subregion: Subregion + latitude: number + precision: number + surfaceForm: string + region: Region + longitude: number + } + + export interface Country { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface City { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Subregion { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Region { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Union { + person: Person + from?: DateTime + to?: DateTime + type?: string + } + + export interface Person { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Language { + str: string + normalizedValue: string + } + + export interface Employment { + isCurrent?: boolean + employer?: Employer + from?: DateTime + categories?: EmploymentCategory[] + title?: string + to?: DateTime + location?: Location + } + + export interface Employer { + summary?: string + image?: string + types?: string[] + name: string + diffbotUri?: string + targetDiffbotId?: string + type: string + } + + export interface EmploymentCategory { + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Location { + country?: Country + isCurrent: boolean + address: string + city: City + street: string + metroArea: MetroArea + subregion: Subregion + latitude: number + precision: number + postalCode: string + region?: Region + longitude: number + } + + export interface MetroArea { + summary: string + image: string + types: string[] + name: string + diffbotUri: string + targetDiffbotId: string + type: string + } + + export interface Religion { + str: string + } + + export interface Award { + title: string + date?: DateTime + } + + export interface NetWorth { + currency: string + value: number + } + + export interface Interest { + name: string + type: string + } + + export function pruneEntity(entity: diffbot.Entity) { + return omit( + entity, + 'allOriginHashes', + 'locations', + 'images', + 'nationalities', + 'awards', + 'interests' + ) + } +} + +/** + * Diffbot provides web page classification and scraping. It also provides + * access to a knowledge graph with the ability to perform person and company + * data enrichment. + * + * @see https://docs.diffbot.com + */ +export class DiffbotClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly kyKnowledgeGraph: KyInstance + + protected readonly apiKey: string + protected readonly apiBaseUrl: string + protected readonly apiKnowledgeGraphBaseUrl: string + + constructor({ + apiKey = getEnv('DIFFBOT_API_KEY'), + apiBaseUrl = diffbot.API_BASE_URL, + apiKnowledgeGraphBaseUrl = diffbot.KNOWLEDGE_GRAPH_API_BASE_URL, + timeoutMs = 30_000, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + apiKnowledgeGraphBaseUrl?: string + timeoutMs?: number + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + `DiffbotClient missing required "apiKey" (defaults to "DIFFBOT_API_KEY")` + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + this.apiKnowledgeGraphBaseUrl = apiKnowledgeGraphBaseUrl + + const throttledKy = throttle ? throttleKy(ky, diffbot.throttle) : ky + + this.ky = throttledKy.extend({ + prefixUrl: apiBaseUrl, + timeout: timeoutMs + }) + + this.kyKnowledgeGraph = throttledKy.extend({ + prefixUrl: apiKnowledgeGraphBaseUrl, + timeout: timeoutMs + }) + } + + @aiFunction({ + name: 'diffbot_analyze_url', + description: + 'Scrapes and extracts structured data from a web page. Also classifies the web page as one of several types (article, product, discussion, job, image, video, list, event, or other).', + inputSchema: z.object({ + url: z.string().url().describe('The URL to process.') + }) + }) + async analyzeUrl(options: diffbot.ExtractAnalyzeOptions) { + return this._extract('v3/analyze', options) + } + + @aiFunction({ + name: 'diffbot_extract_article_from_url', + description: + 'Scrapes and extracts clean article text from news articles, blog posts, and other text-heavy web pages.', + inputSchema: z.object({ + url: z.string().url().describe('The URL to process.') + }) + }) + async extractArticleFromUrl(options: diffbot.ExtractArticleOptions) { + return this._extract('v3/article', options) + } + + @aiFunction({ + name: 'diffbot_enhance_entity', + description: + 'Resolves and enriches a partial person or organization entity.', + inputSchema: diffbot.EnhanceEntityOptionsSchema.omit({ + refresh: true, + search: true, + customId: true, + threshold: true + }) + }) + async enhanceEntity(opts: diffbot.EnhanceEntityOptions) { + const res = await this.kyKnowledgeGraph + .get('kg/v3/enhance', { + searchParams: sanitizeSearchParams({ + ...opts, + token: this.apiKey + }) + }) + .json() + + return res.data.map((datum) => diffbot.pruneEntity(datum.entity)) + } + + async searchKnowledgeGraph(options: diffbot.KnowledgeGraphSearchOptions) { + return this.kyKnowledgeGraph + .get('kg/v3/dql', { + searchParams: { + ...options, + token: this.apiKey + } + }) + .json() + } + + async enhanceKnowledgeGraph(options: diffbot.KnowledgeGraphEnhanceOptions) { + return this.kyKnowledgeGraph + .get('kg/v3/enhance', { + searchParams: { + ...options, + token: this.apiKey + } + }) + .json() + } + + protected async _extract< + T extends diffbot.ExtractResponse = diffbot.ExtractResponse + >(endpoint: string, options: diffbot.ExtractOptions): Promise { + const { customJs, customHeaders, ...rest } = options + const searchParams = sanitizeSearchParams({ + ...rest, + token: this.apiKey + }) + const headers = { + ...Object.fromEntries( + [['X-Forward-X-Evaluate', customJs]].filter(([, value]) => value) + ), + ...customHeaders + } + + // console.log(`DiffbotClient._extract: ${endpoint}`, searchParams) + + return this.ky + .get(endpoint, { + searchParams, + headers, + retry: 1 + }) + .json() + } +} diff --git a/src/services/exa-client.ts b/src/services/exa-client.ts new file mode 100644 index 000000000..58d3a0b1d --- /dev/null +++ b/src/services/exa-client.ts @@ -0,0 +1,263 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, pruneUndefined } from '../utils.js' + +export namespace exa { + export const TextContentsOptionsSchema = z.object({ + maxCharacters: z + .number() + .optional() + .describe('The maximum number of characters to return.'), + includeHtmlTags: z + .boolean() + .optional() + .describe('If true, includes HTML tags in the returned text.') + }) + export type TextContentsOptions = z.infer + + export const HighlightsContentsOptionsSchema = z.object({ + query: z + .string() + .optional() + .describe('The query string to use for highlights search.'), + numSentences: z + .number() + .optional() + .describe('The number of sentences to return for each highlight.'), + highlightsPerUrl: z + .number() + .optional() + .describe('The number of highlights to return for each URL.') + }) + export type HighlightsContentsOptions = z.infer< + typeof HighlightsContentsOptionsSchema + > + + export const ContentsOptionsSchema = z.object({ + text: z.union([TextContentsOptionsSchema, z.literal(true)]).optional(), + highlights: z + .union([HighlightsContentsOptionsSchema, z.literal(true)]) + .optional() + }) + export type ContentsOptions = z.infer + + export const BaseSearchOptionsSchema = z.object({ + numResults: z + .number() + .optional() + .describe('Number of search results to return.'), + includeDomains: z + .array(z.string()) + .optional() + .describe('List of domains to include in the search.'), + excludeDomains: z + .array(z.string()) + .optional() + .describe('List of domains to exclude from the search.'), + startCrawlDate: z + .string() + .optional() + .describe( + 'Start date for results based on crawl date (ISO 8601 format).' + ), + endCrawlDate: z + .string() + .optional() + .describe('End date for results based on crawl date (ISO 8601 format).'), + startPublishedDate: z + .string() + .optional() + .describe( + 'Start date for results based on published date (ISO 8601 format).' + ), + endPublishedDate: z + .string() + .optional() + .describe( + 'End date for results based on published date (ISO 8601 format).' + ), + category: z + .string() + .optional() + .describe( + 'A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company.' + ), + contents: ContentsOptionsSchema.optional().describe( + 'Whether to include the contents of the search results.' + ) + }) + export type BaseSearchOptions = z.infer + + export const RegularSearchOptionsSchema = BaseSearchOptionsSchema.extend({ + query: z.string().describe('search query'), + useAutoprompt: z.boolean().optional(), + type: z.enum(['keyword', 'neural', 'magic']).optional() + }) + export type RegularSearchOptions = z.infer + + export const FindSimilarOptionsSchema = BaseSearchOptionsSchema.extend({ + url: z + .string() + .describe('The url for which you would like to find similar links'), + excludeSourceDomain: z + .boolean() + .optional() + .describe('If true, excludes links from the base domain of the input.') + }) + export type FindSimilarOptions = z.infer + + export const GetContentsOptionsSchema = ContentsOptionsSchema.extend({ + ids: z + .array(z.string()) + .nonempty() + .describe('Exa IDs of the documents to retrieve.') + }) + export type GetContentsOptions = z.infer + + /** + * Represents a search result object. + */ + export type SearchResult = { + /** The title of the search result. */ + title: string | null + + /** The URL of the search result. */ + url: string + + /** The estimated creation date of the content (ISO 8601 format). */ + publishedDate?: string + + /** The author of the content, if available. */ + author?: string + + /** Similarity score between the query/url and the result. */ + score?: number + + /** The temporary Exa ID for the document. */ + id: string + + /** Text from page */ + text?: string + + /** The highlights as an array of strings. */ + highlights?: string[] + + /** The corresponding scores as an array of floats, 0 to 1 */ + highlightScores?: number[] + } + + /** + * Represents a search response object. + */ + export type SearchResponse = { + /** The list of search results. */ + results: SearchResult[] + + /** The autoprompt string, if applicable. */ + autopromptString?: string + + /** Internal ID of this request. */ + requestId?: string + } +} + +/** + * Web search tailored for LLMs. + * + * @see https://docs.exa.ai + */ +export class ExaClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('EXA_API_KEY'), + apiBaseUrl = getEnv('EXA_API_BASE_URL') ?? 'https://api.exa.ai', + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'ExaClient missing required "apiKey" (defaults to "EXA_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl, + headers: { + 'x-api-key': apiKey + } + }) + } + + /** + * Performs an Exa search for the given query. + */ + @aiFunction({ + name: 'exa_search', + description: 'Search the web for the given query.', + inputSchema: exa.RegularSearchOptionsSchema + }) + async search(queryOrOpts: string | exa.RegularSearchOptions) { + const json = + typeof queryOrOpts === 'string' ? { query: queryOrOpts } : queryOrOpts + + return this.ky.post('search', { json }).json() + } + + /** + * Finds similar links to the provided URL. + */ + @aiFunction({ + name: 'exa_find_similar', + description: 'Find similar links to the provided URL.', + inputSchema: exa.FindSimilarOptionsSchema + }) + async findSimilar(opts: exa.FindSimilarOptions) { + const { excludeSourceDomain, ...rest } = opts + const excludeDomains = (opts.excludeDomains ?? []).concat( + excludeSourceDomain ? [new URL(opts.url).hostname] : [] + ) + + return this.ky + .post('findSimilar', { + json: pruneUndefined({ + ...rest, + excludeDomains: excludeDomains.length ? excludeDomains : undefined + }) + }) + .json() + } + + /** + * Retrieves contents of documents based on a list of Exa document IDs. + */ + @aiFunction({ + name: 'exa_get_contents', + description: + 'Retrieve contents of documents based on a list of Exa document IDs.', + inputSchema: exa.GetContentsOptionsSchema + }) + async getContents({ ids, ...opts }: exa.GetContentsOptions) { + const documentIDs = Array.isArray(ids) ? ids : [ids] + assert(documentIDs.length, 'Must provide at least one document ID') + + return this.ky + .post('contents', { + json: { + ...opts, + ids: documentIDs + } + }) + .json() + } +} diff --git a/src/services/firecrawl-client.ts b/src/services/firecrawl-client.ts new file mode 100644 index 000000000..1396f263b --- /dev/null +++ b/src/services/firecrawl-client.ts @@ -0,0 +1,252 @@ +import defaultKy, { type KyInstance } from 'ky' +import z from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, delay, getEnv } from '../utils.js' +import { zodToJsonSchema } from '../zod-to-json-schema.js' + +export namespace firecrawl { + /** + * Generic parameter interface. + */ + export interface Params { + extractorOptions?: { + extractionSchema: z.ZodSchema | any + mode?: 'llm-extraction' + extractionPrompt?: string + } + } + + /** + * Response interface for scraping operations. + */ + export interface ScrapeResponse { + success: boolean + data?: Data + error?: string + } + + export interface Data { + content?: string + markdown?: string + html?: string + metadata: Metadata + } + + export interface Metadata { + title: string + description: string + keywords?: string + robots?: string + ogTitle?: string + ogDescription?: string + ogUrl?: string + ogImage?: string + ogLocaleAlternate?: any[] + ogSiteName?: string + sourceURL?: string + modifiedTime?: string + publishedTime?: string + } + + /** + * Response interface for searching operations. + */ + export interface SearchResponse { + success: boolean + data?: any + error?: string + } + + /** + * Response interface for crawling operations. + */ + export interface CrawlResponse { + success: boolean + jobId?: string + data?: any + error?: string + } + + /** + * Response interface for job status checks. + */ + export interface JobStatusResponse { + success: boolean + status: string + jobId?: string + data?: any + error?: string + } +} + +/** + * Turn websites into LLM-ready data. Crawl and convert any website into clean + * markdown or structured data. + * + * @see https://www.firecrawl.dev + * @see https://github.com/mendableai/firecrawl + */ +export class FirecrawlClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('FIRECRAWL_API_KEY'), + apiBaseUrl = getEnv('FIRECRAWL_API_BASE_URL') ?? + 'https://api.firecrawl.dev', + timeoutMs = 60_000, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + timeoutMs?: number + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'FirecrawlClient missing required "apiKey" (defaults to "FIRECRAWL_API_KEY")' + ) + assert( + apiBaseUrl, + 'FirecrawlClient missing required "apiBaseUrl" (defaults to "FIRECRAWL_API_BASE_URL")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: apiBaseUrl, + timeout: timeoutMs, + headers: { + Authorization: `Bearer ${this.apiKey}` + } + }) + } + + @aiFunction({ + name: 'firecrawl_scrape_url', + description: 'Scrape the contents of a URL.', + inputSchema: z.object({ + url: z.string().url().describe('The URL to scrape.') + }) + }) + async scrapeUrl( + opts: { + url: string + } & firecrawl.Params + ) { + const json = { + ...opts + } + + if (opts?.extractorOptions?.extractionSchema) { + let schema = opts.extractorOptions.extractionSchema + if (schema instanceof z.ZodSchema) { + schema = zodToJsonSchema(schema) + } + + json.extractorOptions = { + mode: 'llm-extraction', + ...opts.extractorOptions, + extractionSchema: schema + } + } + + const res = await this.ky + .post('v0/scrape', { json }) + .json() + + if (!res.success || !res.data) return res + + if (res.data.markdown) { + delete res.data.html + delete res.data.content + } + + return res + } + + async search( + opts: { + query: string + } & firecrawl.Params + ) { + return this.ky + .post('v0/search', { json: opts }) + .json() + } + + async crawlUrl({ + waitUntilDone = true, + timeoutMs = 30_000, + idempotencyKey, + ...params + }: { + url: string + waitUntilDone?: boolean + timeoutMs?: number + idempotencyKey?: string + } & firecrawl.Params) { + const res = await this.ky + .post('v0/crawl', { + json: params, + timeout: timeoutMs, + headers: idempotencyKey + ? { + 'x-idempotency-key': idempotencyKey + } + : undefined + }) + .json() + + assert(res.jobId) + if (waitUntilDone) { + return this.waitForCrawlJob({ jobId: res.jobId, timeoutMs }) + } + + return res + } + + async checkCrawlStatus(jobId: string) { + assert(jobId) + + return this.ky + .get(`v0/crawl/status/${jobId}`) + .json() + } + + async waitForCrawlJob({ + jobId, + timeoutMs = 60_000 + }: { + jobId: string + timeoutMs?: number + }) { + assert(jobId) + + const start = Date.now() + do { + const res = await this.checkCrawlStatus(jobId) + if (res.status === 'completed') { + return res + } + + if (!['active', 'paused', 'pending', 'queued'].includes(res.status)) { + throw new Error( + `Crawl job "${jobId}" failed or was stopped. Status: ${res.status}` + ) + } + + if (Date.now() - start > timeoutMs) { + throw new Error( + `Timeout waiting for crawl job "${jobId}" to complete: ${res.status}` + ) + } + + await delay(1000) + } while (true) + } +} diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 000000000..ade608615 --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,23 @@ +export * from './bing-client.js' +export * from './clearbit-client.js' +export * from './dexa-client.js' +export * from './diffbot-client.js' +export * from './exa-client.js' +export * from './firecrawl-client.js' +export * from './midjourney-client.js' +export * from './novu-client.js' +export * from './people-data-labs-client.js' +export * from './perigon-client.js' +export * from './polygon-client.js' +export * from './predict-leads-client.js' +export * from './proxycurl-client.js' +export * from './scraper-client.js' +export * from './searxng-client.js' +export * from './serpapi-client.js' +export * from './serper-client.js' +export * from './slack-client.js' +export * from './tavily-client.js' +export * from './twilio-client.js' +export * from './weather-client.js' +export * from './wikipedia-client.js' +export * from './wolfram-alpha-client.js' diff --git a/src/services/midjourney-client.ts b/src/services/midjourney-client.ts new file mode 100644 index 000000000..6fad2427e --- /dev/null +++ b/src/services/midjourney-client.ts @@ -0,0 +1,195 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { TimeoutError } from '../errors.js' +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, delay, getEnv, pruneNullOrUndefined } from '../utils.js' + +// TODO: add additional methods for upscaling, variations, etc. + +export namespace midjourney { + export const API_BASE_URL = 'https://cl.imagineapi.dev' + + export type JobStatus = 'pending' | 'in-progress' | 'completed' | 'failed' + + export interface ImagineResponse { + data: Job + } + + export interface Job { + id: string + prompt: string + status: JobStatus + user_created: string + date_created: string + results?: string + progress?: string + url?: string + error?: string + upscaled_urls?: string[] + ref?: string + upscaled?: string[] + } + + export interface JobOptions { + wait?: boolean + timeoutMs?: number + intervalMs?: number + } +} + +/** + * Unofficial Midjourney API client for generative images. + * + * @see https://www.imagineapi.dev + */ +export class MidjourneyClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('MIDJOURNEY_IMAGINE_API_KEY'), + apiBaseUrl = midjourney.API_BASE_URL, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'MidjourneyClient missing required "apiKey" (defaults to "MIDJOURNEY_IMAGINE_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: apiBaseUrl, + headers: { + Authorization: `Bearer ${this.apiKey}` + } + }) + } + + @aiFunction({ + name: 'midjourney_create_images', + description: + 'Creates 4 images from a prompt using the Midjourney API. Useful for generating images on the fly.', + inputSchema: z.object({ + prompt: z + .string() + .describe( + 'Simple, short, comma-separated list of phrases which describe the image you want to generate' + ) + }) + }) + async imagine( + promptOrOptions: + | string + | ({ + prompt: string + } & midjourney.JobOptions) + ): Promise { + const { + wait = true, + timeoutMs, + intervalMs, + ...options + } = typeof promptOrOptions === 'string' + ? ({ prompt: promptOrOptions } as { + prompt: string + } & midjourney.JobOptions) + : promptOrOptions + + const res = await this.ky + .post('items/images', { + json: { ...options } + }) + .json() + + const job = pruneNullOrUndefined(res.data) + if (!wait) { + return job + } + + if (job.status === 'completed' || job.status === 'failed') { + return job + } + + return this.waitForJobById(job.id, { + timeoutMs, + intervalMs + }) + } + + async getJobById( + jobIdOrOptions: + | string + | ({ + jobId: string + } & midjourney.JobOptions) + ): Promise { + const { + jobId, + wait = true, + timeoutMs, + intervalMs + } = typeof jobIdOrOptions === 'string' + ? ({ jobId: jobIdOrOptions } as { + jobId: string + } & midjourney.JobOptions) + : jobIdOrOptions + + const res = await this.ky + .get(`items/images/${jobId}`) + .json() + + const job = pruneNullOrUndefined(res.data) + if (!wait) { + return job + } + + if (job.status === 'completed' || job.status === 'failed') { + return job + } + + return this.waitForJobById(job.id, { + timeoutMs, + intervalMs + }) + } + + async waitForJobById( + jobId: string, + { + timeoutMs = 5 * 60 * 1000, // 5 minutes + intervalMs = 1000 + }: Omit = {} + ): Promise { + const startTimeMs = Date.now() + + function checkForTimeout() { + const elapsedTimeMs = Date.now() - startTimeMs + if (elapsedTimeMs >= timeoutMs) { + throw new TimeoutError( + `MidjourneyClient timeout waiting for job "${jobId}"` + ) + } + } + + do { + checkForTimeout() + + const job = await this.getJobById(jobId) + if (job.status === 'completed' || job.status === 'failed') { + return job + } + + checkForTimeout() + await delay(intervalMs) + } while (true) + } +} diff --git a/src/services/novu-client.ts b/src/services/novu-client.ts new file mode 100644 index 000000000..5cbbe4d17 --- /dev/null +++ b/src/services/novu-client.ts @@ -0,0 +1,161 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv } from '../utils.js' + +export namespace novu { + export const API_BASE_URL = 'https://api.novu.co/v1' + + /** + * Novu subscriber object. + */ + export type Subscriber = { + /** + * Unique identifier for the subscriber. This can be any value that is meaningful to your application such as a user ID stored in your database or a unique email address. + */ + subscriberId: string + + /** + * Email address of the subscriber. + */ + email?: string + + /** + * First name of the subscriber. + */ + firstName?: string + + /** + * Last name of the subscriber. + */ + lastName?: string + + /** + * Phone number of the subscriber. + */ + phone?: string + } + + /** + * Response from the Novu API when triggering an event. + * + * @see {@link https://docs.novu.co/api/client-libraries#trigger-event} + */ + export type TriggerEventResponse = { + /** + * Data about the triggered event. + */ + data: { + /** + * Whether the trigger was acknowledged or not. + */ + acknowledged?: boolean + + /** + * Status for trigger. + */ + status?: string + + /** + * Transaction id for trigger. + */ + transactionId?: string + + /** + * In case of an error, this field will contain the error message. + */ + error?: Array + } + } + + /** + * Options for triggering an event in Novu. + */ + export type TriggerOptions = { + /** + * Name of the event to trigger. This should match the name of an existing notification template in Novu. + */ + name: string + + /** + * Payload to use for the event. This will be used to populate any handlebars placeholders in the notification template. + */ + payload: Record + + /** + * List of subscribers to send the notification to. Each subscriber must at least have a unique `subscriberId` to identify them in Novu and, if not already known to Novu, an `email` address or `phone` number depending on the notification template being used. + */ + to: Subscriber[] + } +} + +/** + * The Novu API provides a router for sending notifications across different + * channels like Email, SMS, Chat, In-App, and Push. + * + * @see https://novu.co + */ +export class NovuClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('NOVU_API_KEY'), + apiBaseUrl = novu.API_BASE_URL, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'NovuClient missing required "apiKey" (defaults to "NOVU_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl, + headers: { + Authorization: `ApiKey ${this.apiKey}` + } + }) + } + + /** + * Triggers an event in Novu. + * + * @see https://docs.novu.co/api-reference/events/trigger-event + */ + @aiFunction({ + name: 'novu_trigger_event', + description: + 'Sends a notification to a person given their novu `subscriberId` and an `email` or `phone` number. Useful for sending emails or SMS text messages to people.', + inputSchema: z.object({ + name: z.string(), + // TODO: make this more + payload: z.record(z.any()), + to: z.array( + z.object({ + subscriberId: z.string(), + email: z.string().optional(), + firstName: z.string().optional(), + lastName: z.string().optional(), + phone: z.string().optional() + }) + ) + }) + }) + async triggerEvent(options: novu.TriggerOptions) { + return this.ky + .post('events/trigger', { + json: options + }) + .json() + } +} diff --git a/src/services/people-data-labs-client.ts b/src/services/people-data-labs-client.ts new file mode 100644 index 000000000..80093b8bd --- /dev/null +++ b/src/services/people-data-labs-client.ts @@ -0,0 +1,546 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' + +import { assert, getEnv, sanitizeSearchParams, throttleKy } from '../utils.js' + +/** + * TODO: I'm holding off on converting this client to an `AIFunctionsProvider` + * because it seems to be significantly more expensive than other data sources, + * and I'm not sure if it's worth the cost. + */ + +export namespace peopledatalabs { + export const BASE_URL = 'https://api.peopledatalabs.com/v5/' + + // Allow up to 10 requests per minute. + export const throttle10PerMin = pThrottle({ + limit: 10, + interval: 60 * 1000, + strict: true + }) + + // Allow up to 100 requests per minute. + export const throttle100PerMin = pThrottle({ + limit: 100, + interval: 60 * 1000, + strict: true + }) + + export const JobTitleLevels = [ + 'cxo', + 'director', + 'entry', + 'manager', + 'owner', + 'partner', + 'senior', + 'training', + 'unpaid', + 'vp' + ] + + export const JobTitleRoles = [ + 'customer_service', + 'design', + 'education', + 'engineering', + 'finance', + 'health', + 'human_resources', + 'legal', + 'marketing', + 'media', + 'operations', + 'public_relations', + 'real_estate', + 'sales', + 'trades' + ] + + // TODO configure this type to make pdl_id or name or profile or ticker or website required. + // Only one is required + export interface CompanyLookupOptions { + pdl_id?: string + name?: string + profile?: string + ticker?: string + website?: string + location?: string[] + locality?: string + region?: string + country?: string + street_address?: string + postal_code?: string + data_include?: string + pretty?: boolean + } + + export interface Naics { + naics_code: string + sector: string + sub_sector: string + industry_group: string + naics_industry: string | null + national_industry: string | null + } + + export interface Sic { + sic_code: string + major_group: string + industry_group: string + industry_sector: string | null + } + + export interface Location { + name: string + locality: string + region: string + metro: string + country: string + continent: string + street_address: string + address_line_2: string | null + postal_code: string + geo: string + } + + export interface EmployeeCountByCountry { + [country: string]: number + } + + export interface CompanyLookupResponse { + status: number + name: string + display_name: string + size: string + employee_count: number + id: string + founded: number + industry: string + naics: Naics[] + sic: Sic[] + location: Location + linkedin_id: string + linkedin_url: string + facebook_url: string + twitter_url: string + profiles: string[] + website: string + ticker: string + gics_sector: string | null + mic_exchange: string | null + type: string + summary: string + tags: string[] + headline: string + alternative_names: string[] + alternative_domains: string[] + affiliated_profiles: string[] + employee_count_by_country: EmployeeCountByCountry + likelihood: number + } + + export interface CompanySearchOptions { + limit?: number + query: { + website?: string + tags?: string + industry?: string + 'location.country'?: string + 'location.metro'?: string + summary?: string + size?: string[] + affiliated_profiles?: string + } + } + + export type CompanySearchOptionsQueryKeys = + keyof CompanySearchOptions['query'] + + export interface CompanySearchResponse { + status: number + data: { + name: string + display_name: string + size: string + employee_count: number + id: string + founded: number + industry: string + naics: Naics[] + sic: Sic[] + location: Location + linkedin_id: string + linkedin_url: string + facebook_url: string + twitter_url: string + profiles: string[] + website: string + ticker: string + gics_sector: string | null + mic_exchange: string | null + type: string + summary: string + tags: string[] + headline: string + alternative_names: string[] + alternative_domains: string[] + affiliated_profiles: string[] + employee_count_by_country: EmployeeCountByCountry + }[] + scroll_token: string + total: number + } + + export interface PersonSearchOptions { + limit?: number + query: { + first_name?: string + full_name?: string + last_name?: string + job_company_website?: string + job_title_role?: string + /** + * The docs says this property should be an array of strings. + * But when sending the array a 404 error is returned. + * See: https://docs.peopledatalabs.com/docs/fields#job_title_levels + */ + job_title_levels?: string + job_company_name?: string + job_company_location_country?: string + } + } + + export type PersonSearchOptionsQueryKeys = keyof PersonSearchOptions['query'] + + // Person response + export interface SearchPersonApiResponse { + id: string + full_name: string + first_name: string + middle_initial: null | string + middle_name: null | string + last_initial: string + last_name: string + gender: string + birth_year: null | number + birth_date: null | string + linkedin_url: string + linkedin_username: string + linkedin_id: string + facebook_url: null | string + facebook_username: null | string + facebook_id: null | string + twitter_url: string + twitter_username: string + github_url: null | string + github_username: null | string + work_email: string + personal_emails: string[] + recommended_personal_email: null | string + mobile_phone: null | string + industry: null | string + job_title: string + job_title_role: null | string + job_title_sub_role: null | string + job_title_levels: string[] + job_onet_code: string + job_onet_major_group: string + job_onet_minor_group: string + job_onet_broad_occupation: string + job_onet_specific_occupation: string + job_onet_specific_occupation_detail: string + job_company_id: string + job_company_name: string + job_company_website: string + job_company_size: string + job_company_founded: number + job_company_industry: string + job_company_linkedin_url: string + job_company_linkedin_id: string + job_company_facebook_url: string + job_company_twitter_url: string + job_company_type: string + job_company_ticker: null | string + job_company_location_name: string + job_company_location_locality: string + job_company_location_metro: string + job_company_location_region: string + job_company_location_geo: string + job_company_location_street_address: string + job_company_location_address_line_2: string + job_company_location_postal_code: string + job_company_location_country: string + job_company_location_continent: string + job_last_updated: string + job_start_date: string + job_summary: null | string + location_name: null | string + location_locality: null | string + location_metro: null | string + location_region: null | string + location_country: null | string + location_continent: null | string + location_street_address: null | string + location_address_line_2: null | string + location_postal_code: null | string + location_geo: null | string + location_last_updated: null | string + linkedin_connections: number + facebook_friends: null | string + inferred_salary: string + inferred_years_experience: number + summary: null | string + phone_numbers: string[] + phones: string[] + emails: Email[] + interests: string[] + skills: string[] + location_names: string[] + regions: string[] + countries: string[] + street_addresses: string[] + experience: Experience[] + education: Education[] + profiles: Profile[] + name_aliases: string[] + possible_emails: PossibleEmail[] + possible_profiles: PossibleProfile[] + possible_phones: PossiblePhone[] + possible_street_addresses: string[] + possible_location_names: string[] + possible_birth_dates: string[] + job_history: JobHistory[] + certifications: string[] + languages: string[] + first_seen: string + num_sources: number + num_records: number + version_status: VersionStatus + } + + export interface Email { + address: string + type: null | string + first_seen: string + last_seen: string + num_sources: number + } + + export interface Experience { + company: Company + start_date: null | string + end_date: null | string + title: Title + location_names: string[] + is_primary: boolean + summary: null | string + num_sources: number + first_seen: string + last_seen: string + } + + export interface Company { + name: string + size: string + id: string + founded: number + industry: string + location: Location + linkedin_url: string + linkedin_id: string + facebook_url: null | string + twitter_url: string + website: string + ticker: null | string + type: string + raw: string[] + fuzzy_match: boolean + } + + export interface Title { + name: string + raw: string[] + role: null | string + sub_role: null | string + levels: string[] + } + + export interface Education { + school: School + degrees: string[] + start_date: string + end_date: string + majors: string[] + minors: string[] + gpa: null | string + raw: string[] + summary: null | string + } + + export interface School { + name: string + type: string + id: string + location: Location + linkedin_url: string + facebook_url: string + twitter_url: string + linkedin_id: string + website: string + domain: string + raw: string[] + } + + export interface Profile { + network: string + id: null | string + url: string + username: string + num_sources: number + first_seen: string + last_seen: string + } + + export interface PossibleEmail { + address: string + type: null | string + first_seen: string + last_seen: string + num_sources: number + } + + export interface PossibleProfile { + network: string + id: null | string + url: string + username: null | string + num_sources: number + first_seen: string + last_seen: string + } + + export interface PossiblePhone { + number: string + first_seen: string + last_seen: string + num_sources: number + } + + export interface VersionStatus { + status: string + contains: string[] + previous_version: string + current_version: string + } + + export interface JobHistory { + company_id: string + company_name: string + title: string + first_seen: string + last_seen: string + num_sources: number + } +} + +/** + * People & Company Data + * + * @see https://www.peopledatalabs.com + */ +export class PeopleDataLabsClient { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('PEOPLE_DATA_LABS_API_KEY'), + apiBaseUrl = peopledatalabs.BASE_URL, + timeoutMs = 30_000, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + timeoutMs?: number + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'PeopleDataLabsClient missing required "apiKey" (defaults to "PEOPLE_DATA_LABS_API_KEY")' + ) + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + const throttledKy = throttle + ? throttleKy(ky, peopledatalabs.throttle10PerMin) + : ky + + this.ky = throttledKy.extend({ + prefixUrl: apiBaseUrl, + timeout: timeoutMs, + headers: { + 'x-api-key': `${this.apiKey}` + } + }) + } + + async companyLookup(options: peopledatalabs.CompanySearchOptions) { + const terms = options.query + const termsQuery = [] + + for (const term of Object.keys( + terms + ) as peopledatalabs.CompanySearchOptionsQueryKeys[]) { + termsQuery.push({ term: { [term]: terms[term] } }) + } + + return this.ky + .get('company/search', { + searchParams: { + size: options.limit || 1, + query: JSON.stringify({ + bool: { + must: termsQuery + } + }) + } + }) + .json() + } + + async companyProfile(options: peopledatalabs.CompanyLookupOptions) { + return this.ky + .get('company/enrich', { + searchParams: sanitizeSearchParams({ ...options }) + }) + .json() + } + + async personSearch(options: peopledatalabs.PersonSearchOptions) { + const terms = options.query + const termsQuery = [] + + for (const term of Object.keys( + terms + ) as peopledatalabs.PersonSearchOptionsQueryKeys[]) { + termsQuery.push({ term: { [term]: terms[term] } }) + } + + return this.ky + .get('person/search', { + searchParams: { + size: options.limit || 10, + query: JSON.stringify({ + bool: { + must: termsQuery + } + }) + } + }) + .json() + } +} diff --git a/src/services/perigon-client.ts b/src/services/perigon-client.ts new file mode 100644 index 000000000..729104a13 --- /dev/null +++ b/src/services/perigon-client.ts @@ -0,0 +1,794 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, sanitizeSearchParams, throttleKy } from '../utils.js' + +// TODO: https://docs.goperigon.com/docs/searching-sources +// TODO: https://docs.goperigon.com/docs/journalist-data +// TODO: https://docs.goperigon.com/docs/topics + +export namespace perigon { + // Allow up to 2 requests per second by default. + export const throttle = pThrottle({ + limit: 2, + interval: 1000, + strict: true + }) + + export const DEFAULT_PAGE_SIZE = 10 + export const MAX_PAGE_SIZE = 100 + + export const ArticleLabelSchema = z.union([ + z.literal('Opinion'), + z.literal('Non-news'), + z.literal('Paid News'), + z.literal('Fact Check'), + z.literal('Pop Culture'), + z.literal('Roundup'), + z.literal('Press Release') + ]) + export type ArticleLabel = z.infer + + export const CategoriesSchema = z.union([ + z.literal('Politics'), + z.literal('Tech'), + z.literal('Sports'), + z.literal('Business'), + z.literal('Finance'), + z.literal('Entertainment'), + z.literal('Health'), + z.literal('Weather'), + z.literal('Lifestyle'), + z.literal('Auto'), + z.literal('Science'), + z.literal('Travel'), + z.literal('Environment'), + z.literal('World'), + z.literal('General'), + z.literal('none') + ]) + export type Categories = z.infer + + export const SourceGroupSchema = z.union([ + z.literal('top10').describe('Top 10 most popular sources globally'), + z.literal('top100').describe('Top 100 most popular sources globally'), + z + .literal('top500English') + .describe('Top 500 most popular (English) sources globally'), + z + .literal('top25crypto') + .describe( + 'Top 25 most popular sources covering cryptocurrency & blockchain developments' + ), + z + .literal('top25finance') + .describe( + 'Top 25 most popular sources covering financial news, movement in the markets & public equities' + ), + z + .literal('top50tech') + .describe('Top 50 sources covering new technology & businesses in tech'), + z + .literal('top100sports') + .describe( + 'Top 100 most popular (English) sources covering sports of all types' + ), + z + .literal('top100leftUS') + .describe( + 'Top 100 most popular (US) sources with an average political bias rating of Left or Leans Left' + ), + z + .literal('top100rightUS') + .describe( + 'Top 100 most popular (US) sources with an average political bias rating of Right or Leans Right' + ), + z + .literal('top100centerUS') + .describe( + 'Top 100 most popular (US) sources with an average political bias rating of Center or Middle' + ) + ]) + export type SourceGroup = z.infer + + export const SortBySchema = z.union([ + z.literal('date'), + z.literal('relevance'), + z.literal('addDate'), + z.literal('pubDate'), + z.literal('refreshDate') + ]) + export type SortBy = z.infer + + export const ArticlesSearchOptionsSchema = z.object({ + q: z.string() + .describe(`Search query. It may use boolean operators (AND, OR, NOT) and quotes for exact matching. Example search queries: + +- election news +- "elon musk" AND tesla +- (upcoming release OR launch) AND apple +- (Google OR Amazon) AND NOT ("Jeff Bezos" OR Android) +- "climate change" +`), + title: z + .string() + .optional() + .describe( + 'Search query which applies only to article titles / headlines.' + ), + desc: z.string().optional(), + content: z.string().optional(), + url: z.string().optional(), + from: z + .string() + .optional() + .describe( + 'Filter to only return articles published after the specified date (ISO or "yyyy-mm-dd" format)' + ), + to: z + .string() + .optional() + .describe( + 'Filter to only return articles published before the specified date (ISO or "yyyy-mm-dd" format)' + ), + addDateFrom: z.string().optional(), + addDateTo: z.string().optional(), + refreshDateFrom: z.string().optional(), + refreshDateTo: z.string().optional(), + articleId: z.string().optional(), + clusterId: z.string().optional(), + medium: z.union([z.literal('article'), z.literal('video')]).optional(), + source: z + .string() + .optional() + .describe("Filter articles from a specific publisher's source domain."), + sourceGroup: SourceGroupSchema.optional().describe( + 'The source group to retrieve articles from.' + ), + excludeSource: z + .string() + .optional() + .describe( + 'Source website domains which should be excluded from the search. Wildcards (* and ?) are suported (e.g. "*.cnn.com").' + ), + paywall: z + .boolean() + .optional() + .describe( + 'Filter to show only results where the source has a paywall (true) or does not have a paywall (false).' + ), + country: z + .string() + .optional() + .describe('Country code to filter by country.'), + language: z.string().optional(), + label: ArticleLabelSchema.optional().describe( + 'Labels to filter by, could be "Opinion", "Paid-news", "Non-news", etc. If multiple parameters are passed, they will be applied as OR operations.' + ), + excludeLabel: z + .union([ArticleLabelSchema, z.literal('Low Content')]) + .optional() + .describe( + 'Exclude results that include specific labels ("Opinion", "Non-news", "Paid News", etc.). You can filter multiple by repeating the parameter.' + ), + byline: z.string().optional(), + topic: z.string().optional(), + category: CategoriesSchema.optional().describe( + 'Filter by categories. Categories are general themes that the article is about. Examples of categories: Tech, Politics, etc. If multiple parameters are passed, they will be applied as OR operations. Use "none" to search uncategorized articles.' + ), + journalistId: z.string().optional(), + state: z + .string() + .optional() + .describe( + 'Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question.' + ), + city: z + .string() + .optional() + .describe( + 'Filters articles where a specified city plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the urban area in question.' + ), + area: z + .string() + .optional() + .describe( + 'Filters articles where a specified area, such as a neighborhood, borough, or district, plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the area in question.' + ), + location: z.string().optional(), + sortBy: SortBySchema.default('relevance') + .optional() + .describe('How to sort the article results.'), + showReprints: z + .boolean() + .optional() + .describe( + 'Whether to return reprints in the response or not. Reprints are usually wired articles from sources like AP or Reuters that are reprinted in multiple sources at the same time. By default, this parameter is "true".' + ), + showNumResults: z.boolean().optional(), + type: z + .union([z.literal('all'), z.literal('local'), z.literal('world')]) + .optional(), + linkTo: z.string().optional(), + reprintGroupId: z.string().optional(), + personWikidataId: z.array(z.string()).optional(), + personName: z + .array(z.string()) + .optional() + .describe('List of person names for exact matches.'), + companyId: z.array(z.string()).optional(), + companyName: z.string().optional().describe('Search by company name.'), + companyDomain: z + .array(z.string()) + .optional() + .describe('Search by company domain.'), + companySymbol: z + .array(z.string()) + .optional() + .describe('Search by company stock ticker symbol.'), + maxDistance: z.number().optional(), + lat: z.number().optional(), + lon: z.number().optional(), + searchTranslation: z + .boolean() + .optional() + .describe( + 'Expand a query to search the translation, translatedTitle, and translatedDescription fields for non-English articles.' + ), + page: z + .number() + .int() + .positive() + .max(10_000) + .default(0) + .optional() + .describe('Page number of results to return (zero-based)'), + size: z + .number() + .int() + .positive() + .max(DEFAULT_PAGE_SIZE) + .optional() + .describe('Number of results to return per page') + }) + export type ArticlesSearchOptions = z.infer< + typeof ArticlesSearchOptionsSchema + > + + export const StoriesSearchOptionsSchema = ArticlesSearchOptionsSchema.pick({ + q: true, + clusterId: true, + topic: true, + category: true, + from: true, + to: true, + state: true, + city: true, + area: true, + showNumResults: true, + page: true, + size: true, + sourceGroup: true, + personWikidataId: true, + personName: true, + companyId: true, + companyName: true, + companyDomain: true, + companySymbol: true + }).extend({ + name: z.string().optional().describe('Search stories by name.'), + nameExists: z.boolean().optional(), + initializedFrom: z.string().optional(), + initializedTo: z.string().optional(), + updatedFrom: z.string().optional(), + updatedTo: z.string().optional(), + minClusterSize: z.number().optional(), + maxClusterSize: z.number().optional(), + showDuplicates: z + .boolean() + .optional() + .describe( + 'Stories are deduplicated by default. If a story is deduplicated, all future articles are merged into the original story. `duplicateOf` field contains the original cluster id. When showDuplicates=true, all stories are shown.' + ), + sortBy: z + .union([ + z.literal('count'), + z.literal('createdAt'), + z.literal('updatedAt') + ]) + .optional() + .describe('How to sort the results.') + }) + export type StoriesSearchOptions = z.infer + + export const PeopleSearchOptionsSchema = z.object({ + name: z + .string() + .describe( + 'Person name query to search for. It may use boolean operators (AND, OR, NOT) and quotes for exact matching.' + ), + wikidataId: z + .array(z.string()) + .optional() + .describe('Search by ID of Wikidata entity.'), + occupationId: z + .array(z.string()) + .optional() + .describe('Search by Wikidata occupation ID.'), + occupationLabel: z + .string() + .optional() + .describe('Search by occupation name.'), + size: z + .number() + .int() + .positive() + .max(DEFAULT_PAGE_SIZE) + .optional() + .describe('Number of results to return per page') + }) + export type PeopleSearchOptions = z.infer + + export const CompanySearchOptionsSchema = z.object({ + q: z + .string() + .optional() + .describe( + 'Company search query. It may use boolean operators (AND, OR, NOT) and quotes for exact matching.' + ), + name: z + .string() + .optional() + .describe( + 'Search by company name. It may use boolean operators (AND, OR, NOT) and quotes for exact matching.' + ), + industry: z + .string() + .optional() + .describe( + 'Search by company industry. It may use boolean operators (AND, OR, NOT) and quotes for exact matching.' + ), + sector: z + .string() + .optional() + .describe( + 'Search by company sector. It may use boolean operators (AND, OR, NOT) and quotes for exact matching.' + ), + id: z.array(z.string()).optional().describe('Search by company ID.'), + symbol: z + .array(z.string()) + .optional() + .describe('Search by company stock ticker symbol.'), + domain: z + .array(z.string()) + .optional() + .describe('Search by company domain.'), + country: z.string().optional().describe('Search by country.'), + exchange: z.string().optional().describe('Search by exchange name.'), + numEmployeesFrom: z + .number() + .int() + .positive() + .optional() + .describe('Minimum number of employees.'), + numEmployeesTo: z + .number() + .int() + .positive() + .optional() + .describe('Maximum number of employees.'), + ipoFrom: z + .string() + .optional() + .describe('Starting IPO date (ISO or "yyyy-mm-dd" format)'), + ipoTo: z + .string() + .optional() + .describe('Ending IPO date (ISO or "yyyy-mm-dd" format)'), + size: z + .number() + .int() + .positive() + .max(DEFAULT_PAGE_SIZE) + .optional() + .describe('Number of results to return per page') + }) + export type CompanySearchOptions = z.infer + + export type ArticlesSearchResponse = { + status: number + numResults: number + articles: Article[] + } + + export type Article = { + url: string + authorsByline: string + articleId: string + clusterId: string + source: { + domain: string + } + imageUrl: string + country: string + language: string + pubDate: string + addDate: string + refreshDate: string + score: number + title: string + description: string + content: string + medium: string + links: string[] + labels: string[] + matchedAuthors: string[] + claim: string + verdict: string + keywords: { + name: string + weight: number + }[] + topics: { + name: string + }[] + categories: { + name: string + }[] + entities: { + data: string + type: string + mentions: number + }[] + sentiment: { + positive: number + negative: number + neutral: number + } + summary: string + translation: string + locations: string[] + reprint: boolean + reprintGroupId: string + places: null + } + + export type StoriesSearchResponse = { + status: number + numResults: number + results: Story[] + } + + export type Story = { + createdAt: string + updatedAt: string + initializedAt: string + id: string + name: string + summary: string + summaryReferences: Array + keyPoints: Array<{ + point: string + references: Array + }> + sentiment: { + positive: number + negative: number + neutral: number + } + uniqueCount: number + reprintCount: number + totalCount: number + countries: Array<{ + name: string + count: number + }> + topCountries: Array + topics: Array<{ + name: string + count: number + }> + topTopics: Array<{ name: string }> + categories: Array<{ + name: string + count: number + }> + topCategories: Array<{ name: string }> + people: Array<{ wikidataId: string; name: string; count: number }> + topPeople: Array<{ wikidataId: string; name: string }> + companies: Array<{ + id: string + name: string + domains: Array + symbols: Array + count: number + }> + topCompanies: Array<{ + id: string + name: string + domains: Array + symbols: Array + }> + locations: Array<{ + state: string + city?: string + area?: string + county?: string + count: number + }> + topLocations: Array<{ + state: string + city?: string + area?: string + county?: string + }> + } + + export interface PeopleSearchResponse { + status: number + numResults: number + results: Person[] + } + + export interface Person { + wikidataId: string + name: string + gender: Gender + dateOfBirth: DateOfBirth + dateOfDeath: any + description: string + aliases: string[] + occupation: Occupation[] + position: Position[] + politicalParty: PoliticalParty[] + image?: Image + abstract: string + } + + export interface Gender { + wikidataId: string + label: string + } + + export interface DateOfBirth { + time: string + precision: string + } + + export interface Occupation { + wikidataId: string + label: string + } + + export interface Position { + wikidataId: string + label: string + startTime: any + endTime: any + employer: any + } + + export interface PoliticalParty { + wikidataId: string + label: string + startTime: any + endTime: any + } + + export interface Image { + url: string + } + + export interface CompanySearchResponse { + status: number + numResults: number + results: Company[] + } + + export interface Company { + id: string + name: string + altNames: string[] + domains: string[] + monthlyVisits: number + globalRank?: number + description: string + ceo: any + industry: string + sector: any + country: string + fullTimeEmployees?: number + address: any + city: any + state: any + zip: any + logo?: string + favicon?: string + isEtf: boolean + isActivelyTrading: any + isFund: boolean + isAdr: boolean + symbols: any[] + } +} + +/** + * **The intelligent news API** + * + * Real-time global news and web content data from 140,000+ sources. + * + * - search news articles + * - search news stories (clusters of related news articles) + * - search people, companies, topics, and journalists + * + * @see https://www.goperigon.com/products/news-api + */ +export class PerigonClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + + constructor({ + apiKey = getEnv('PERIGON_API_KEY'), + timeoutMs = 30_000, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + throttle?: boolean + timeoutMs?: number + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'PerigonClient missing required "apiKey" (defaults to "PERIGON_API_KEY")' + ) + super() + + this.apiKey = apiKey + + const throttledKy = throttle ? throttleKy(ky, perigon.throttle) : ky + + this.ky = throttledKy.extend({ + prefixUrl: 'https://api.goperigon.com/v1/', + timeout: timeoutMs + }) + } + + /** + * @see https://docs.goperigon.com/docs/overview + * @see https://docs.goperigon.com/reference/all-news + */ + @aiFunction({ + name: 'search_news_articles', + description: + 'Search for news articles indexed by Perigon. Articles can optionally be filtered by various parameters.', + inputSchema: perigon.ArticlesSearchOptionsSchema.pick({ + q: true, + title: true, + from: true, + to: true, + source: true, + sourceGroup: true, + excludeSource: true, + category: true, + personName: true, + companyName: true, + companyDomain: true, + sortBy: true + }) + }) + async searchArticles(opts: perigon.ArticlesSearchOptions) { + return this.ky + .get('all', { + searchParams: sanitizeSearchParams({ + ...opts, + apiKey: this.apiKey, + size: Math.max( + 1, + Math.min( + perigon.MAX_PAGE_SIZE, + opts.size || perigon.DEFAULT_PAGE_SIZE + ) + ) + }) + }) + .json() + } + + /** + * @see https://docs.goperigon.com/docs/stories-overview + * @see https://docs.goperigon.com/reference/stories-1 + */ + @aiFunction({ + name: 'search_news_stories', + description: + 'Search for news stories indexed by Perigon. Stories are clusters of related news articles and are useful for finding top stories and trending headlines. Stories can optionally be filtered by various parameters.', + inputSchema: perigon.StoriesSearchOptionsSchema.pick({ + q: true, + name: true, + from: true, + to: true, + sourceGroup: true, + category: true, + personName: true, + companyName: true, + companyDomain: true, + sortBy: true + }) + }) + async searchStories(opts: perigon.StoriesSearchOptions) { + return this.ky + .get('stories/all', { + searchParams: sanitizeSearchParams({ + ...opts, + apiKey: this.apiKey, + size: Math.max( + 1, + Math.min( + perigon.MAX_PAGE_SIZE, + opts.size || perigon.DEFAULT_PAGE_SIZE + ) + ) + }) + }) + .json() + } + + /** + * @see https://docs.goperigon.com/docs/people-data + * @see https://docs.goperigon.com/reference/people + */ + @aiFunction({ + name: 'search_people', + description: 'Search for well-known people indexed by Perigon.', + inputSchema: perigon.PeopleSearchOptionsSchema + }) + async searchPeople(opts: perigon.PeopleSearchOptions) { + return this.ky + .get('people/all', { + searchParams: sanitizeSearchParams({ + ...opts, + apiKey: this.apiKey, + size: Math.max( + 1, + Math.min( + perigon.MAX_PAGE_SIZE, + opts.size || perigon.DEFAULT_PAGE_SIZE + ) + ) + }) + }) + .json() + } + + /** + * @see https://docs.goperigon.com/docs/company-data + * @see https://docs.goperigon.com/reference/companies + */ + @aiFunction({ + name: 'search_companies', + description: + 'Search for companies indexed by Perigon. Includes public and private companies sourced from public records and Wikidata.', + inputSchema: perigon.CompanySearchOptionsSchema + }) + async searchCompanies(opts: perigon.CompanySearchOptions) { + return this.ky + .get('companies/all', { + searchParams: sanitizeSearchParams({ + ...opts, + apiKey: this.apiKey, + size: Math.max( + 1, + Math.min( + perigon.MAX_PAGE_SIZE, + opts.size || perigon.DEFAULT_PAGE_SIZE + ) + ) + }) + }) + .json() + } +} diff --git a/src/services/polygon-client.ts b/src/services/polygon-client.ts new file mode 100644 index 000000000..5a934a583 --- /dev/null +++ b/src/services/polygon-client.ts @@ -0,0 +1,1099 @@ +import defaultKy, { type KyInstance } from 'ky' + +import { AIFunctionsProvider } from '../fns.js' +import { assert, getEnv } from '../utils.js' + +// TODO: add aiFunction decorator to select methods + +export namespace polygon { + export const API_BASE_URL = 'https://api.polygon.io' + + /** + * Asset classes available on Polygon. + */ + export type ASSET_CLASS = 'stocks' | 'options' | 'crypto' | 'fx' + + /** + * Supported time spans for Polygon's indicator APIs. + */ + export type TIMESPAN = + | 'minute' + | 'hour' + | 'day' + | 'week' + | 'month' + | 'quarter' + | 'year' + + /** + * Supported series types for Polygon's indicator APIs. + */ + export type SERIES_TYPE = 'close' | 'open' | 'high' | 'low' + + /** + * Order types available on Polygon. + */ + export type ORDER_TYPE = 'asc' | 'desc' + + /** + * Input parameters for the aggregates API. + */ + export interface AggregatesInput { + /** The ticker symbol of the stock/equity. */ + ticker: string + + /** The size of the timespan multiplier. */ + multiplier: number + + /** The size of the time window. */ + timespan: TIMESPAN + + /** The start of the aggregate time window. Either a date with the format YYYY-MM-DD or a millisecond timestamp. */ + from: string | number + + /** The end of the aggregate time window. Either a date with the format YYYY-MM-DD or a millisecond timestamp. */ + to: string | number + + /** Whether or not the results are adjusted for splits. By default, results are adjusted. Set this to false to get results that are NOT adjusted for splits. */ + adjusted?: boolean + + /** Sort the results by timestamp. "asc" will return results in ascending order (oldest at the top), "desc" will return results in descending order (newest at the top). */ + sort?: ORDER_TYPE + + /** Limits the number of base aggregates queried to create the aggregate results. Max 50000 and Default 5000. */ + limit?: number + } + + /** + * Output parameters for the aggregates API. + */ + export interface AggregatesOutput { + /** The exchange symbol that this item is traded under. */ + ticker: string + + /** Whether or not this response was adjusted for splits. */ + adjusted: boolean + + /** The number of aggregates (minute or day) used to generate the response. */ + queryCount: number + + /** A request id assigned by the server. */ + request_id: string + + /** The total number of results for this request. */ + resultsCount: number + + /** The status of this request's response. */ + status: string + + /** The results of the query. */ + results: Aggregate[] + + /** If present, this value can be used to fetch the next page of data. */ + next_url?: string + } + + /** + * Input parameters for the grouped daily API. + */ + export type GroupedDailyInput = { + /** The beginning date for the aggregate window. */ + date: string + + /** Whether or not the results are adjusted for splits. By default, results are adjusted. Set this to false to get results that are NOT adjusted for splits. */ + adjusted?: boolean + } + + /** + * Input parameters for the grouped daily API for stocks. + */ + export interface GroupedDailyInputStocks extends GroupedDailyInput { + /** Include OTC securities in the response. Default is false (don't include OTC securities). */ + include_otc?: boolean + } + + /** + * Output parameters for the grouped daily API. + */ + export interface GroupedDailyOutput { + /** Whether or not this response was adjusted for splits. */ + adjusted: boolean + + /** The number of aggregates (minute or day) used to generate the response. */ + queryCount: number + + /** A request id assigned by the server. */ + request_id: string + + /** The total number of results for this request. */ + resultsCount: number + + /** The status of this request's response. */ + status: string + + /** The results of the query. */ + results: AggregateDaily[] + } + + /** + * AggregateDaily parameters. + */ + export interface AggregateDaily extends Aggregate { + /** The exchange symbol that this item is traded under. */ + T: string + } + + /** + * Ticker Details v3 input parameters. + */ + export type TickerDetailsInput = { + /** The ticker symbol of the asset. */ + ticker: string + + /** Specify a point in time to get information about the ticker available on that date (formatted as YYYY-MM-DD). */ + date?: string + } + + /** + * Daily Open/Close input parameters. + */ + export type DailyOpenCloseInput = { + /** The ticker symbol */ + ticker: string + + /** The date of the requested open/close in the format YYYY-MM-DD. */ + date: string + + /** Whether or not the results are adjusted for splits. By default, results are adjusted. */ + adjusted?: boolean + } + + /** + * Result returned by the Daily Open/Close API. + */ + export interface DailyOpenCloseOutput { + /** The close price of the ticker symbol in after-hours trading. */ + afterHours: number + + /** The close price for the symbol in the given time period. */ + close: number + + /** The requested date. */ + from: string + + /** The highest price for the symbol in the given time period. */ + high: number + + /** The lowest price for the symbol in the given time period. */ + low: number + + /** The open price for the symbol in the given time period. */ + open: number + + /** The open price of the ticker symbol in pre-market trading. */ + preMarket: number + + /** The status of this request's response. */ + status: string + + /** The exchange symbol that this item is traded under. */ + symbol: string + + /** The trading volume of the symbol in the given time period. */ + volume: number + } + + /** + * Result returned by the Previous Close API. + */ + export interface PreviousCloseOutput { + /** Whether or not this response was adjusted for splits. */ + adjusted: boolean + + /** The number of aggregates (minute or day) used to generate the response. */ + queryCount: number + + /** A request id assigned by the server. */ + requestId: string + + /** Array of results, each containing details for the symbol in the given time period. */ + results: { + /** The exchange symbol that this item is traded under. */ + T: string + + /** The close price for the symbol in the given time period. */ + c: number + + /** The highest price for the symbol in the given time period. */ + h: number + + /** The lowest price for the symbol in the given time period. */ + l: number + + /** The open price for the symbol in the given time period. */ + o: number + + /** The Unix Msec timestamp for the start of the aggregate window. */ + t: number + + /** The trading volume of the symbol in the given time period. */ + v: number + + /** The volume weighted average price. */ + vw: number + }[] + + /** The total number of results for this request. */ + resultsCount: number + + /** The status of this request's response. */ + status: string + + /** The exchange symbol that this item is traded under. */ + ticker: string + } + + /** + * Result returned by the Ticker Details v3 API. + */ + export interface TickerDetailsOutput { + /** A request id assigned by the server. */ + requestId: string + + /** Detailed results for the specific ticker. */ + results: { + /** Whether the ticker is actively traded. */ + active: boolean + + /** Address of the company. */ + address: { + /** The first line of the company's headquarters address. */ + address1: string + + /** The city of the company's headquarters address. */ + city: string + + /** The postal code of the company's headquarters address. */ + postalCode: string + + /** The state of the company's headquarters address. */ + state: string + } + + /** Branding details of the company. */ + branding: { + /** A link to this ticker's company's icon. Icon's are generally smaller, square images that represent the company at a glance. */ + iconUrl: string + + /** A link to this ticker's company's logo. Note that you must provide an API key when accessing this URL. See the "Authentication" section at the top of this page for more details. */ + logoUrl: string + } + + /** Central Index Key (CIK) of the company. */ + cik: string + + /** Composite Financial Instrument Global Identifier (FIGI). */ + compositeFigi: string + + /** Name of the currency in which the company trades. */ + currencyName: string + + /** Date and time the company was delisted, if applicable. */ + delistedUtc?: string + + /** Description of the company. */ + description: string + + /** The company's homepage URL. */ + homepageUrl: string + + /** The date when the company was listed. */ + listDate: string + + /** Locale of the company. */ + locale: string + + /** Market in which the company trades. */ + market: string + + /** Market capitalization of the company. */ + marketCap: number + + /** Name of the company. */ + name: string + + /** Phone number of the company. */ + phoneNumber: string + + /** The primary exchange on which the company trades. */ + primaryExchange: string + + /** Round lot size for the company's stock. */ + roundLot: number + + /** Share class FIGI. */ + shareClassFigi: string + + /** The number of outstanding shares for the share class. */ + shareClassSharesOutstanding: number + + /** The Standard Industrial Classification (SIC) code of the company. */ + sicCode: string + + /** Description of the SIC code. */ + sicDescription: string + + /** The ticker symbol of the company. */ + ticker: string + + /** The root of the ticker symbol. */ + tickerRoot: string + + /** The suffix of the ticker symbol, if applicable. */ + tickerSuffix?: string + + /** The total number of employees in the company. */ + totalEmployees: number + + /** The type of the ticker (e.g., common stock, preferred stock, etc.). */ + type: string + + /** The number of weighted outstanding shares. */ + weightedSharesOutstanding: number + } + + /** The status of this request's response. */ + status: string + } + + /** + * Input parameters for technical indicators. + */ + export type IndicatorInput = { + /** The ticker symbol for which to get data. */ + ticker: string + + /** Query by timestamp. Either a date with the format YYYY-MM-DD or a millisecond timestamp. */ + timestamp?: string + + /** The size of the aggregate time window. */ + timespan?: TIMESPAN + + /** Whether or not the aggregates are adjusted for splits. By default, aggregates are adjusted. Set this to false to get results that are NOT adjusted for splits. */ + adjusted?: boolean + + /** The window size used to calculate the indicator. i.e. a window size of 10 with daily aggregates would result in a 10 day moving average. */ + window?: number + + /** The price in the aggregate which will be used to calculate the indicator. */ + series_type?: SERIES_TYPE + + /** Whether or not to include the aggregates used to calculate this indicator in the response. */ + expand_underlying?: boolean + + /** The order in which to return the results, ordered by timestamp. */ + order?: ORDER_TYPE + + /** Limit the number of results returned, default is 10 and max is 5000 */ + limit?: number + } + + /** + * Represents an aggregate, which includes data for a given time period. + */ + export interface Aggregate { + /** The close price for the symbol in the given time period. */ + c: number + + /** The highest price for the symbol in the given time period. */ + h: number + + /** The lowest price for the symbol in the given time period. */ + l: number + + /** The number of transactions in the aggregate window. */ + n: number + + /** The open price for the symbol in the given time period. */ + o: number + + /** Whether or not this aggregate is for an OTC ticker. This field will be left off if false. */ + otc?: boolean + + /** The Unix Msec timestamp for the start of the aggregate window. */ + t: number + + /** The trading volume of the symbol in the given time period. */ + v: number + + /** The volume weighted average price. */ + vw?: number + } + + /** + * Represents a value of the indicator, which includes timestamp and value itself. + */ + export interface IndicatorValue { + /** The Unix Msec timestamp from the last aggregate used in this calculation. */ + timestamp: number + + /** The indicator value for this period. */ + value: number + } + + /** + * The output response from the technical indicator API. + */ + export interface IndicatorOutput { + /** If present, this value can be used to fetch the next page of data. */ + next_url: string + + /** A request id assigned by the server. */ + request_id: string + + /** Results object containing underlying aggregates and values array. */ + results: { + /** Underlying object containing aggregates and a URL to fetch underlying data. */ + underlying: { + /** Array of aggregates used for calculation. */ + aggregates: Aggregate[] + + /** The URL which can be used to request the underlying aggregates used in this request. */ + url: string + } + + /** Array of calculated indicator values. */ + values: IndicatorValue[] + } + + /** The status of this request's response. */ + status: string + } + + /** + * Input parameters for the /v3/reference/tickers API. + */ + export type TickerInput = { + /** Specify a ticker symbol. Defaults to empty string which queries all tickers. */ + ticker?: string + + /** Specify the type of the tickers. */ + type?: string + + /** Filter by market type. */ + market?: 'crypto' + + /** Specify the primary exchange of the asset in the ISO code format. */ + exchange?: string + + /** Specify the CUSIP code of the asset you want to search for. */ + cusip?: string + + /** Specify the CIK of the asset you want to search for. */ + cik?: string + + /** Specify a point in time to retrieve tickers available on that date. */ + date?: string + + /** Search for terms within the ticker and/or company name. */ + search?: string + + /** Specify if the tickers returned should be actively traded on the queried date. */ + active?: boolean + + /** Order results based on the sort field. */ + order?: ORDER_TYPE + + /** Limit the number of results returned. */ + limit?: number + + /** Sort field used for ordering. */ + sort?: string + } + + /** + * Represents a ticker that matches the query. + */ + export interface Ticker { + /** Whether or not the asset is actively traded. */ + active: boolean + + /** The CIK number for this ticker. */ + cik: string + + /** The composite OpenFIGI number for this ticker. */ + composite_figi: string + + /** The name of the currency that this asset is traded with. */ + currency_name: string + + /** The last date that the asset was traded. */ + delisted_utc: string + + /** The information is accurate up to this time. */ + last_updated_utc: string + + /** The locale of the asset. */ + locale: 'us' | 'global' + + /** The market type of the asset. */ + market: 'stocks' | 'crypto' | 'fx' | 'otc' | 'indices' + + /** The name of the asset. */ + name: string + + /** The ISO code of the primary listing exchange for this asset. */ + primary_exchange: string + + /** The share Class OpenFIGI number for this ticker. */ + share_class_figi: string + + /** The exchange symbol that this item is traded under. */ + ticker: string + + /** The type of the asset. */ + type: string + } + + /** + * The output response from the /v3/reference/tickers API. + */ + export interface TickerOutput { + /** The total number of results for this request. */ + count: number + + /** If present, this value can be used to fetch the next page of data. */ + next_url: string + + /** A request id assigned by the server. */ + request_id: string + + /** An array of tickers that match your query. */ + results: Ticker[] + + /** The status of this request's response. */ + status: string + } + + /** + * Output parameters for the market status API. + */ + export interface MarketStatusOutput { + /** Whether or not the market is in post-market hours. */ + afterHours: boolean + + /** The status of the crypto and forex markets. */ + currencies: { + /** The status of the crypto market. */ + crypto: string + /** The status of the forex market. */ + fx: string + } + + /** Whether or not the market is in pre-market hours. */ + earlyHours: boolean + + /** The status of the Nasdaq, NYSE and OTC markets. */ + exchanges: { + /** The status of the Nasdaq market. */ + nasdaq: string + /** The status of the NYSE market. */ + nyse: string + /** The status of the OTC market. */ + otc: string + } + + /** The status of the market as a whole. */ + market: string + + /** The current time of the server. */ + serverTime: string + } + + /** + * Output parameters for the market holidays API. + */ + export interface MarketHolidayOutput { + /** The market close time on the holiday (if it's not closed). */ + close?: string + + /** The date of the holiday. */ + date: string + + /** Which market the record is for. */ + exchange: string + + /** The name of the holiday. */ + name: string + + /** The market open time on the holiday (if it's not closed). */ + open?: string + + /** The status of the market on the holiday. */ + status: string + } + + /** + * Input parameters for the ticker types API. + */ + export type TickerTypesInput = { + /** Filter by asset class. */ + asset_class?: ASSET_CLASS + + /** Filter by locale. */ + locale?: string + } + + /** + * Output parameters for the ticker types API. + */ + export interface TickerTypesOutput { + /** The total number of results for this request. */ + count: number + + /** A request ID assigned by the server. */ + request_id: string + + /** The results of the query. */ + results: TickerType[] + + /** The status of this request's response. */ + status: string + } + + /** + * Ticker type parameters. + */ + export interface TickerType { + /** An identifier for a group of similar financial instruments. */ + asset_class: ASSET_CLASS + + /** A code used by Polygon.io to refer to this ticker type. */ + code: string + + /** A short description of this ticker type. */ + description: string + + /** An identifier for a geographical location. */ + locale: string + } + + /** + * Input parameters for the ticker news API. + */ + export type TickerNewsInput = { + /** Ticker symbol to return results for. */ + ticker: string + + /** Date to return results published on, before, or after. */ + published_utc?: string + + /** Order results based on the sort field. */ + order?: ORDER_TYPE + + /** Limit the number of results returned, default is 10 and max is 1000. */ + limit?: number + + /** Sort field used for ordering. */ + sort?: string + } + + /** + * Output parameters for the ticker news API. + */ + export interface TickerNewsOutput { + /** The total number of results for this request. */ + count: number + + /** If present, this value can be used to fetch the next page of data. */ + next_url: string + + /** A request id assigned by the server. */ + request_id: string + + /** The results of the query. */ + results: TickerNews[] + + /** The status of this request's response. */ + status: string + } + + /** + * Ticker news parameters. + */ + export interface TickerNews { + /** The mobile friendly Accelerated Mobile Page (AMP) URL. */ + amp_url?: string + + /** A link to the news article. */ + article_url: string + + /** The article's author. */ + author: string + + /** A description of the article. */ + description?: string + + /** Unique identifier for the article. */ + id: string + + /** The article's image URL. */ + image_url?: string + + /** The keywords associated with the article (which will vary depending on the publishing source). */ + keywords?: string[] + + /** The date the article was published on. */ + published_utc: string + + /** The publisher's details. */ + publisher: Publisher + + /** The ticker symbols associated with the article. */ + tickers: string[] + + /** The title of the news article. */ + title: string + } + + /** + * Publisher parameters. + */ + export interface Publisher { + /** The publisher's homepage favicon URL. */ + favicon_url?: string + + /** The publisher's homepage URL. */ + homepage_url: string + + /** The publisher's logo URL. */ + logo_url: string + + /** The publisher's name. */ + name: string + } + + /** + * Input parameters for the exchanges API. + */ + export type ExchangesInput = { + /** Filter by asset class. */ + asset_class?: ASSET_CLASS + + /** Filter by locale. */ + locale?: string + } + + /** + * Output parameters for the exchanges API. + */ + export interface ExchangesOutput { + /** The total number of results for this request. */ + count: number + + /** A request ID assigned by the server. */ + request_id: string + + /** The results of the query. */ + results: Exchange[] + + /** The status of this request's response. */ + status: string + } + + /** + * Exchange parameters. + */ + export interface Exchange { + /** A commonly used abbreviation for this exchange. */ + acronym?: string + + /** An identifier for a group of similar financial instruments. */ + asset_class: ASSET_CLASS + + /** A unique identifier used by Polygon.io for this exchange. */ + id: number + + /** An identifier for a geographical location. */ + locale: 'us' | 'global' + + /** The Market Identifer Code of this exchange (see ISO 10383). */ + mic: string + + /** Name of this exchange. */ + name: string + + /** The MIC of the entity that operates this exchange. */ + operating_mic: string + + /** The ID used by SIP's to represent this exchange. */ + participant_id?: string + + /** Represents the type of exchange. */ + type: 'exchange' | 'TRF' | 'SIP' + + /** A link to this exchange's website, if one exists. */ + url?: string + } +} + +/** + * Client for the Polygon.io API that lets you query the latest market data + * from all US stock exchanges. You can also find data on company financials, + * stock market holidays, corporate actions, and more. + * + * @see {@link https://polygon.io/docs} + */ +export class PolygonClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('POLYGON_API_KEY'), + apiBaseUrl = polygon.API_BASE_URL, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'PolygonClient missing required "apiKey" (defaults to "POLYGON_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl, + headers: { + Authorization: `Bearer ${this.apiKey}` + } + }) + } + + /** + * Returns detailed information about a single ticker. + * + * @param params - input parameters (`ticker` symbol and optional `date`) + * @returns promise that resolves to detailed information about a single ticker + */ + async tickerDetails(params: polygon.TickerDetailsInput) { + let searchParams + if (params.date) { + searchParams = { + date: params.date + } + } + + return this.ky + .get(`v3/reference/tickers/${params.ticker}`, { + searchParams + }) + .json() + } + + /** + * Returns the open, close and after hours prices of a stock symbol on a certain date. + * + * @param params - input parameters (`ticker` symbol and `date`) + * @returns promise that resolves to the open, close and after hours prices of a stock symbol on a certain date + */ + async dailyOpenClose(params: polygon.DailyOpenCloseInput) { + return this.ky + .get(`v1/open-close/${params.ticker}/${params.date}`, { + searchParams: { + adjusted: params.adjusted ?? true + } + }) + .json() + } + + /** + * Returns the previous day's open, high, low, and close (OHLC) for the specified stock ticker. + * + * @param ticker - ticker symbol of the stock/equity + * @param adjusted - whether or not the results are adjusted for splits + * @returns promise that resolves to the previous day's open, high, low, and close (OHLC) for the specified stock ticker + */ + async previousClose(ticker: string, adjusted = true) { + return this.ky + .get(`v2/aggs/ticker/${ticker}/prev`, { + searchParams: { + adjusted + } + }) + .json() + } + + /** + * Get the simple moving average (SMA) for a ticker symbol over a given time range. + * + * @param params - input parameters + * @returns promise that resolves to the simple moving average (SMA) for a ticker symbol over a given time range + */ + async sma(params: polygon.IndicatorInput) { + return this.ky + .get(`v1/indicators/sma/${params.ticker}`, { + searchParams: params + }) + .json() + } + + /** + * Get the exponential moving average (EMA) for a ticker symbol over a given time range. + * + * @param params - input parameters + * @returns promise that resolves to the exponential moving average (EMA) for a ticker symbol over a given time range + */ + async ema(params: polygon.IndicatorInput) { + return this.ky + .get(`v1/indicators/ema/${params.ticker}`, { + searchParams: params + }) + .json() + } + + /** + * Get moving average convergence/divergence (MACD) for a ticker symbol over a given time range. + * + * @param params - input parameters + * @returns promise that resolves to the moving average convergence/divergence (MACD) for a ticker symbol over a given time range + */ + async macd(params: polygon.IndicatorInput) { + return this.ky + .get(`v1/indicators/ema/${params.ticker}`, { + searchParams: params + }) + .json() + } + + /** + * Get the relative strength index (RSI) for a ticker symbol over a given time range. + * + * @param params - input parameters + * @returns promise that resolves to the relative strength index (RSI) for a ticker symbol over a given time range + */ + async rsi(params: polygon.IndicatorInput) { + return this.ky + .get(`v1/indicators/rsi/${params.ticker}`, { + searchParams: params + }) + .json() + } + + /** + * Query all ticker symbols which are supported by Polygon.io. Currently includes Stocks/Equities, Indices, Forex, and Crypto. + * + * @param params - input parameters to filter the list of ticker symbols + * @returns promise that resolves to a list of ticker symbols and their details + */ + async tickers(params: polygon.TickerInput): Promise { + return this.ky + .get('v3/reference/tickers', { searchParams: params }) + .json() + } + + /** + * List all ticker types that Polygon.io has. + * + * @param params - input parameters (`asset_class` and `locale`) + * @returns promise that resolves to ticker types + */ + async tickerTypes(params: polygon.TickerTypesInput = {}) { + return this.ky + .get('v3/reference/tickers/types', { searchParams: params }) + .json() + } + + /** + * Get the most recent news articles relating to a stock ticker symbol. + * + * @param params - input parameters (`ticker`, `published_utc`, `order`, `limit`, `sort`) + * @returns promise that resolves to ticker news + */ + async tickerNews(params: polygon.TickerNewsInput) { + return this.ky + .get('v2/reference/news', { searchParams: params }) + .json() + } + + /** + * Returns the current trading status of the exchanges and overall financial markets. + * + * @returns promise that resolves to the market status + */ + async marketStatus() { + return this.ky.get('v1/marketstatus/now').json() + } + + /** + * Gets upcoming market holidays and their open/close times. + * + * @returns promise that resolves to an array of market holidays + */ + async marketHolidays(): Promise { + return this.ky + .get('v1/marketstatus/upcoming') + .json() + } + + /** + * List all exchanges that Polygon.io knows about. + * + * @param params - input parameters (`asset_class`, `locale`) + * @returns promise that resolves to list of exchanges + */ + async exchanges(params: polygon.ExchangesInput = {}) { + return this.ky + .get('v3/reference/exchanges', { searchParams: params }) + .json() + } + + /** + * Get aggregate bars for a stock over a given date range in custom time window sizes. + * + * @param params - input parameters + * @returns promise that resolves to list of aggregates + */ + async aggregates(params: polygon.AggregatesInput) { + const { ticker, multiplier, timespan, from, to, ...otherParams } = params + const endpoint = `v2/aggs/ticker/${ticker}/range/${multiplier}/${timespan}/${from}/${to}` + return this.ky + .get(endpoint, { searchParams: otherParams }) + .json() + } + + /** + * Get the daily open, high, low, and close (OHLC) for the entire markets. + * + * @param assetClass - the asset class to get data for + * @param params - input parameters (`date`, `adjusted`, `include_otc`) + * @returns promise that resolves to list of aggregates + */ + async groupedDaily( + assetClass: 'stocks', + params: polygon.GroupedDailyInputStocks + ): Promise + + /** + * Get the daily open, high, low, and close (OHLC) for the entire markets. + * + * @param assetClass - the asset class to get data for + * @param params - input parameters (`date`, `adjusted`) + * @returns promise that resolves to list of aggregates + */ + async groupedDaily( + assetClass: polygon.ASSET_CLASS, + params: polygon.GroupedDailyInput + ) { + const { date, ...otherParams } = params + const endpoint = `v2/aggs/grouped/locale/us/market/${assetClass}/${date}` + return this.ky + .get(endpoint, { searchParams: otherParams }) + .json() + } +} diff --git a/src/services/predict-leads-client.ts b/src/services/predict-leads-client.ts new file mode 100644 index 000000000..3973d631e --- /dev/null +++ b/src/services/predict-leads-client.ts @@ -0,0 +1,793 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import type { DeepNullable } from '../types.js' +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { + assert, + getEnv, + pruneUndefined, + sanitizeSearchParams, + throttleKy +} from '../utils.js' + +// TODO: improve `domain` validation for fast-fail + +export namespace predictleads { + // Allow up to 20 requests per minute by default. + export const throttle = pThrottle({ + limit: 20, + interval: 60 * 1000 + }) + + export const DEFAULT_PAGE_SIZE = 100 + export const MAX_PAGE_SIZE = 1000 + + export type Meta = DeepNullable<{ + count: number + message?: string | null + message_type?: string + }> + + export type GenericSuccessResponse = { + success: { + type: string + message: string + } + } + + export type FollowedCompaniesResponse = { + data: DeepNullable< + Array<{ + domain: string + custom_company_identifier: string | null + }> + > + meta: Meta + } + + export type Relationship = Record< + string, + { + data: { + id: string + type: string + } + } + > + + export type AdditionalData = { + relationships: { + companies: [string, string] + } + date: string + location: string + location_data: { + region?: string + continent?: string + country?: string + state?: string + zip_code?: string + city?: string + fuzzy_match?: boolean + } + contact?: string + job_title?: string + product?: string + product_tags?: string[] + amount?: number + recognition?: string + assets?: string + asset_tags?: string[] + headcount?: number + award?: string + financing_type?: string + financing_type_tags?: string[] + funding_round?: string + division?: string + conference?: string + vulnerability?: string + planning?: boolean + article_title?: string + article_sentence?: string + article_body?: string + article_source?: string + article_published_at?: string + article_image_url?: string + } + + export type Event = { + id: string + type: string + attributes: { + categories: string[] + title: string + url: string + found_at: string + additional_data: AdditionalData + domain: string + location: string + location_data: { + state: string + country: string + } + company_name: string + friendly_company_name: string + ticker: null + meta_title: string + meta_description: string + published_at: string + post_type: string + post_url: string + company_domain: string + fuzzy_match: boolean + } + relationships: Relationship + } + + export type Response = DeepNullable<{ + data: Event[] + included: Relationship + meta: Meta + }> + + export type JobOpeningData = { + id: string + type: string + attributes: { + title: string + url: string + description: string + salary: string + salary_data: { + salary_low: number + salary_high: number + salary_currency: string + salary_low_usd: number + salary_high_usd: number + salary_time_unit: string + } + job_opening_closed: boolean + location: string + contract_types: string[] + first_seen_at: string + last_seen_at: string + last_processed_at: string + categories: string[] + onet_code: string + additional_data: { + job_title_seniority: string + tags: string[] + location_data: { + country: string + city: string + fuzzy_match: boolean + } + } + } + relationships: { + company: { + data: { + id: string + type: string + } + } + } + } + + export type CompanyData = { + id: string + type: string + attributes: { + domain: string + company_name: string + ticker: string | null + } + } + + export type JobOpeningResponse = DeepNullable<{ + data: JobOpeningData[] + included: CompanyData[] + meta: { + count: number + } + }> + + export type JobOpeningByIdResponse = Omit + + export const EventCategorySchema = z + .union([ + z + .literal('hires') + .describe( + 'Company hired new executive or senior personnel. (leadership)' + ), + z + .literal('promotes') + .describe( + 'Company promoted existing executive or senior personnel. (leadership)' + ), + z + .literal('leaves') + .describe( + 'Executive or senior personnel left the company. (leadership)' + ), + z + .literal('retires') + .describe( + 'Executive or senior personnel retires from the company. (leadership)' + ), + z + .literal('acquires') + .describe('Company acquired other company. (acquisition)'), + z + .literal('merges_with') + .describe('Company merges with other company. (acquisition)'), + z + .literal('sells_assets_to') + .describe( + 'Company sells assets (like properties or warehouses) to other company. (acquisition)' + ), + z + .literal('expands_offices_to') + .describe( + 'Company opens new offices in another town, state, country or continent. (expansion)' + ), + z + .literal('expands_offices_in') + .describe('Company expands existing offices. (expansion)'), + z + .literal('expands_facilities') + .describe( + 'Company opens new or expands existing facilities like warehouses, data centers, manufacturing plants etc. (expansion)' + ), + z + .literal('opens_new_location') + .describe( + 'Company opens new service location like hotels, restaurants, bars, hospitals etc. (expansion)' + ), + z + .literal('increases_headcount_by') + .describe('Company offers new job vacancies. (expansion)'), + z + .literal('launches') + .describe('Company launches new offering. (new_offering)'), + z + .literal('integrates_with') + .describe('Company integrates with other company. (new_offering)'), + z + .literal('is_developing') + .describe( + 'Company begins development of a new offering. (new_offering)' + ), + z + .literal('receives_financing') + .describe( + 'Company receives investment like venture funding, loan, grant etc. (investment)' + ), + z + .literal('invests_into') + .describe('Company invests into other company. (investment)'), + z + .literal('invests_into_assets') + .describe( + 'Company invests into assets like property, trucks, facilities etc. (investment)' + ), + z + .literal('goes_public') + .describe( + 'Company issues shares to the public for the first time. (investment)' + ), + z + .literal('closes_offices_in') + .describe('Company closes existing offices. (cost_cutting)'), + z + .literal('decreases_headcount_by') + .describe('Company lays off employees. (cost_cutting)'), + z + .literal('partners_with') + .describe('Company partners with other company. (partnership)'), + z + .literal('receives_award') + .describe( + 'Company or person at the company receives an award. (recognition)' + ), + z + .literal('recognized_as') + .describe( + 'Company or person at the company receives recognition. (recognition)' + ), + z + .literal('signs_new_client') + .describe('Company signs new client. (contract)'), + z + .literal('files_suit_against') + .describe( + 'Company files suit against other company. (corporate_challenges)' + ), + z + .literal('has_issues_with') + .describe('Company has vulnerability problems. (corporate_challenges)'), + z + .literal('identified_as_competitor_of') + .describe('New or existing competitor was identified. (relational)') + ]) + .describe('Event category') + export type EventCategory = z.infer + + export const CompanyParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company') + }) + export type CompanyParams = z.infer + + export const CompanyEventsParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + categories: z.array(EventCategorySchema).optional(), + found_at_from: z + .string() + .optional() + .describe('Signals found from specified date (ISO 8601).'), + found_at_until: z + .string() + .optional() + .describe('Signals found until specified date (ISO 8601).'), + page: z.number().int().positive().default(1).optional(), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional(), + with_news_article_bodies: z + .boolean() + .optional() + .describe('Whether or not to include the body contents of news articles.') + }) + export type CompanyEventsParams = z.infer + + export const CompanyFinancingEventsParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company') + }) + export type CompanyFinancingEventsParams = z.infer< + typeof CompanyFinancingEventsParamsSchema + > + + export const CompanyJobOpeningsParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + categories: z.array(EventCategorySchema).optional(), + found_at_from: z + .string() + .optional() + .describe('Signals found from specified date (ISO 8601).'), + found_at_until: z + .string() + .optional() + .describe('Signals found until specified date (ISO 8601).'), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional(), + with_job_descriptions: z + .boolean() + .optional() + .describe('Whether or not to include the full descriptions of the jobs.'), + with_description_only: z + .boolean() + .optional() + .describe('If set, only returns job openings with descriptions.'), + with_location_only: z + .boolean() + .optional() + .describe('If set, only returns job openings with locations.'), + active_only: z + .boolean() + .optional() + .describe( + 'If set, only returns job openings that are not closed, have `last_seen_at` more recent than 5 days and were found in the last year.' + ), + not_closed: z + .boolean() + .optional() + .describe( + 'Similar to `active_only`, but without considering `last_seen_at` timestamp.' + ) + }) + export type CompanyJobOpeningsParams = z.infer< + typeof CompanyJobOpeningsParamsSchema + > + + export const CompanyTechnologiesParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + categories: z.array(EventCategorySchema).optional(), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional() + }) + export type CompanyTechnologiesParams = z.infer< + typeof CompanyTechnologiesParamsSchema + > + + export const CompanyConnectionsParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + categories: z.array(EventCategorySchema).optional(), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional() + }) + export type CompanyConnectionsParams = z.infer< + typeof CompanyConnectionsParamsSchema + > + + export const CompanyWebsiteEvolutionParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional() + }) + export type CompanyWebsiteEvolutionParams = z.infer< + typeof CompanyWebsiteEvolutionParamsSchema + > + + export const CompanyGitHubReposParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional() + }) + export type CompanyGitHubReposParams = z.infer< + typeof CompanyGitHubReposParamsSchema + > + + export const CompanyProductsParamsSchema = z.object({ + domain: z.string().min(3).describe('domain of the company'), + sources: z.array(z.string()).optional(), + limit: z + .number() + .int() + .positive() + .max(MAX_PAGE_SIZE) + .default(DEFAULT_PAGE_SIZE) + .optional() + }) + export type CompanyProductsParams = z.infer< + typeof CompanyProductsParamsSchema + > +} + +/** + * In-depth company data, including signals like fundraising announcemnts, + * hiring intent, new customers signed, technologies used, product launches, + * location expansions, awards received, etc. + * + * @see https://predictleads.com + */ +export class PredictLeadsClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiToken: string + + constructor({ + apiKey = getEnv('PREDICT_LEADS_API_KEY'), + apiToken = getEnv('PREDICT_LEADS_API_TOKEN'), + timeoutMs = 30_000, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiToken?: string + apiBaseUrl?: string + timeoutMs?: number + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'PredictLeadsClient missing required "apiKey" (defaults to "PREDICT_LEADS_API_KEY")' + ) + assert( + apiToken, + 'PredictLeadsClient missing required "apiToken" (defaults to "PREDICT_LEADS_API_TOKEN")' + ) + super() + + this.apiKey = apiKey + this.apiToken = apiToken + + const throttledKy = throttle ? throttleKy(ky, predictleads.throttle) : ky + + this.ky = throttledKy.extend({ + prefixUrl: 'https://predictleads.com/api', + timeout: timeoutMs, + headers: { + 'x-api-key': apiKey, + 'x-api-token': apiToken + } + }) + } + + @aiFunction({ + name: 'get_company', + description: + 'Returns basic information about a company given its `domain` like location, name, stock ticker, description, etc.', + inputSchema: predictleads.CompanyParamsSchema + }) + async company(domainOrOpts: string | predictleads.CompanyParams) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky.get(`v2/companies/${domain}`).json() + } + + @aiFunction({ + name: 'get_company_events', + description: + 'Returns a list of events from news for a given company. Events are found in press releases, industry news, blogs, social media, and other online sources.', + inputSchema: predictleads.CompanyEventsParamsSchema + }) + async getCompanyEvents( + domainOrOpts: string | predictleads.CompanyEventsParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { + domain, + page = 1, + limit = predictleads.DEFAULT_PAGE_SIZE, + ...params + } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/events`, { + searchParams: sanitizeSearchParams({ + page, + limit, + ...params + }) + }) + .json() + } + + async getEventById(id: string) { + return this.ky.get(`v2/events/${id}`).json() + } + + @aiFunction({ + name: 'get_company_financing_events', + description: + 'Returns a list of financing events for a given company. Financing events include fundraising announcements and quarterly earning reports for public companies. They are sourced from press releases, industry news, blogs, social media, and other online sources.', + inputSchema: predictleads.CompanyFinancingEventsParamsSchema + }) + async getCompanyFinancingEvents( + domainOrOpts: string | predictleads.CompanyFinancingEventsParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/financing_events`) + .json() + } + + @aiFunction({ + name: 'get_company_job_openings', + description: + 'Returns a list of job openings for a given company. Job openings are found on companies’ career sites and job boards.', + inputSchema: predictleads.CompanyJobOpeningsParamsSchema + }) + async getCompanyJobOpenings( + domainOrOpts: string | predictleads.CompanyJobOpeningsParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/job_openings`, { + searchParams: sanitizeSearchParams({ + limit, + ...params + }) + }) + .json() + } + + async getJobOpeningById(id: string) { + return this.ky + .get(`v2/job_openings/${id}`) + .json() + } + + @aiFunction({ + name: 'get_company_technologies', + description: 'Returns a list of technology providers for a given company.', + inputSchema: predictleads.CompanyTechnologiesParamsSchema + }) + async getCompanyTechnologies( + domainOrOpts: string | predictleads.CompanyTechnologiesParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/technologies`, { + searchParams: sanitizeSearchParams({ + limit, + ...params + }) + }) + .json() + } + + @aiFunction({ + name: 'get_company_connections', + description: + 'Returns a list of categorized business connections. Business connections can be found via backlinks or logos on /our-customers, /case-studies, /portfolio, /clients etc. pages. Business connections enable you to eg. calculate network health of a company, to build systems when new high value connections are made… Connections can be of many types: partner, vendor, investor, parent…', + inputSchema: predictleads.CompanyConnectionsParamsSchema + }) + async getCompanyConnections( + domainOrOpts: string | predictleads.CompanyConnectionsParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/connections`, { + searchParams: sanitizeSearchParams({ + limit, + ...params + }) + }) + .json() + } + + @aiFunction({ + name: 'get_company_website_evolution', + description: + 'Returns insights into how a website has changed over time. E.g., when pages like “Blog”, “Privacy policy”, “Pricing”, “Product”, “API Docs”, “Team”, “Support pages” etc were added. This can serve as a proxy to how quickly a website is growing, to determine the growth stage they are at and also to help segment websites.', + inputSchema: predictleads.CompanyWebsiteEvolutionParamsSchema + }) + async getCompanyWebsiteEvolution( + domainOrOpts: string | predictleads.CompanyWebsiteEvolutionParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/website_evolution`, { + searchParams: sanitizeSearchParams({ limit, ...params }) + }) + .json() + } + + @aiFunction({ + name: 'get_company_github_repos', + description: + 'Returns insights into how frequently a company is contributing to its public GitHub repositories.', + inputSchema: predictleads.CompanyGitHubReposParamsSchema + }) + async getCompanyGitHubRepositories( + domainOrOpts: string | predictleads.CompanyGitHubReposParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/github_repositories`, { + searchParams: sanitizeSearchParams({ limit, ...params }) + }) + .json() + } + + @aiFunction({ + name: 'get_company_products', + description: + 'Returns what kind of products / solutions / features a company is offering.', + inputSchema: predictleads.CompanyProductsParamsSchema + }) + async getCompanyProducts( + domainOrOpts: string | predictleads.CompanyProductsParams + ) { + const opts = + typeof domainOrOpts === 'string' ? { domain: domainOrOpts } : domainOrOpts + const { domain, limit = predictleads.DEFAULT_PAGE_SIZE, ...params } = opts + assert(domain, 'Missing required company "domain"') + + return this.ky + .get(`v2/companies/${domain}/products`, { + searchParams: sanitizeSearchParams({ + limit, + ...params + }) + }) + .json() + } + + async discoverStartupJobsHN(params?: { + post_datetime_from?: string + post_datetime_until?: string + min_score?: string + limit?: string + }) { + return this.ky + .get(`v2/discover/startup_platform/jobs_hn`, { + searchParams: params + }) + .json() + } + + async discoverStartupShowHN(params?: { + post_datetime_from?: string + post_datetime_until?: string + min_score?: string + limit?: string + }) { + return this.ky + .get(`v2/discover/startup_platform/show_hn`, { + searchParams: params + }) + .json() + } + + // -------------------------------------------------------------------------- + // Stateful endpoints which should generally not be used as AI functions. + // -------------------------------------------------------------------------- + + async followCompany(domain: string, customCompanyIdentifier?: string) { + return this.ky + .post(`v2/companies/${domain}/follow`, { + json: pruneUndefined({ customCompanyIdentifier }) + }) + .json() + } + + async getFollowingCompanies(limit: number = predictleads.DEFAULT_PAGE_SIZE) { + return this.ky + .get(`v2/followings`, { + searchParams: sanitizeSearchParams({ limit }) + }) + .json() + } + + async unfollowCompany(domain: string, customCompanyIdentifier?: string) { + return this.ky + .post(`v2/companies/${domain}/unfollow`, { + json: pruneUndefined({ customCompanyIdentifier }) + }) + .json() + } +} diff --git a/src/services/proxycurl-client.ts b/src/services/proxycurl-client.ts new file mode 100644 index 000000000..b83eccf00 --- /dev/null +++ b/src/services/proxycurl-client.ts @@ -0,0 +1,2183 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, throttleKy } from '../utils.js' + +// All proxycurl types are auto-generated from their openapi spec +export namespace proxycurl { + // Allow up to 300 requests per minute by default (enforced at 5 minute intervals). + export const throttle = pThrottle({ + limit: 1500, + interval: 5 * 60 * 1000 + }) + + export const CompanyTypeSchema = z.enum([ + 'EDUCATIONAL', + 'GOVERNMENT_AGENCY', + 'NON_PROFIT', + 'PARTNERSHIP', + 'PRIVATELY_HELD', + 'PUBLIC_COMPANY', + 'SELF_EMPLOYED', + 'SELF_OWNED' + ]) + export type CompanyType = z.infer + + export const CompanyProfileEndpointParamsQueryClassSchema = z.object({ + acquisitions: z.string().optional(), + categories: z.string().optional(), + exit_data: z.string().optional(), + extra: z.string().optional(), + fallback_to_cache: z.string().optional(), + funding_data: z.string().optional(), + resolve_numeric_id: z.string().optional(), + url: z.string(), + use_cache: z.string().optional() + }) + export type CompanyProfileEndpointParamsQueryClass = z.infer< + typeof CompanyProfileEndpointParamsQueryClassSchema + > + + export const PersonProfileEndpointParamsQueryClassSchema = z.object({ + extra: z.string().optional(), + facebook_profile_id: z.string().optional(), + facebook_profile_url: z.string().optional(), + fallback_to_cache: z.string().optional(), + github_profile_id: z.string().optional(), + inferred_salary: z.string().optional(), + linkedin_profile_url: z.string().optional(), + personal_contact_number: z.string().optional(), + personal_email: z.string().optional(), + skills: z.string().optional(), + twitter_profile_id: z.string().optional(), + twitter_profile_url: z.string().optional(), + use_cache: z.string().optional() + }) + export type PersonProfileEndpointParamsQueryClass = z.infer< + typeof PersonProfileEndpointParamsQueryClassSchema + > + + export const PersonLookupEndpointParamsQueryClassSchema = z.object({ + company_domain: z + .string() + .describe('The domain URL of the company the person works at'), + enrich_profile: z.string().optional(), + first_name: z.string(), + last_name: z.string().optional(), + location: z.string().optional(), + similarity_checks: z.string().optional(), + title: z.string().optional() + }) + export type PersonLookupEndpointParamsQueryClass = z.infer< + typeof PersonLookupEndpointParamsQueryClassSchema + > + + export const RoleLookupEndpointParamsQueryClassSchema = z.object({ + company_name: z.string(), + role: z.string(), + enrich_profile: z.string().optional() + }) + export type RoleLookupEndpointParamsQueryClass = z.infer< + typeof RoleLookupEndpointParamsQueryClassSchema + > + + export const CompanyLookupEndpointParamsQueryClassSchema = z.object({ + company_domain: z.string().optional(), + company_location: z.string().optional(), + company_name: z.string().optional(), + enrich_profile: z.string().optional() + }) + export type CompanyLookupEndpointParamsQueryClass = z.infer< + typeof CompanyLookupEndpointParamsQueryClassSchema + > + + export const ReverseEmailLookupEndpointParamsQueryClassSchema = z.object({ + email: z.string(), + enrich_profile: z.string().optional(), + lookup_depth: z.string().optional() + }) + export type ReverseEmailLookupEndpointParamsQueryClass = z.infer< + typeof ReverseEmailLookupEndpointParamsQueryClassSchema + > + + export const CompanySearchEndpointParamsQueryClassSchema = z.object({ + city: z.string().optional(), + country: z.string().optional(), + description: z.string().optional(), + employee_count_max: z.string().optional(), + employee_count_min: z.string().optional(), + follower_count_max: z.string().optional(), + follower_count_min: z.string().optional(), + founded_after_year: z.string().optional(), + founded_before_year: z.string().optional(), + funding_amount_max: z.string().optional(), + funding_amount_min: z.string().optional(), + funding_raised_after: z.string().optional(), + funding_raised_before: z.string().optional(), + industry: z.string().optional(), + name: z.string().optional(), + page_size: z.string().optional(), + public_identifier_in_list: z.string().optional(), + public_identifier_not_in_list: z.string().optional(), + region: z.string().optional(), + type: z.string().optional(), + enrich_profiles: z.string().optional() + }) + export type CompanySearchEndpointParamsQueryClass = z.infer< + typeof CompanySearchEndpointParamsQueryClassSchema + > + + export const PersonSearchEndpointParamsQueryClassSchema = z.object({ + city: z.string().optional(), + country: z.string(), + current_company_city: z.string().optional(), + current_company_country: z.string().optional(), + current_company_description: z.string().optional(), + current_company_employee_count_max: z.string().optional(), + current_company_employee_count_min: z.string().optional(), + current_company_follower_count_max: z.string().optional(), + current_company_follower_count_min: z.string().optional(), + current_company_founded_after_year: z.string().optional(), + current_company_founded_before_year: z.string().optional(), + current_company_funding_amount_max: z.string().optional(), + current_company_funding_amount_min: z.string().optional(), + current_company_funding_raised_after: z.string().optional(), + current_company_funding_raised_before: z.string().optional(), + current_company_industry: z.string().optional(), + current_company_linkedin_profile_url: z.string().optional(), + current_company_name: z.string().optional(), + current_company_region: z.string().optional(), + current_company_type: z.string().optional(), + current_job_description: z.string().optional(), + current_role_after: z.string().optional(), + current_role_before: z.string().optional(), + current_role_title: z.string().optional(), + education_degree_name: z.string().optional(), + education_field_of_study: z.string().optional(), + education_school_linkedin_profile_url: z.string().optional(), + education_school_name: z.string().optional(), + enrich_profiles: z.string().optional(), + first_name: z.string().optional(), + headline: z.string().optional(), + industries: z.string().optional(), + interests: z.string().optional(), + languages: z.string().optional(), + last_name: z.string().optional(), + linkedin_groups: z.string().optional(), + page_size: z.string().optional(), + past_company_linkedin_profile_url: z.string().optional(), + past_company_name: z.string().optional(), + past_job_description: z.string().optional(), + past_role_title: z.string().optional(), + public_identifier_in_list: z.string().optional(), + public_identifier_not_in_list: z.string().optional(), + region: z.string().optional(), + skills: z.string().optional(), + summary: z.string().optional() + }) + export type PersonSearchEndpointParamsQueryClass = z.infer< + typeof PersonSearchEndpointParamsQueryClassSchema + > + + export const PurpleCourseSchema = z.object({ + name: z.string().optional(), + number: z.string().optional() + }) + export type PurpleCourse = z.infer + + export const PurpleDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type PurpleDate = z.infer + + export const FluffyDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type FluffyDate = z.infer + + export const TentacledDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type TentacledDate = z.infer + + export const StickyDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type StickyDate = z.infer + + export const IndigoDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type IndigoDate = z.infer + + export const IndecentDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type IndecentDate = z.infer + + export const HilariousDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type HilariousDate = z.infer + + export const AmbitiousDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type AmbitiousDate = z.infer + + export const PurpleActivitySchema = z.object({ + activity_status: z.string().optional(), + link: z.string().optional(), + title: z.string().optional() + }) + export type PurpleActivity = z.infer + + export const CunningDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type CunningDate = z.infer + + export const MagentaDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type MagentaDate = z.infer + + export const FriskyDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type FriskyDate = z.infer + + export const MischievousDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type MischievousDate = z.infer + + export const BraggadociousDateSchema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type BraggadociousDate = z.infer + + export const Date1Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date1 = z.infer + + export const Date2Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date2 = z.infer + + export const Date3Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date3 = z.infer + + export const PurplePersonExtraSchema = z.object({ + facebook_profile_id: z.string().optional(), + github_profile_id: z.string().optional(), + twitter_profile_id: z.string().optional(), + website: z.string().optional() + }) + export type PurplePersonExtra = z.infer + + export const PurplePersonGroupSchema = z.object({ + name: z.string().optional(), + profile_pic_url: z.string().optional(), + url: z.string().optional() + }) + export type PurplePersonGroup = z.infer + + export const PurpleInferredSalarySchema = z.object({ + max: z.number().optional(), + min: z.number().optional() + }) + export type PurpleInferredSalary = z.infer + + export const PurplePeopleAlsoViewedSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type PurplePeopleAlsoViewed = z.infer< + typeof PurplePeopleAlsoViewedSchema + > + + export const PurpleSimilarProfileSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type PurpleSimilarProfile = z.infer + + export const Date4Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date4 = z.infer + + export const Date5Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date5 = z.infer + + export const FluffyCourseSchema = z.object({ + name: z.string().optional(), + number: z.string().optional() + }) + export type FluffyCourse = z.infer + + export const Date6Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date6 = z.infer + + export const Date7Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date7 = z.infer + + export const Date8Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date8 = z.infer + + export const Date9Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date9 = z.infer + + export const Date10Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date10 = z.infer + + export const Date11Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date11 = z.infer + + export const Date12Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date12 = z.infer + + export const Date13Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date13 = z.infer + + export const FluffyActivitySchema = z.object({ + activity_status: z.string().optional(), + link: z.string().optional(), + title: z.string().optional() + }) + export type FluffyActivity = z.infer + + export const Date14Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date14 = z.infer + + export const Date15Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date15 = z.infer + + export const Date16Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date16 = z.infer + + export const Date17Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date17 = z.infer + + export const Date18Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date18 = z.infer + + export const Date19Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date19 = z.infer + + export const Date20Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date20 = z.infer + + export const Date21Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date21 = z.infer + + export const FluffyPersonExtraSchema = z.object({ + facebook_profile_id: z.string().optional(), + github_profile_id: z.string().optional(), + twitter_profile_id: z.string().optional(), + website: z.string().optional() + }) + export type FluffyPersonExtra = z.infer + + export const FluffyPersonGroupSchema = z.object({ + name: z.string().optional(), + profile_pic_url: z.string().optional(), + url: z.string().optional() + }) + export type FluffyPersonGroup = z.infer + + export const FluffyInferredSalarySchema = z.object({ + max: z.number().optional(), + min: z.number().optional() + }) + export type FluffyInferredSalary = z.infer + + export const FluffyPeopleAlsoViewedSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type FluffyPeopleAlsoViewed = z.infer< + typeof FluffyPeopleAlsoViewedSchema + > + + export const FluffySimilarProfileSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type FluffySimilarProfile = z.infer + + export const Date22Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date22 = z.infer + + export const Date23Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date23 = z.infer + + export const TentacledCourseSchema = z.object({ + name: z.string().optional(), + number: z.string().optional() + }) + export type TentacledCourse = z.infer + + export const Date24Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date24 = z.infer + + export const Date25Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date25 = z.infer + + export const Date26Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date26 = z.infer + + export const Date27Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date27 = z.infer + + export const Date28Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date28 = z.infer + + export const Date29Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date29 = z.infer + + export const Date30Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date30 = z.infer + + export const Date31Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date31 = z.infer + + export const TentacledActivitySchema = z.object({ + activity_status: z.string().optional(), + link: z.string().optional(), + title: z.string().optional() + }) + export type TentacledActivity = z.infer + + export const Date32Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date32 = z.infer + + export const Date33Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date33 = z.infer + + export const Date34Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date34 = z.infer + + export const Date35Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date35 = z.infer + + export const Date36Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date36 = z.infer + + export const Date37Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date37 = z.infer + + export const Date38Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date38 = z.infer + + export const Date39Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date39 = z.infer + + export const TentacledPersonExtraSchema = z.object({ + facebook_profile_id: z.string().optional(), + github_profile_id: z.string().optional(), + twitter_profile_id: z.string().optional(), + website: z.string().optional() + }) + export type TentacledPersonExtra = z.infer + + export const TentacledPersonGroupSchema = z.object({ + name: z.string().optional(), + profile_pic_url: z.string().optional(), + url: z.string().optional() + }) + export type TentacledPersonGroup = z.infer + + export const TentacledInferredSalarySchema = z.object({ + max: z.number().optional(), + min: z.number().optional() + }) + export type TentacledInferredSalary = z.infer< + typeof TentacledInferredSalarySchema + > + + export const TentacledPeopleAlsoViewedSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type TentacledPeopleAlsoViewed = z.infer< + typeof TentacledPeopleAlsoViewedSchema + > + + export const TentacledSimilarProfileSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type TentacledSimilarProfile = z.infer< + typeof TentacledSimilarProfileSchema + > + + export const Date40Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date40 = z.infer + + export const Date41Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date41 = z.infer + + export const StickyCourseSchema = z.object({ + name: z.string().optional(), + number: z.string().optional() + }) + export type StickyCourse = z.infer + + export const Date42Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date42 = z.infer + + export const Date43Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date43 = z.infer + + export const Date44Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date44 = z.infer + + export const Date45Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date45 = z.infer + + export const Date46Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date46 = z.infer + + export const Date47Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date47 = z.infer + + export const Date48Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date48 = z.infer + + export const Date49Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date49 = z.infer + + export const StickyActivitySchema = z.object({ + activity_status: z.string().optional(), + link: z.string().optional(), + title: z.string().optional() + }) + export type StickyActivity = z.infer + + export const Date50Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date50 = z.infer + + export const Date51Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date51 = z.infer + + export const Date52Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date52 = z.infer + + export const Date53Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date53 = z.infer + + export const Date54Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date54 = z.infer + + export const Date55Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date55 = z.infer + + export const Date56Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date56 = z.infer + + export const StickyPersonGroupSchema = z.object({ + name: z.string().optional(), + profile_pic_url: z.string().optional(), + url: z.string().optional() + }) + export type StickyPersonGroup = z.infer + + export const StickyPeopleAlsoViewedSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type StickyPeopleAlsoViewed = z.infer< + typeof StickyPeopleAlsoViewedSchema + > + + export const StickySimilarProfileSchema = z.object({ + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional(), + summary: z.string().optional() + }) + export type StickySimilarProfile = z.infer + + export const Date57Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date57 = z.infer + + export const Date58Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date58 = z.infer + + export const Date59Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date59 = z.infer + + export const Date60Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date60 = z.infer + + export const PurpleAffiliatedCompanySchema = z.object({ + industry: z.string().optional(), + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional() + }) + export type PurpleAffiliatedCompany = z.infer< + typeof PurpleAffiliatedCompanySchema + > + + export const PurpleExitSchema = z.object({ + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + name: z.string().optional() + }) + export type PurpleExit = z.infer + + export const Date61Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date61 = z.infer + + export const Date62Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date62 = z.infer + + export const Date63Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date63 = z.infer + + export const PurpleInvestorSchema = z.object({ + linkedin_profile_url: z.string().optional(), + name: z.string().optional(), + type: z.string().optional() + }) + export type PurpleInvestor = z.infer + + export const PurpleCompanyLocationSchema = z.object({ + city: z.string().optional(), + country: z.string().optional(), + is_hq: z.boolean().optional(), + line_1: z.string().optional(), + postal_code: z.string().optional(), + state: z.string().optional() + }) + export type PurpleCompanyLocation = z.infer< + typeof PurpleCompanyLocationSchema + > + + export const FluffyCompanyLocationSchema = z.object({ + city: z.string().optional(), + country: z.string().optional(), + is_hq: z.boolean().optional(), + line_1: z.string().optional(), + postal_code: z.string().optional(), + state: z.string().optional() + }) + export type FluffyCompanyLocation = z.infer< + typeof FluffyCompanyLocationSchema + > + + export const PurpleSimilarCompanySchema = z.object({ + industry: z.string().optional(), + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional() + }) + export type PurpleSimilarCompany = z.infer + + export const Date64Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date64 = z.infer + + export const Date65Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date65 = z.infer + + export const Date66Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date66 = z.infer + + export const FluffyAffiliatedCompanySchema = z.object({ + industry: z.string().optional(), + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional() + }) + export type FluffyAffiliatedCompany = z.infer< + typeof FluffyAffiliatedCompanySchema + > + + export const FluffyExitSchema = z.object({ + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + name: z.string().optional() + }) + export type FluffyExit = z.infer + + export const Date67Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date67 = z.infer + + export const Date68Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date68 = z.infer + + export const Date69Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date69 = z.infer + + export const FluffyInvestorSchema = z.object({ + linkedin_profile_url: z.string().optional(), + name: z.string().optional(), + type: z.string().optional() + }) + export type FluffyInvestor = z.infer + + export const TentacledCompanyLocationSchema = z.object({ + city: z.string().optional(), + country: z.string().optional(), + is_hq: z.boolean().optional(), + line_1: z.string().optional(), + postal_code: z.string().optional(), + state: z.string().optional() + }) + export type TentacledCompanyLocation = z.infer< + typeof TentacledCompanyLocationSchema + > + + export const StickyCompanyLocationSchema = z.object({ + city: z.string().optional(), + country: z.string().optional(), + is_hq: z.boolean().optional(), + line_1: z.string().optional(), + postal_code: z.string().optional(), + state: z.string().optional() + }) + export type StickyCompanyLocation = z.infer< + typeof StickyCompanyLocationSchema + > + + export const FluffySimilarCompanySchema = z.object({ + industry: z.string().optional(), + link: z.string().optional(), + location: z.string().optional(), + name: z.string().optional() + }) + export type FluffySimilarCompany = z.infer + + export const Date70Schema = z.object({ + day: z.number().optional(), + month: z.number().optional(), + year: z.number().optional() + }) + export type Date70 = z.infer + + export const PurpleHonourAwardSchema = z.object({ + description: z.string().optional(), + issued_on: PurpleDateSchema.optional(), + issuer: z.string().optional(), + title: z.string().optional() + }) + export type PurpleHonourAward = z.infer + + export const PurpleAccomplishmentOrgSchema = z.object({ + description: z.string().optional(), + ends_at: FluffyDateSchema.optional(), + org_name: z.string().optional(), + starts_at: TentacledDateSchema.optional(), + title: z.string().optional() + }) + export type PurpleAccomplishmentOrg = z.infer< + typeof PurpleAccomplishmentOrgSchema + > + + export const PurplePatentSchema = z.object({ + application_number: z.string().optional(), + description: z.string().optional(), + issued_on: StickyDateSchema.optional(), + issuer: z.string().optional(), + patent_number: z.string().optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type PurplePatent = z.infer + + export const PurpleProjectSchema = z.object({ + description: z.string().optional(), + ends_at: IndigoDateSchema.optional(), + starts_at: IndecentDateSchema.optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type PurpleProject = z.infer + + export const PurplePublicationSchema = z.object({ + description: z.string().optional(), + name: z.string().optional(), + published_on: HilariousDateSchema.optional(), + publisher: z.string().optional(), + url: z.string().optional() + }) + export type PurplePublication = z.infer + + export const PurpleTestScoreSchema = z.object({ + date_on: AmbitiousDateSchema.optional(), + description: z.string().optional(), + name: z.string().optional(), + score: z.string().optional() + }) + export type PurpleTestScore = z.infer + + export const PurpleArticleSchema = z.object({ + author: z.string().optional(), + image_url: z.string().optional(), + link: z.string().optional(), + published_date: CunningDateSchema.optional(), + title: z.string().optional() + }) + export type PurpleArticle = z.infer + + export const PurpleCertificationSchema = z.object({ + authority: z.string().optional(), + display_source: z.string().optional(), + ends_at: FriskyDateSchema.optional(), + license_number: z.string().optional(), + name: z.string().optional(), + starts_at: MischievousDateSchema.optional(), + url: z.string().optional() + }) + export type PurpleCertification = z.infer + + export const PurpleEducationSchema = z.object({ + activities_and_societies: z.string().optional(), + degree_name: z.string().optional(), + description: z.string().optional(), + ends_at: BraggadociousDateSchema.optional(), + field_of_study: z.string().optional(), + grade: z.string().optional(), + logo_url: z.string().optional(), + school: z.string().optional(), + school_facebook_profile_url: z.string().optional(), + school_linkedin_profile_url: z.string().optional(), + starts_at: Date1Schema.optional() + }) + export type PurpleEducation = z.infer + + export const PurpleExperienceSchema = z.object({ + company: z.string().optional(), + company_facebook_profile_url: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date2Schema.optional(), + location: z.string().optional(), + logo_url: z.string().optional(), + starts_at: Date3Schema.optional(), + title: z.string().optional() + }) + export type PurpleExperience = z.infer + + export const PurpleVolunteeringExperienceSchema = z.object({ + cause: z.string().optional(), + company: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date4Schema.optional(), + logo_url: z.string().optional(), + starts_at: Date5Schema.optional(), + title: z.string().optional() + }) + export type PurpleVolunteeringExperience = z.infer< + typeof PurpleVolunteeringExperienceSchema + > + + export const FluffyHonourAwardSchema = z.object({ + description: z.string().optional(), + issued_on: Date6Schema.optional(), + issuer: z.string().optional(), + title: z.string().optional() + }) + export type FluffyHonourAward = z.infer + + export const FluffyAccomplishmentOrgSchema = z.object({ + description: z.string().optional(), + ends_at: Date7Schema.optional(), + org_name: z.string().optional(), + starts_at: Date8Schema.optional(), + title: z.string().optional() + }) + export type FluffyAccomplishmentOrg = z.infer< + typeof FluffyAccomplishmentOrgSchema + > + + export const FluffyPatentSchema = z.object({ + application_number: z.string().optional(), + description: z.string().optional(), + issued_on: Date9Schema.optional(), + issuer: z.string().optional(), + patent_number: z.string().optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type FluffyPatent = z.infer + + export const FluffyProjectSchema = z.object({ + description: z.string().optional(), + ends_at: Date10Schema.optional(), + starts_at: Date11Schema.optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type FluffyProject = z.infer + + export const FluffyPublicationSchema = z.object({ + description: z.string().optional(), + name: z.string().optional(), + published_on: Date12Schema.optional(), + publisher: z.string().optional(), + url: z.string().optional() + }) + export type FluffyPublication = z.infer + + export const FluffyTestScoreSchema = z.object({ + date_on: Date13Schema.optional(), + description: z.string().optional(), + name: z.string().optional(), + score: z.string().optional() + }) + export type FluffyTestScore = z.infer + + export const FluffyArticleSchema = z.object({ + author: z.string().optional(), + image_url: z.string().optional(), + link: z.string().optional(), + published_date: Date14Schema.optional(), + title: z.string().optional() + }) + export type FluffyArticle = z.infer + + export const FluffyCertificationSchema = z.object({ + authority: z.string().optional(), + display_source: z.string().optional(), + ends_at: Date16Schema.optional(), + license_number: z.string().optional(), + name: z.string().optional(), + starts_at: Date17Schema.optional(), + url: z.string().optional() + }) + export type FluffyCertification = z.infer + + export const FluffyEducationSchema = z.object({ + activities_and_societies: z.string().optional(), + degree_name: z.string().optional(), + description: z.string().optional(), + ends_at: Date18Schema.optional(), + field_of_study: z.string().optional(), + grade: z.string().optional(), + logo_url: z.string().optional(), + school: z.string().optional(), + school_facebook_profile_url: z.string().optional(), + school_linkedin_profile_url: z.string().optional(), + starts_at: Date19Schema.optional() + }) + export type FluffyEducation = z.infer + + export const FluffyExperienceSchema = z.object({ + company: z.string().optional(), + company_facebook_profile_url: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date20Schema.optional(), + location: z.string().optional(), + logo_url: z.string().optional(), + starts_at: Date21Schema.optional(), + title: z.string().optional() + }) + export type FluffyExperience = z.infer + + export const FluffyVolunteeringExperienceSchema = z.object({ + cause: z.string().optional(), + company: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date22Schema.optional(), + logo_url: z.string().optional(), + starts_at: Date23Schema.optional(), + title: z.string().optional() + }) + export type FluffyVolunteeringExperience = z.infer< + typeof FluffyVolunteeringExperienceSchema + > + + export const TentacledHonourAwardSchema = z.object({ + description: z.string().optional(), + issued_on: Date24Schema.optional(), + issuer: z.string().optional(), + title: z.string().optional() + }) + export type TentacledHonourAward = z.infer + + export const TentacledAccomplishmentOrgSchema = z.object({ + description: z.string().optional(), + ends_at: Date25Schema.optional(), + org_name: z.string().optional(), + starts_at: Date26Schema.optional(), + title: z.string().optional() + }) + export type TentacledAccomplishmentOrg = z.infer< + typeof TentacledAccomplishmentOrgSchema + > + + export const TentacledPatentSchema = z.object({ + application_number: z.string().optional(), + description: z.string().optional(), + issued_on: Date27Schema.optional(), + issuer: z.string().optional(), + patent_number: z.string().optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type TentacledPatent = z.infer + + export const TentacledProjectSchema = z.object({ + description: z.string().optional(), + ends_at: Date28Schema.optional(), + starts_at: Date29Schema.optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type TentacledProject = z.infer + + export const TentacledPublicationSchema = z.object({ + description: z.string().optional(), + name: z.string().optional(), + published_on: Date30Schema.optional(), + publisher: z.string().optional(), + url: z.string().optional() + }) + export type TentacledPublication = z.infer + + export const TentacledTestScoreSchema = z.object({ + date_on: Date31Schema.optional(), + description: z.string().optional(), + name: z.string().optional(), + score: z.string().optional() + }) + export type TentacledTestScore = z.infer + + export const TentacledArticleSchema = z.object({ + author: z.string().optional(), + image_url: z.string().optional(), + link: z.string().optional(), + published_date: Date32Schema.optional(), + title: z.string().optional() + }) + export type TentacledArticle = z.infer + + export const TentacledCertificationSchema = z.object({ + authority: z.string().optional(), + display_source: z.string().optional(), + ends_at: Date34Schema.optional(), + license_number: z.string().optional(), + name: z.string().optional(), + starts_at: Date35Schema.optional(), + url: z.string().optional() + }) + export type TentacledCertification = z.infer< + typeof TentacledCertificationSchema + > + + export const TentacledEducationSchema = z.object({ + activities_and_societies: z.string().optional(), + degree_name: z.string().optional(), + description: z.string().optional(), + ends_at: Date36Schema.optional(), + field_of_study: z.string().optional(), + grade: z.string().optional(), + logo_url: z.string().optional(), + school: z.string().optional(), + school_facebook_profile_url: z.string().optional(), + school_linkedin_profile_url: z.string().optional(), + starts_at: Date37Schema.optional() + }) + export type TentacledEducation = z.infer + + export const TentacledExperienceSchema = z.object({ + company: z.string().optional(), + company_facebook_profile_url: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date38Schema.optional(), + location: z.string().optional(), + logo_url: z.string().optional(), + starts_at: Date39Schema.optional(), + title: z.string().optional() + }) + export type TentacledExperience = z.infer + + export const TentacledVolunteeringExperienceSchema = z.object({ + cause: z.string().optional(), + company: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date40Schema.optional(), + logo_url: z.string().optional(), + starts_at: Date41Schema.optional(), + title: z.string().optional() + }) + export type TentacledVolunteeringExperience = z.infer< + typeof TentacledVolunteeringExperienceSchema + > + + export const StickyHonourAwardSchema = z.object({ + description: z.string().optional(), + issued_on: Date42Schema.optional(), + issuer: z.string().optional(), + title: z.string().optional() + }) + export type StickyHonourAward = z.infer + + export const StickyAccomplishmentOrgSchema = z.object({ + description: z.string().optional(), + ends_at: Date43Schema.optional(), + org_name: z.string().optional(), + starts_at: Date44Schema.optional(), + title: z.string().optional() + }) + export type StickyAccomplishmentOrg = z.infer< + typeof StickyAccomplishmentOrgSchema + > + + export const StickyPatentSchema = z.object({ + application_number: z.string().optional(), + description: z.string().optional(), + issued_on: Date45Schema.optional(), + issuer: z.string().optional(), + patent_number: z.string().optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type StickyPatent = z.infer + + export const StickyProjectSchema = z.object({ + description: z.string().optional(), + ends_at: Date46Schema.optional(), + starts_at: Date47Schema.optional(), + title: z.string().optional(), + url: z.string().optional() + }) + export type StickyProject = z.infer + + export const StickyPublicationSchema = z.object({ + description: z.string().optional(), + name: z.string().optional(), + published_on: Date48Schema.optional(), + publisher: z.string().optional(), + url: z.string().optional() + }) + export type StickyPublication = z.infer + + export const StickyTestScoreSchema = z.object({ + date_on: Date49Schema.optional(), + description: z.string().optional(), + name: z.string().optional(), + score: z.string().optional() + }) + export type StickyTestScore = z.infer + + export const StickyArticleSchema = z.object({ + author: z.string().optional(), + image_url: z.string().optional(), + link: z.string().optional(), + published_date: Date50Schema.optional(), + title: z.string().optional() + }) + export type StickyArticle = z.infer + + export const StickyCertificationSchema = z.object({ + authority: z.string().optional(), + display_source: z.string().optional(), + ends_at: Date51Schema.optional(), + license_number: z.string().optional(), + name: z.string().optional(), + starts_at: Date52Schema.optional(), + url: z.string().optional() + }) + export type StickyCertification = z.infer + + export const StickyEducationSchema = z.object({ + activities_and_societies: z.string().optional(), + degree_name: z.string().optional(), + description: z.string().optional(), + ends_at: Date53Schema.optional(), + field_of_study: z.string().optional(), + grade: z.string().optional(), + logo_url: z.string().optional(), + school: z.string().optional(), + school_facebook_profile_url: z.string().optional(), + school_linkedin_profile_url: z.string().optional(), + starts_at: Date54Schema.optional() + }) + export type StickyEducation = z.infer + + export const StickyExperienceSchema = z.object({ + company: z.string().optional(), + company_facebook_profile_url: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date55Schema.optional(), + location: z.string().optional(), + logo_url: z.string().optional(), + starts_at: Date56Schema.optional(), + title: z.string().optional() + }) + export type StickyExperience = z.infer + + export const StickyVolunteeringExperienceSchema = z.object({ + cause: z.string().optional(), + company: z.string().optional(), + company_linkedin_profile_url: z.string().optional(), + description: z.string().optional(), + ends_at: Date57Schema.optional(), + logo_url: z.string().optional(), + starts_at: Date58Schema.optional(), + title: z.string().optional() + }) + export type StickyVolunteeringExperience = z.infer< + typeof StickyVolunteeringExperienceSchema + > + + export const PurpleAcquiredCompanySchema = z.object({ + announced_date: Date59Schema.optional(), + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + price: z.number().optional() + }) + export type PurpleAcquiredCompany = z.infer< + typeof PurpleAcquiredCompanySchema + > + + export const PurpleAcquisitorSchema = z.object({ + announced_date: Date60Schema.optional(), + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + price: z.number().optional() + }) + export type PurpleAcquisitor = z.infer + + export const PurpleCompanyDetailsSchema = z.object({ + company_type: z.string().optional(), + contact_email: z.string().optional(), + crunchbase_profile_url: z.string().optional(), + crunchbase_rank: z.number().optional(), + facebook_id: z.string().optional(), + founding_date: Date61Schema.optional(), + ipo_date: Date62Schema.optional(), + ipo_status: z.string().optional(), + number_of_acquisitions: z.number().optional(), + number_of_exits: z.number().optional(), + number_of_funding_rounds: z.number().optional(), + number_of_investments: z.number().optional(), + number_of_investors: z.number().optional(), + number_of_lead_investments: z.number().optional(), + number_of_lead_investors: z.number().optional(), + operating_status: z.string().optional(), + phone_number: z.string().optional(), + stock_symbol: z.string().optional(), + total_fund_raised: z.number().optional(), + total_funding_amount: z.number().optional(), + twitter_id: z.string().optional() + }) + export type PurpleCompanyDetails = z.infer + + export const PurpleFundingSchema = z.object({ + announced_date: Date63Schema.optional(), + funding_type: z.string().optional(), + investor_list: z.array(PurpleInvestorSchema).optional(), + money_raised: z.number().optional(), + number_of_investor: z.number().optional() + }) + export type PurpleFunding = z.infer + + export const PurpleCompanyUpdateSchema = z.object({ + article_link: z.string().optional(), + image: z.string().optional(), + posted_on: Date64Schema.optional(), + text: z.string().optional(), + total_likes: z.number().optional() + }) + export type PurpleCompanyUpdate = z.infer + + export const FluffyAcquiredCompanySchema = z.object({ + announced_date: Date65Schema.optional(), + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + price: z.number().optional() + }) + export type FluffyAcquiredCompany = z.infer< + typeof FluffyAcquiredCompanySchema + > + + export const FluffyAcquisitorSchema = z.object({ + announced_date: Date66Schema.optional(), + crunchbase_profile_url: z.string().optional(), + linkedin_profile_url: z.string().optional(), + price: z.number().optional() + }) + export type FluffyAcquisitor = z.infer + + export const FluffyCompanyDetailsSchema = z.object({ + company_type: z.string().optional(), + contact_email: z.string().optional(), + crunchbase_profile_url: z.string().optional(), + crunchbase_rank: z.number().optional(), + facebook_id: z.string().optional(), + founding_date: Date67Schema.optional(), + ipo_date: Date68Schema.optional(), + ipo_status: z.string().optional(), + number_of_acquisitions: z.number().optional(), + number_of_exits: z.number().optional(), + number_of_funding_rounds: z.number().optional(), + number_of_investments: z.number().optional(), + number_of_investors: z.number().optional(), + number_of_lead_investments: z.number().optional(), + number_of_lead_investors: z.number().optional(), + operating_status: z.string().optional(), + phone_number: z.string().optional(), + stock_symbol: z.string().optional(), + total_fund_raised: z.number().optional(), + total_funding_amount: z.number().optional(), + twitter_id: z.string().optional() + }) + export type FluffyCompanyDetails = z.infer + + export const FluffyFundingSchema = z.object({ + announced_date: Date69Schema.optional(), + funding_type: z.string().optional(), + investor_list: z.array(FluffyInvestorSchema).optional(), + money_raised: z.number().optional(), + number_of_investor: z.number().optional() + }) + export type FluffyFunding = z.infer + + export const FluffyCompanyUpdateSchema = z.object({ + article_link: z.string().optional(), + image: z.string().optional(), + posted_on: Date70Schema.optional(), + text: z.string().optional(), + total_likes: z.number().optional() + }) + export type FluffyCompanyUpdate = z.infer + + export const PersonLookupUrlEnrichResultProfileSchema = z.object({ + accomplishment_courses: z.array(PurpleCourseSchema).optional(), + accomplishment_honors_awards: z.array(PurpleHonourAwardSchema).optional(), + accomplishment_organisations: z + .array(PurpleAccomplishmentOrgSchema) + .optional(), + accomplishment_patents: z.array(PurplePatentSchema).optional(), + accomplishment_projects: z.array(PurpleProjectSchema).optional(), + accomplishment_publications: z.array(PurplePublicationSchema).optional(), + accomplishment_test_scores: z.array(PurpleTestScoreSchema).optional(), + activities: z.array(PurpleActivitySchema).optional(), + articles: z.array(PurpleArticleSchema).optional(), + background_cover_image_url: z.string().optional(), + birth_date: MagentaDateSchema.optional(), + certifications: z.array(PurpleCertificationSchema).optional(), + city: z.string().optional(), + connections: z.number().optional(), + country: z.string().optional(), + country_full_name: z.string().optional(), + education: z.array(PurpleEducationSchema).optional(), + experiences: z.array(PurpleExperienceSchema).optional(), + extra: PurplePersonExtraSchema.optional(), + first_name: z.string().optional(), + follower_count: z.number().optional(), + full_name: z.string().optional(), + gender: z.string().optional(), + groups: z.array(PurplePersonGroupSchema).optional(), + headline: z.string().optional(), + industry: z.string().optional(), + inferred_salary: PurpleInferredSalarySchema.optional(), + interests: z.array(z.string()).optional(), + languages: z.array(z.string()).optional(), + last_name: z.string().optional(), + occupation: z.string().optional(), + people_also_viewed: z.array(PurplePeopleAlsoViewedSchema).optional(), + personal_emails: z.array(z.string()).optional(), + personal_numbers: z.array(z.string()).optional(), + profile_pic_url: z.string().optional(), + public_identifier: z.string().optional(), + recommendations: z.array(z.string()).optional(), + similarly_named_profiles: z.array(PurpleSimilarProfileSchema).optional(), + skills: z.array(z.string()).optional(), + state: z.string().optional(), + summary: z.string().optional(), + volunteer_work: z.array(PurpleVolunteeringExperienceSchema).optional() + }) + export type PersonLookupUrlEnrichResultProfile = z.infer< + typeof PersonLookupUrlEnrichResultProfileSchema + > + + export const RoleSearchEnrichedResultProfileSchema = z.object({ + accomplishment_courses: z.array(FluffyCourseSchema).optional(), + accomplishment_honors_awards: z.array(FluffyHonourAwardSchema).optional(), + accomplishment_organisations: z + .array(FluffyAccomplishmentOrgSchema) + .optional(), + accomplishment_patents: z.array(FluffyPatentSchema).optional(), + accomplishment_projects: z.array(FluffyProjectSchema).optional(), + accomplishment_publications: z.array(FluffyPublicationSchema).optional(), + accomplishment_test_scores: z.array(FluffyTestScoreSchema).optional(), + activities: z.array(FluffyActivitySchema).optional(), + articles: z.array(FluffyArticleSchema).optional(), + background_cover_image_url: z.string().optional(), + birth_date: Date15Schema.optional(), + certifications: z.array(FluffyCertificationSchema).optional(), + city: z.string().optional(), + connections: z.number().optional(), + country: z.string().optional(), + country_full_name: z.string().optional(), + education: z.array(FluffyEducationSchema).optional(), + experiences: z.array(FluffyExperienceSchema).optional(), + extra: FluffyPersonExtraSchema.optional(), + first_name: z.string().optional(), + follower_count: z.number().optional(), + full_name: z.string().optional(), + gender: z.string().optional(), + groups: z.array(FluffyPersonGroupSchema).optional(), + headline: z.string().optional(), + industry: z.string().optional(), + inferred_salary: FluffyInferredSalarySchema.optional(), + interests: z.array(z.string()).optional(), + languages: z.array(z.string()).optional(), + last_name: z.string().optional(), + occupation: z.string().optional(), + people_also_viewed: z.array(FluffyPeopleAlsoViewedSchema).optional(), + personal_emails: z.array(z.string()).optional(), + personal_numbers: z.array(z.string()).optional(), + profile_pic_url: z.string().optional(), + public_identifier: z.string().optional(), + recommendations: z.array(z.string()).optional(), + similarly_named_profiles: z.array(FluffySimilarProfileSchema).optional(), + skills: z.array(z.string()).optional(), + state: z.string().optional(), + summary: z.string().optional(), + volunteer_work: z.array(FluffyVolunteeringExperienceSchema).optional() + }) + export type RoleSearchEnrichedResultProfile = z.infer< + typeof RoleSearchEnrichedResultProfileSchema + > + + export const ReverseEmailUrlEnrichResultProfileSchema = z.object({ + accomplishment_courses: z.array(TentacledCourseSchema).optional(), + accomplishment_honors_awards: z + .array(TentacledHonourAwardSchema) + .optional(), + accomplishment_organisations: z + .array(TentacledAccomplishmentOrgSchema) + .optional(), + accomplishment_patents: z.array(TentacledPatentSchema).optional(), + accomplishment_projects: z.array(TentacledProjectSchema).optional(), + accomplishment_publications: z.array(TentacledPublicationSchema).optional(), + accomplishment_test_scores: z.array(TentacledTestScoreSchema).optional(), + activities: z.array(TentacledActivitySchema).optional(), + articles: z.array(TentacledArticleSchema).optional(), + background_cover_image_url: z.string().optional(), + birth_date: Date33Schema.optional(), + certifications: z.array(TentacledCertificationSchema).optional(), + city: z.string().optional(), + connections: z.number().optional(), + country: z.string().optional(), + country_full_name: z.string().optional(), + education: z.array(TentacledEducationSchema).optional(), + experiences: z.array(TentacledExperienceSchema).optional(), + extra: TentacledPersonExtraSchema.optional(), + first_name: z.string().optional(), + follower_count: z.number().optional(), + full_name: z.string().optional(), + gender: z.string().optional(), + groups: z.array(TentacledPersonGroupSchema).optional(), + headline: z.string().optional(), + industry: z.string().optional(), + inferred_salary: TentacledInferredSalarySchema.optional(), + interests: z.array(z.string()).optional(), + languages: z.array(z.string()).optional(), + last_name: z.string().optional(), + occupation: z.string().optional(), + people_also_viewed: z.array(TentacledPeopleAlsoViewedSchema).optional(), + personal_emails: z.array(z.string()).optional(), + personal_numbers: z.array(z.string()).optional(), + profile_pic_url: z.string().optional(), + public_identifier: z.string().optional(), + recommendations: z.array(z.string()).optional(), + similarly_named_profiles: z.array(TentacledSimilarProfileSchema).optional(), + skills: z.array(z.string()).optional(), + state: z.string().optional(), + summary: z.string().optional(), + volunteer_work: z.array(TentacledVolunteeringExperienceSchema).optional() + }) + export type ReverseEmailUrlEnrichResultProfile = z.infer< + typeof ReverseEmailUrlEnrichResultProfileSchema + > + + export const PublicPersonSchema = z.object({ + accomplishment_courses: z.array(StickyCourseSchema).optional(), + accomplishment_honors_awards: z.array(StickyHonourAwardSchema).optional(), + accomplishment_organisations: z + .array(StickyAccomplishmentOrgSchema) + .optional(), + accomplishment_patents: z.array(StickyPatentSchema).optional(), + accomplishment_projects: z.array(StickyProjectSchema).optional(), + accomplishment_publications: z.array(StickyPublicationSchema).optional(), + accomplishment_test_scores: z.array(StickyTestScoreSchema).optional(), + activities: z.array(StickyActivitySchema).optional(), + articles: z.array(StickyArticleSchema).optional(), + background_cover_image_url: z.string().optional(), + certifications: z.array(StickyCertificationSchema).optional(), + city: z.string().optional(), + connections: z.number().optional(), + country: z.string().optional(), + country_full_name: z.string().optional(), + education: z.array(StickyEducationSchema).optional(), + experiences: z.array(StickyExperienceSchema).optional(), + first_name: z.string().optional(), + follower_count: z.number().optional(), + full_name: z.string().optional(), + groups: z.array(StickyPersonGroupSchema).optional(), + headline: z.string().optional(), + languages: z.array(z.string()).optional(), + last_name: z.string().optional(), + occupation: z.string().optional(), + people_also_viewed: z.array(StickyPeopleAlsoViewedSchema).optional(), + profile_pic_url: z.string().optional(), + public_identifier: z.string().optional(), + recommendations: z.array(z.string()).optional(), + similarly_named_profiles: z.array(StickySimilarProfileSchema).optional(), + skills: z.array(z.string()).optional(), + state: z.string().optional(), + summary: z.string().optional(), + volunteer_work: z.array(StickyVolunteeringExperienceSchema).optional() + }) + export type PublicPerson = z.infer + + export const PurpleAcquisitionSchema = z.object({ + acquired: z.array(PurpleAcquiredCompanySchema).optional(), + acquired_by: PurpleAcquisitorSchema.optional() + }) + export type PurpleAcquisition = z.infer + + export const FluffyAcquisitionSchema = z.object({ + acquired: z.array(FluffyAcquiredCompanySchema).optional(), + acquired_by: FluffyAcquisitorSchema.optional() + }) + export type FluffyAcquisition = z.infer + + export const PersonLookupUrlEnrichResultSchema = z.object({ + company_similarity_score: z.number().optional(), + last_updated: z.string().optional(), + location_similarity_score: z.number().optional(), + name_similarity_score: z.number().optional(), + profile: PersonLookupUrlEnrichResultProfileSchema.optional(), + title_similarity_score: z.number().optional(), + url: z.string().optional() + }) + export type PersonLookupUrlEnrichResult = z.infer< + typeof PersonLookupUrlEnrichResultSchema + > + + export const RoleSearchEnrichedResultSchema = z.object({ + last_updated: z.string().optional(), + linkedin_profile_url: z.string().optional(), + profile: RoleSearchEnrichedResultProfileSchema.optional() + }) + export type RoleSearchEnrichedResult = z.infer< + typeof RoleSearchEnrichedResultSchema + > + + export const ReverseEmailUrlEnrichResultSchema = z.object({ + backwards_compatibility_notes: z.string().optional(), + facebook_profile_url: z.string().optional(), + last_updated: z.string().optional(), + linkedin_profile_url: z.string().optional(), + profile: ReverseEmailUrlEnrichResultProfileSchema.optional(), + similarity_score: z.number().optional(), + twitter_profile_url: z.string().optional(), + url: z.string().optional() + }) + export type ReverseEmailUrlEnrichResult = z.infer< + typeof ReverseEmailUrlEnrichResultSchema + > + + export const SearchResultSchema = z.object({ + last_updated: z.string().optional(), + linkedin_profile_url: z.string().optional(), + profile: PublicPersonSchema.optional() + }) + export type SearchResult = z.infer + + export const ResultProfileSchema = z.object({ + acquisitions: PurpleAcquisitionSchema.optional(), + affiliated_companies: z.array(PurpleAffiliatedCompanySchema).optional(), + background_cover_image_url: z.string().optional(), + categories: z.array(z.string()).optional(), + company_size: z.array(z.number()).optional(), + company_size_on_linkedin: z.number().optional(), + company_type: CompanyTypeSchema.optional(), + customer_list: z.array(z.string()).optional(), + description: z.string().optional(), + exit_data: z.array(PurpleExitSchema).optional(), + extra: PurpleCompanyDetailsSchema.optional(), + follower_count: z.number().optional(), + founded_year: z.number().optional(), + funding_data: z.array(PurpleFundingSchema).optional(), + hq: PurpleCompanyLocationSchema.optional(), + industry: z.string().optional(), + linkedin_internal_id: z.string().optional(), + locations: z.array(FluffyCompanyLocationSchema).optional(), + name: z.string().optional(), + profile_pic_url: z.string().optional(), + search_id: z.string().optional(), + similar_companies: z.array(PurpleSimilarCompanySchema).optional(), + specialities: z.array(z.string()).optional(), + tagline: z.string().optional(), + universal_name_id: z.string().optional(), + updates: z.array(PurpleCompanyUpdateSchema).optional(), + website: z.string().optional() + }) + export type ResultProfile = z.infer + + export const CompanyUrlEnrichResultProfileSchema = z.object({ + acquisitions: FluffyAcquisitionSchema.optional(), + affiliated_companies: z.array(FluffyAffiliatedCompanySchema).optional(), + background_cover_image_url: z.string().optional(), + categories: z.array(z.string()).optional(), + company_size: z.array(z.number()).optional(), + company_size_on_linkedin: z.number().optional(), + company_type: CompanyTypeSchema.optional(), + customer_list: z.array(z.string()).optional(), + description: z.string().optional(), + exit_data: z.array(FluffyExitSchema).optional(), + extra: FluffyCompanyDetailsSchema.optional(), + follower_count: z.number().optional(), + founded_year: z.number().optional(), + funding_data: z.array(FluffyFundingSchema).optional(), + hq: TentacledCompanyLocationSchema.optional(), + industry: z.string().optional(), + linkedin_internal_id: z.string().optional(), + locations: z.array(StickyCompanyLocationSchema).optional(), + name: z.string().optional(), + profile_pic_url: z.string().optional(), + search_id: z.string().optional(), + similar_companies: z.array(FluffySimilarCompanySchema).optional(), + specialities: z.array(z.string()).optional(), + tagline: z.string().optional(), + universal_name_id: z.string().optional(), + updates: z.array(FluffyCompanyUpdateSchema).optional(), + website: z.string().optional() + }) + export type CompanyUrlEnrichResultProfile = z.infer< + typeof CompanyUrlEnrichResultProfileSchema + > + + export const PersonSearchResultSchema = z.object({ + next_page: z.string().optional(), + results: z.array(SearchResultSchema).optional(), + total_result_count: z.number().optional() + }) + export type PersonSearchResult = z.infer + + export const CSearchResultSchema = z.object({ + last_updated: z.string().optional(), + linkedin_profile_url: z.string().optional(), + profile: ResultProfileSchema.optional() + }) + export type CSearchResult = z.infer + + export const CompanyUrlEnrichResultSchema = z.object({ + last_updated: z.string().optional(), + profile: CompanyUrlEnrichResultProfileSchema.optional(), + url: z.string().optional() + }) + export type CompanyUrlEnrichResult = z.infer< + typeof CompanyUrlEnrichResultSchema + > + + export const CompanySearchResultSchema = z.object({ + next_page: z.string().optional(), + results: z.array(CSearchResultSchema).optional(), + total_result_count: z.number().optional() + }) + export type CompanySearchResult = z.infer +} + +/** + * Pull rich data about people and companies. + * + * Essentially a wrapper around LinkedIn & Crunchbase. + * + * @see https://nubela.co/proxycurl/ + */ +export class ProxycurlClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('PROXYCURL_API_KEY'), + apiBaseUrl = getEnv('PROXYCURL_API_BASE_URL') ?? + 'https://nubela.co/proxycurl', + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'ProxycurlClient missing required "apiKey" (defaults to "PROXYCURL_API_KEY")' + ) + assert( + apiBaseUrl, + 'ProxycurlClient missing required "apiBaseUrl" (defaults to "PROXYCURL_API_BASE_URL")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + const throttledKy = throttle ? throttleKy(ky, proxycurl.throttle) : ky + + this.ky = throttledKy.extend({ + prefixUrl: apiBaseUrl, + headers: { + Authorization: `Bearer ${apiKey}` + } + }) + } + + @aiFunction({ + name: 'get_linkedin_company', + description: + "Gets the LinkedIn profile for a company given it's domain `url`.", + inputSchema: proxycurl.CompanyProfileEndpointParamsQueryClassSchema + }) + async getLinkedInCompany( + opts: proxycurl.CompanyProfileEndpointParamsQueryClass + ) { + return this.ky + .get('api/linkedin/company', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'get_linkedin_person', + description: + 'Gets the LinkedIn profile for a person given some unique, identifying information about them.', + inputSchema: proxycurl.PersonProfileEndpointParamsQueryClassSchema + }) + async getLinkedInPerson( + opts: proxycurl.PersonProfileEndpointParamsQueryClass + ) { + return this.ky + .get('api/v2/linkedin', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'resolve_linkedin_person', + description: + 'Resolves the LinkedIn profile for a person given their `first_name` and `company_domain` URL.', + inputSchema: proxycurl.PersonLookupEndpointParamsQueryClassSchema + }) + async resolveLinkedInPerson( + opts: proxycurl.PersonLookupEndpointParamsQueryClass + ) { + return this.ky + .get('api/linkedin/profile/resolve', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'resolve_linkedin_person_by_email', + description: + 'Resolves the LinkedIn profile for a person given their `email`.', + inputSchema: proxycurl.ReverseEmailLookupEndpointParamsQueryClassSchema + }) + async resolveLinkedInPersonByEmail( + opts: proxycurl.ReverseEmailLookupEndpointParamsQueryClass + ) { + return this.ky + .get('api/linkedin/profile/resolve/email', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'resolve_linkedin_person_at_company_by_role', + description: + 'Resolves the LinkedIn profile for a person at a given `company_name` and `role`.', + inputSchema: proxycurl.RoleLookupEndpointParamsQueryClassSchema + }) + async resolveLinkedInPersonAtCompanyByRole( + opts: proxycurl.RoleLookupEndpointParamsQueryClass + ) { + return this.ky + .get('api/find/company/role/', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'resolve_linkedin_company', + description: + 'Resolves the LinkedIn profile for a company given the `company_name` and/or `company_domain`.', + inputSchema: proxycurl.CompanyLookupEndpointParamsQueryClassSchema + }) + async resolveLinkedInCompany( + opts: proxycurl.CompanyLookupEndpointParamsQueryClass + ) { + return this.ky + .get('api/linkedin/company/resolve', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'search_linkedin_companies', + description: + 'Searches LinkedIn company profiles based on a set of criteria such as `name`, `industry`, `region`, `description`, `city`, number of employees, founding date, funding raised, etc.', + inputSchema: proxycurl.CompanySearchEndpointParamsQueryClassSchema + }) + async searchCompanies(opts: proxycurl.CompanySearchEndpointParamsQueryClass) { + return this.ky + .get('api/v2/search/company', { + searchParams: { ...opts } + }) + .json() + } + + @aiFunction({ + name: 'search_linkedin_people', + description: + 'Searches LinkedIn people profiles based on a set of criteria such as `country`, `first_name`, `last_name`, `current_company_name`, `headline`, `industries`, `past_company_name`, `summary`, `city`, `education_school_name`, etc.', + inputSchema: proxycurl.PersonSearchEndpointParamsQueryClassSchema + }) + async searchPeople(opts: proxycurl.PersonSearchEndpointParamsQueryClass) { + return this.ky + .get('api/v2/search/person/', { + searchParams: { ...opts } + }) + .json() + } +} diff --git a/src/services/scraper-client.ts b/src/services/scraper-client.ts new file mode 100644 index 000000000..b0719f29b --- /dev/null +++ b/src/services/scraper-client.ts @@ -0,0 +1,116 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, omit } from '../utils.js' + +export namespace scraper { + export type ScrapeResult = { + author: string + byline: string + description: string + imageUrl: string + lang: string + length: number + logoUrl: string + publishedTime: string + siteName: string + title: string + + /** The HTML for the main content of the page. */ + content: string + + /** The raw HTML response from the server. */ + rawHtml: string + + /** The text for the main content of the page in markdown format. */ + markdownContent: string + + /** The text for the main content of the page. */ + textContent: string + } +} + +/** + * This is a single endpoint API for scraping websites. It returns the HTML, + * markdown, and plaintext for main body content of the page, as well as + * metadata like title and description. + * + * It tries the simplest and fastest methods first, and falls back to slower + * proxies and JavaScript rendering if needed. + * + * @note This service is currently available only via a closed beta. + */ +export class ScraperClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiBaseUrl: string + + constructor({ + apiBaseUrl = getEnv('SCRAPER_API_BASE_URL'), + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiBaseUrl, + 'ScraperClient missing required "apiBaseUrl" (defaults to "SCRAPER_API_BASE_URL")' + ) + super() + + this.apiBaseUrl = apiBaseUrl + this.ky = ky.extend({ prefixUrl: this.apiBaseUrl }) + } + + @aiFunction({ + name: 'scrape_url', + description: 'Scrapes the content of a single URL.', + inputSchema: z.object({ + url: z.string().url().describe('The URL of the web page to scrape'), + format: z + .enum(['html', 'markdown', 'plaintext']) + .default('markdown') + .optional() + .describe( + 'Whether to return the content as HTML, markdown, or plaintext.' + ) + }) + }) + async scrapeUrl( + urlOrOpts: + | string + | { + url: string + format?: 'html' | 'markdown' | 'plaintext' + timeoutMs?: number + } + ): Promise> { + const { + timeoutMs = 60_000, + format = 'markdown', + ...opts + } = typeof urlOrOpts === 'string' ? { url: urlOrOpts } : urlOrOpts + + const res = await this.ky + .post('scrape', { + json: opts, + timeout: timeoutMs + }) + .json() + + switch (format) { + case 'html': + return omit(res, 'markdownContent', 'textContent', 'rawHtml') + + case 'markdown': + return omit(res, 'textContent', 'rawHtml', 'content') + + case 'plaintext': + return omit(res, 'markdownContent', 'rawHtml', 'content') + + default: + return res + } + } +} diff --git a/src/services/searxng-client.ts b/src/services/searxng-client.ts new file mode 100644 index 000000000..69717816d --- /dev/null +++ b/src/services/searxng-client.ts @@ -0,0 +1,354 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, omit, pick, pruneUndefined } from '../utils.js' + +export namespace searxng { + export const SearchCategorySchema = z.enum([ + 'general', + 'images', + 'videos', + 'news', + 'map', + 'music', + 'it', + 'science', + 'files', + 'social media' + ]) + export type SearchCategory = z.infer + + export const SearchEngineSchema = z.enum([ + '9gag', + 'annas archive', + 'apk mirror', + 'apple app store', + 'ahmia', + 'anaconda', + 'arch linux wiki', + 'artic', + 'arxiv', + 'ask', + 'bandcamp', + 'wikipedia', + 'bilibili', + 'bing', + 'bing images', + 'bing news', + 'bing videos', + 'bitbucket', + 'bpb', + 'btdigg', + 'ccc-tv', + 'openverse', + 'chefkoch', + 'crossref', + 'crowdview', + 'yep', + 'yep images', + 'yep news', + 'curlie', + 'currency', + 'bahnhof', + 'deezer', + 'destatis', + 'deviantart', + 'ddg definitions', + 'docker hub', + 'erowid', + 'wikidata', + 'duckduckgo', + 'duckduckgo images', + 'duckduckgo videos', + 'duckduckgo news', + 'duckduckgo weather', + 'apple maps', + 'emojipedia', + 'tineye', + 'etymonline', + '1x', + 'fdroid', + 'flickr', + 'free software directory', + 'frinkiac', + 'fyyd', + 'genius', + 'gentoo', + 'gitlab', + 'github', + 'codeberg', + 'goodreads', + 'google', + 'google images', + 'google news', + 'google videos', + 'google scholar', + 'google play apps', + 'google play movies', + 'material icons', + 'gpodder', + 'habrahabr', + 'hackernews', + 'hoogle', + 'imdb', + 'imgur', + 'ina', + 'invidious', + 'jisho', + 'kickass', + 'lemmy communities', + 'lemmy users', + 'lemmy posts', + 'lemmy comments', + 'library genesis', + 'z-library', + 'library of congress', + 'lingva', + 'lobste.rs', + 'mastodon users', + 'mastodon hashtags', + 'mdn', + 'metacpan', + 'mixcloud', + 'mozhi', + 'mwmbl', + 'npm', + 'nyaa', + 'mankier', + 'odysee', + 'openairedatasets', + 'openairepublications', + 'openstreetmap', + 'openrepos', + 'packagist', + 'pdbe', + 'photon', + 'pinterest', + 'piped', + 'piped.music', + 'piratebay', + 'podcastindex', + 'presearch', + 'presearch images', + 'presearch videos', + 'presearch news', + 'pub.dev', + 'pubmed', + 'pypi', + 'qwant', + 'qwant news', + 'qwant images', + 'qwant videos', + 'radio browser', + 'reddit', + 'rottentomatoes', + 'sepiasearch', + 'soundcloud', + 'stackoverflow', + 'askubuntu', + 'internetarchivescholar', + 'superuser', + 'searchcode code', + 'semantic scholar', + 'startpage', + 'tokyotoshokan', + 'solidtorrents', + 'tagesschau', + 'tmdb', + 'torch', + 'unsplash', + 'yandex music', + 'yahoo', + 'yahoo news', + 'youtube', + 'dailymotion', + 'vimeo', + 'wiby', + 'alexandria', + 'wikibooks', + 'wikinews', + 'wikiquote', + 'wikisource', + 'wikispecies', + 'wiktionary', + 'wikiversity', + 'wikivoyage', + 'wikicommons.images', + 'wolframalpha', + 'dictzone', + 'mymemory translated', + '1337x', + 'duden', + 'seznam', + 'mojeek', + 'moviepilot', + 'naver', + 'rubygems', + 'peertube', + 'mediathekviewweb', + 'yacy', + 'yacy images', + 'rumble', + 'livespace', + 'wordnik', + 'woxikon.de synonyme', + 'seekr news', + 'seekr images', + 'seekr videos', + 'sjp.pwn', + 'stract', + 'svgrepo', + 'tootfinder', + 'wallhaven', + 'wikimini', + 'wttr.in', + 'yummly', + 'brave', + 'brave.images', + 'brave.videos', + 'brave.news', + 'lib.rs', + 'sourcehut', + 'goo', + 'bt4g', + 'pkg.go.dev' + ]) + export type SearchEngine = z.infer + + export const SearchOptionsSchema = z.object({ + query: z.string().describe('search query'), + categories: z + .array(SearchCategorySchema) + .optional() + .describe( + 'narrows the search to only use search engines in specific categories' + ), + engines: z + .array(SearchEngineSchema) + .optional() + .describe('narrows the search to only use specific search engines'), + language: z.string().optional(), + pageno: z.number().int().optional() + }) + export type SearchOptions = z.infer + + export interface SearchResult { + title: string + url: string + img_src?: string + thumbnail_src?: string + thumbnail?: string + content?: string + author?: string + iframe_src?: string + category?: SearchCategory + engine?: SearchEngine + publishedDate?: string + } + + export interface SearchResponse { + results: SearchResult[] + suggestions: string[] + query: string + } +} + +/** + * Open source meta search engine capable of searching across many different + * sources and search engines. + * + * The most important search engines are: + * + * - "reddit" (Reddit posts) + * - "google" (Google web search) + * - "google news" (Google News search) + * - "brave" (Brave web search) + * - "arxiv" (academic papers) + * - "genius" (Genius.com for song lyrics) + * - "imdb" (movies and TV shows) + * - "hackernews" (Hacker News) + * - "wikidata" (Wikidata) + * - "wolframalpha" (Wolfram Alpha) + * - "youtube" (YouTube videos) + * - "github" (GitHub code and repositories) + * + * @see https://docs.searxng.org + * + * NOTE: You'll need to run a local instance of Searxng to use this client. + * + * See [perplexica](https://github.com/ItzCrazyKns/Perplexica/blob/master/docker-compose.yaml) for an example of how to set this up. + */ +export class SearxngClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiBaseUrl: string + + constructor({ + apiBaseUrl = getEnv('SEARXNG_API_BASE_URL'), + ky = defaultKy + }: { + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiBaseUrl, + 'SearxngClient missing required "apiBaseUrl" (defaults to "SEARXNG_API_BASE_URL")' + ) + super() + + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ prefixUrl: apiBaseUrl }) + } + + @aiFunction({ + name: 'searxng', + description: `Searches across multiple search engines using a local instance of Searxng. To search only specific engines, use the \`engines\` parameter. + +The most important search engines are: + +- "reddit" (Reddit posts) +- "google" (Google web search) +- "google news" (Google News search) +- "brave" (Brave web search) +- "arxiv" (academic papers) +- "genius" (Genius.com for song lyrics) +- "imdb" (movies and TV shows) +- "hackernews" (Hacker News) +- "wikidata" (Wikidata) +- "wolframalpha" (Wolfram Alpha) +- "youtube" (YouTube videos) +- "github" (GitHub code and repositories) +`, + inputSchema: searxng.SearchOptionsSchema + }) + async search({ + query, + ...opts + }: searxng.SearchOptions): Promise { + const res = await this.ky + .get('search', { + searchParams: pruneUndefined({ + ...opts, + q: query, + categories: opts.categories?.join(','), + engines: opts.engines?.join(','), + format: 'json' + }) + }) + .json() + + res.results = res.results?.map( + (result: any) => + omit( + result, + 'parsed_url', + 'engines', + 'positions', + 'template' + ) as searxng.SearchResult + ) + + return pick(res, 'results', 'suggestions', 'query') + } +} diff --git a/src/services/serpapi-client.ts b/src/services/serpapi-client.ts new file mode 100644 index 000000000..19af9dae8 --- /dev/null +++ b/src/services/serpapi-client.ts @@ -0,0 +1,703 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv } from '../utils.js' + +/** + * All types have been exported from the `serpapi` package, which we're + * not using directly because it is bloated and has compatibility issues. + */ + +export namespace serpapi { + export const API_BASE_URL = 'https://serpapi.com' + + export type BaseResponse

> = { + search_metadata: { + id: string + status: string | 'Queued' | 'Processing' | 'Success' + json_endpoint: string + created_at: string + processed_at: string + raw_html_file: string + total_time_taken: number + } + search_parameters: { + engine: string + } & Omit + serpapi_pagination?: { + next: string + } + pagination?: { + next: string + } + [key: string]: any + } + + export type BaseParameters = { + /** + * Parameter defines the device to use to get the results. It can be set to + * `desktop` (default) to use a regular browser, `tablet` to use a tablet browser + * (currently using iPads), or `mobile` to use a mobile browser (currently + * using iPhones). + */ + device?: 'desktop' | 'tablet' | 'mobile' + + /** + * Parameter will force SerpApi to fetch the Google results even if a cached + * version is already present. A cache is served only if the query and all + * parameters are exactly the same. Cache expires after 1h. Cached searches + * are free, and are not counted towards your searches per month. It can be set + * to `false` (default) to allow results from the cache, or `true` to disallow + * results from the cache. `no_cache` and `async` parameters should not be used together. + */ + no_cache?: boolean + + /** + * Parameter defines the way you want to submit your search to SerpApi. It can + * be set to `false` (default) to open an HTTP connection and keep it open until + * you got your search results, or `true` to just submit your search to SerpApi + * and retrieve them later. In this case, you'll need to use our + * [Searches Archive API](https://serpapi.com/search-archive-api) to retrieve + * your results. `async` and `no_cache` parameters should not be used together. + * `async` should not be used on accounts with + * [Ludicrous Speed](https://serpapi.com/plan) enabled. + */ + async?: boolean + + /** + * Parameter defines the SerpApi private key to use. + */ + api_key?: string | null + + /** + * Specify the client-side timeout of the request. In milliseconds. + */ + timeout?: number + } + + export type GoogleParameters = BaseParameters & { + /** + * Search Query + * Parameter defines the query you want to search. You can use anything that you + * would use in a regular Google search. e.g. `inurl:`, `site:`, `intitle:`. We + * also support advanced search query parameters such as as_dt and as_eq. See the + * [full list](https://serpapi.com/advanced-google-query-parameters) of supported + * advanced search query parameters. + */ + q: string + + /** + * Location + * Parameter defines from where you want the search to originate. If several + * locations match the location requested, we'll pick the most popular one. Head to + * the [/locations.json API](https://serpapi.com/locations-api) if you need more + * precise control. location and uule parameters can't be used together. Avoid + * utilizing location when setting the location outside the U.S. when using Google + * Shopping and/or Google Product API. + */ + location?: string + + /** + * Encoded Location + * Parameter is the Google encoded location you want to use for the search. uule + * and location parameters can't be used together. + */ + uule?: string + + /** + * Google Place ID + * Parameter defines the id (`CID`) of the Google My Business listing you want to + * scrape. Also known as Google Place ID. + */ + ludocid?: string + + /** + * Additional Google Place ID + * Parameter that you might have to use to force the knowledge graph map view to + * show up. You can find the lsig ID by using our [Local Pack + * API](https://serpapi.com/local-pack) or [Places Results + * API](https://serpapi.com/places-results). + * lsig ID is also available via a redirect Google uses within [Google My + * Business](https://www.google.com/business/). + */ + lsig?: string + + /** + * Google Knowledge Graph ID + * Parameter defines the id (`KGMID`) of the Google Knowledge Graph listing you + * want to scrape. Also known as Google Knowledge Graph ID. Searches with kgmid + * parameter will return results for the originally encrypted search parameters. + * For some searches, kgmid may override all other parameters except start, and num + * parameters. + */ + kgmid?: string + + /** + * Google Cached Search Parameters ID + * Parameter defines the cached search parameters of the Google Search you want to + * scrape. Searches with si parameter will return results for the originally + * encrypted search parameters. For some searches, si may override all other + * parameters except start, and num parameters. si can be used to scrape Google + * Knowledge Graph Tabs. + */ + si?: string + + /** + * Domain + * Parameter defines the Google domain to use. It defaults to `google.com`. Head to + * the [Google domains page](https://serpapi.com/google-domains) for a full list of + * supported Google domains. + */ + google_domain?: string + + /** + * Country + * Parameter defines the country to use for the Google search. It's a two-letter + * country code. (e.g., `us` for the United States, `uk` for United Kingdom, or + * `fr` for France). Head to the [Google countries + * page](https://serpapi.com/google-countries) for a full list of supported Google + * countries. + */ + gl?: string + + /** + * Language + * Parameter defines the language to use for the Google search. It's a two-letter + * language code. (e.g., `en` for English, `es` for Spanish, or `fr` for French). + * Head to the [Google languages page](https://serpapi.com/google-languages) for a + * full list of supported Google languages. + */ + hl?: string + + /** + * Set Multiple Languages + * Parameter defines one or multiple languages to limit the search to. It uses + * `lang_{two-letter language code}` to specify languages and `|` as a delimiter. + * (e.g., `lang_fr|lang_de` will only search French and German pages). Head to the + * [Google lr languages page](https://serpapi.com/google-lr-languages) for a full + * list of supported languages. + */ + lr?: string + + /** + * as_dt + * Parameter controls whether to include or exclude results from the site named in + * the as_sitesearch parameter. + */ + as_dt?: string + + /** + * as_epq + * Parameter identifies a phrase that all documents in the search results must + * contain. You can also use the [phrase + * search](https://developers.google.com/custom-search/docs/xml_results#PhraseSearchqt) + * query term to search for a phrase. + */ + as_epq?: string + + /** + * as_eq + * Parameter identifies a word or phrase that should not appear in any documents in + * the search results. You can also use the [exclude + * query](https://developers.google.com/custom-search/docs/xml_results#Excludeqt) + * term to ensure that a particular word or phrase will not appear in the documents + * in a set of search results. + */ + as_eq?: string + + /** + * as_lq + * Parameter specifies that all search results should contain a link to a + * particular URL. You can also use the + * [link:](https://developers.google.com/custom-search/docs/xml_results#BackLinksqt) + * query term for this type of query. + */ + as_lq?: string + + /** + * as_nlo + * Parameter specifies the starting value for a search range. Use as_nlo and as_nhi + * to append an inclusive search range. + */ + as_nlo?: string + + /** + * as_nhi + * Parameter specifies the ending value for a search range. Use as_nlo and as_nhi + * to append an inclusive search range. + */ + as_nhi?: string + + /** + * as_oq + * Parameter provides additional search terms to check for in a document, where + * each document in the search results must contain at least one of the additional + * search terms. You can also use the [Boolean + * OR](https://developers.google.com/custom-search/docs/xml_results#BooleanOrqt) + * query term for this type of query. + */ + as_oq?: string + + /** + * as_q + * Parameter provides search terms to check for in a document. This parameter is + * also commonly used to allow users to specify additional terms to search for + * within a set of search results. + */ + as_q?: string + + /** + * as_qdr + * Parameter requests search results from a specified time period (quick date + * range). The following values are supported: + * `d[number]`: requests results from the specified number of past days. Example + * for the past 10 days: `as_qdr=d10` + * `w[number]`: requests results from the specified number of past weeks. + * `m[number]`: requests results from the specified number of past months. + * `y[number]`: requests results from the specified number of past years. Example + * for the past year: `as_qdr=y` + */ + as_qdr?: string + + /** + * as_rq + * Parameter specifies that all search results should be pages that are related to + * the specified URL. The parameter value should be a URL. You can also use the + * [related:](https://developers.google.com/custom-search/docs/xml_results#RelatedLinksqt) + * query term for this type of query. + */ + as_rq?: string + + /** + * as_sitesearch + * Parameter allows you to specify that all search results should be pages from a + * given site. By setting the as_dt parameter, you can also use it to exclude pages + * from a given site from your search resutls. + */ + as_sitesearch?: string + + /** + * Advanced Search Parameters + * (to be searched) parameter defines advanced search parameters that aren't + * possible in the regular query field. (e.g., advanced search for patents, dates, + * news, videos, images, apps, or text contents). + */ + tbs?: string + + /** + * Adult Content Filtering + * Parameter defines the level of filtering for adult content. It can be set to + * `active`, or `off` (default). + */ + safe?: string + + /** + * Exclude Auto-corrected Results + * Parameter defines the exclusion of results from an auto-corrected query that is + * spelled wrong. It can be set to `1` to exclude these results, or `0` to include + * them (default). + */ + nfpr?: string + + /** + * Results Filtering + * Parameter defines if the filters for 'Similar Results' and 'Omitted Results' are + * on or off. It can be set to `1` (default) to enable these filters, or `0` to + * disable these filters. + */ + filter?: string + + /** + * Search Type + * (to be matched) parameter defines the type of search you want to do. + * It can be set to: + * `(no tbm parameter)`: regular Google Search, + * `isch`: [Google Images API](https://serpapi.com/images-results), + * `lcl` - [Google Local API](https://serpapi.com/local-results) + * `vid`: [Google Videos API](https://serpapi.com/videos-results), + * `nws`: [Google News API](https://serpapi.com/news-results), + * `shop`: [Google Shopping API](https://serpapi.com/shopping-results), + * or any other Google service. + */ + tbm?: string + + /** + * Result Offset + * Parameter defines the result offset. It skips the given number of results. It's + * used for pagination. (e.g., `0` (default) is the first page of results, `10` is + * the 2nd page of results, `20` is the 3rd page of results, etc.). + * Google Local Results only accepts multiples of `20`(e.g. `20` for the second + * page results, `40` for the third page results, etc.) as the start value. + */ + start?: number + + /** + * Number of Results + * Parameter defines the maximum number of results to return. (e.g., `10` (default) + * returns 10 results, `40` returns 40 results, and `100` returns 100 results). + */ + num?: number + + /** + * Page Number (images) + * Parameter defines the page number for [Google + * Images](https://serpapi.com/images-results). There are 100 images per page. This + * parameter is equivalent to start (offset) = ijn * 100. This parameter works only + * for [Google Images](https://serpapi.com/images-results) (set tbm to `isch`). + */ + ijn?: string + } + + export interface SearchResult extends BaseResponse { + search_metadata: SearchMetadata + search_parameters: SearchParameters + search_information: SearchInformation + local_map?: LocalMap + local_results?: LocalResults + answer_box?: AnswerBox + knowledge_graph?: KnowledgeGraph + inline_images?: InlineImage[] + inline_people_also_search_for?: InlinePeopleAlsoSearchFor[] + related_questions?: SearchResultRelatedQuestion[] + organic_results?: OrganicResult[] + related_searches?: RelatedSearch[] + pagination: Pagination + serpapi_pagination: Pagination + twitter_results?: TwitterResults + } + + export interface TwitterResults { + title: string + link: string + displayed_link: string + tweets: Tweet[] + } + + export interface Tweet { + link: string + snippet: string + published_date: string + } + + export interface AnswerBox { + type: string + title: string + link: string + displayed_link: string + snippet: string + snippet_highlighted_words: string[] + images: string[] + about_this_result: AboutThisResult + about_page_link: string + cached_page_link: string + } + + export interface InlineImage { + link: string + source: string + thumbnail: string + original: string + source_name: string + title?: string + } + + export interface InlinePeopleAlsoSearchFor { + title: string + items: SearchItem[] + see_more_link: string + see_more_serpapi_link: string + } + + export interface SearchItem { + name: string + image: string + link: string + serpapi_link: string + } + + export interface KnowledgeGraph { + type: string + kgmid: string + knowledge_graph_search_link: string + serpapi_knowledge_graph_search_link: string + header_images: HeaderImage[] + description: string + source: Source + buttons: Button[] + people_also_search_for: SearchItem[] + people_also_search_for_link: string + people_also_search_for_stick: string + list: { [key: string]: string[] } + } + + export interface Button { + text: string + subtitle: string + title: string + link: string + displayed_link: string + snippet?: string + snippet_highlighted_words?: string[] + answer?: string + thumbnail: string + search_link: string + serpapi_search_link: string + date?: string + list?: string[] + } + + export interface HeaderImage { + image: string + source: string + } + + export interface Source { + name: string + link: string + } + + export interface LocalMap { + link: string + image: string + gps_coordinates: LocalMapGpsCoordinates + } + + export interface LocalMapGpsCoordinates { + latitude: number + longitude: number + altitude: number + } + + export interface LocalResults { + places: Place[] + more_locations_link: string + } + + export interface Place { + position: number + title: string + rating?: number + reviews_original?: string + reviews?: number + place_id: string + place_id_search: string + lsig: string + thumbnail: string + gps_coordinates: PlaceGpsCoordinates + service_options: ServiceOptions + address?: string + type?: string + hours?: string + } + + export interface PlaceGpsCoordinates { + latitude: number + longitude: number + } + + export interface ServiceOptions { + dine_in?: boolean + takeout: boolean + no_delivery?: boolean + } + + export interface OrganicResult { + position: number + title: string + link: string + displayed_link: string + thumbnail?: string + favicon?: string + snippet: string + snippet_highlighted_words: string[] + sitelinks?: Sitelinks + rich_snippet?: RichSnippet + about_this_result: AboutThisResult + cached_page_link: string + related_pages_link?: string + source: string + related_results?: RelatedResult[] + date?: string + related_questions?: OrganicResultRelatedQuestion[] + } + + export interface AboutThisResult { + keywords: string[] + languages: string[] + regions: string[] + } + + export interface OrganicResultRelatedQuestion { + question: string + snippet: string + snippet_links: SnippetLink[] + } + + export interface SnippetLink { + text: string + link: string + } + + export interface RelatedResult { + position: number + title: string + link: string + displayed_link: string + snippet: string + snippet_highlighted_words: string[] + about_this_result: AboutThisResult + cached_page_link: string + } + + export interface RichSnippet { + bottom: Bottom + } + + export interface Bottom { + extensions?: string[] + questions?: string[] + } + + export interface Sitelinks { + inline: Inline[] + } + + export interface Inline { + title: string + link: string + } + + export interface Pagination { + current: number + next: string + other_pages: { [key: string]: string } + next_link?: string + } + + export interface SearchResultRelatedQuestion { + question: string + snippet: string + title: string + link: string + displayed_link: string + thumbnail: string + next_page_token: string + serpapi_link: string + date?: string + } + + export interface RelatedSearch { + query: string + link: string + } + + export interface SearchInformation { + organic_results_state: string + query_displayed: string + total_results: number + time_taken_displayed: number + menu_items: MenuItem[] + } + + export interface MenuItem { + position: number + title: string + link: string + serpapi_link?: string + } + + export interface SearchMetadata { + id: string + status: string + json_endpoint: string + created_at: string + processed_at: string + google_url: string + raw_html_file: string + total_time_taken: number + } + + export interface SearchParameters { + engine: string + q: string + google_domain: string + device?: 'desktop' | 'tablet' | 'mobile' + } + + export type ClientParams = Partial> +} + +/** + * Lightweight wrapper around SerpAPI for Google search. + * + * @see https://serpapi.com/search-api + */ +export class SerpAPIClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + protected readonly params: serpapi.ClientParams + + constructor({ + apiKey = getEnv('SERPAPI_API_KEY') ?? getEnv('SERP_API_KEY'), + apiBaseUrl = serpapi.API_BASE_URL, + ky = defaultKy, + ...params + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } & serpapi.ClientParams = {}) { + assert( + apiKey, + 'SerpAPIClient missing required "apiKey" (defaults to "SERPAPI_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + this.params = params + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl + }) + } + + @aiFunction({ + name: 'serpapi_google_search', + description: + 'Uses Google Search to return the most relevant web pages for a given query. Useful for finding up-to-date news and information about any topic.', + inputSchema: z.object({ + q: z.string().describe('search query'), + num: z + .number() + .int() + .positive() + .default(5) + .optional() + .describe('number of results to return') + }) + }) + async search(queryOrOpts: string | serpapi.GoogleParameters) { + const defaultGoogleParams: Partial = {} + const options: serpapi.GoogleParameters = + typeof queryOrOpts === 'string' + ? { ...defaultGoogleParams, q: queryOrOpts } + : queryOrOpts + const { timeout, ...rest } = this.params + + // console.log('SerpAPIClient.search', options) + return this.ky + .get('search', { + searchParams: { + ...rest, + engine: 'google', + api_key: this.apiKey, + ...(options as any) + }, + timeout + }) + .json() + } +} diff --git a/src/services/serper-client.ts b/src/services/serper-client.ts new file mode 100644 index 000000000..f7e6d12b5 --- /dev/null +++ b/src/services/serper-client.ts @@ -0,0 +1,297 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, omit } from '../utils.js' + +export namespace serper { + export const API_BASE_URL = 'https://google.serper.dev' + + export const SearchParamsSchema = z.object({ + q: z.string().describe('search query'), + autocorrect: z.boolean().default(true).optional(), + gl: z.string().default('us').optional(), + hl: z.string().default('en').optional(), + page: z.number().int().positive().default(1).optional(), + num: z + .number() + .int() + .positive() + .default(10) + .optional() + .describe('number of results to return') + }) + export type SearchParams = z.infer + + export const GeneralSearchSchema = SearchParamsSchema.extend({ + type: z + .enum(['search', 'images', 'videos', 'places', 'news', 'shopping']) + .default('search') + .optional() + .describe('Type of Google search to perform') + }) + export type GeneralSearchParams = z.infer + + export interface SearchResponse { + searchParameters: SearchParameters & { type: 'search' } + organic: Organic[] + answerBox?: AnswerBox + knowledgeGraph?: KnowledgeGraph + topStories?: TopStory[] + peopleAlsoAsk?: PeopleAlsoAsk[] + relatedSearches?: RelatedSearch[] + } + + export interface SearchImagesResponse { + searchParameters: SearchParameters & { type: 'images' } + images: Image[] + } + + export interface SearchVideosResponse { + searchParameters: SearchParameters & { type: 'videos' } + videos: Video[] + } + + export interface SearchPlacesResponse { + searchParameters: SearchParameters & { type: 'places' } + places: Place[] + } + + export interface SearchNewsResponse { + searchParameters: SearchParameters & { type: 'news' } + news: News[] + } + + export interface SearchShoppingResponse { + searchParameters: SearchParameters & { type: 'shopping' } + shopping: Shopping[] + } + + export type Response = + | SearchResponse + | SearchImagesResponse + | SearchVideosResponse + | SearchPlacesResponse + | SearchNewsResponse + | SearchShoppingResponse + + export interface KnowledgeGraph { + title: string + type: string + website: string + imageUrl: string + description: string + descriptionSource: string + descriptionLink: string + attributes: Record + } + + export interface Organic { + title: string + link: string + snippet: string + position: number + imageUrl?: string + sitelinks?: SiteLink[] + } + + export interface AnswerBox { + snippet: string + snippetHighlighted?: string[] + title: string + link: string + date?: string + position?: number + } + + export interface SiteLink { + title: string + link: string + } + + export interface PeopleAlsoAsk { + question: string + snippet: string + title: string + link: string + } + + export interface RelatedSearch { + query: string + } + + export interface SearchParameters { + q: string + gl: string + hl: string + num: number + autocorrect: boolean + page: number + type: string + engine: string + } + + export interface TopStory { + title: string + link: string + source: string + date: string + imageUrl: string + } + + export interface Image { + title: string + imageUrl: string + imageWidth: number + imageHeight: number + thumbnailUrl: string + thumbnailWidth: number + thumbnailHeight: number + source: string + domain: string + link: string + googleUrl: string + position: number + } + + export interface Video { + title: string + link: string + snippet: string + date: string + imageUrl: string + position: number + } + + export interface Place { + position: number + title: string + address: string + latitude: number + longitude: number + category: string + phoneNumber?: string + website: string + cid: string + rating?: number + ratingCount?: number + } + + export interface News { + title: string + link: string + snippet: string + date: string + source: string + imageUrl: string + position: number + } + + export interface Shopping { + title: string + source: string + link: string + price: string + imageUrl: string + delivery?: Record + rating?: number + ratingCount?: number + offers?: string + productId?: string + position: number + } + + export type ClientParams = Partial> +} + +/** + * Lightweight wrapper around Serper for Google search. + * + * @see https://serper.dev + */ +export class SerperClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + protected readonly params: serper.ClientParams + + constructor({ + apiKey = getEnv('SERPER_API_KEY'), + apiBaseUrl = serper.API_BASE_URL, + ky = defaultKy, + ...params + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } & serper.ClientParams = {}) { + assert( + apiKey, + 'SerperClient missing required "apiKey" (defaults to "SERPER_API_KEY")' + ) + + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + this.params = params + + this.ky = ky.extend({ + prefixUrl: this.apiBaseUrl, + headers: { + 'x-api-key': this.apiKey + } + }) + } + + @aiFunction({ + name: 'serper_google_search', + description: + 'Uses Google Search to return the most relevant web pages for a given query. Useful for finding up-to-date news and information about any topic.', + inputSchema: serper.GeneralSearchSchema.pick({ + q: true, + num: true, + type: true + }) + }) + async search(queryOrOpts: string | serper.GeneralSearchParams) { + const searchType = + typeof queryOrOpts === 'string' ? 'search' : queryOrOpts.type || 'search' + return this._fetch( + searchType, + typeof queryOrOpts === 'string' ? queryOrOpts : omit(queryOrOpts, 'type') + ) + } + + async searchImages(queryOrOpts: string | serper.SearchParams) { + return this._fetch('images', queryOrOpts) + } + + async searchVideos(queryOrOpts: string | serper.SearchParams) { + return this._fetch('videos', queryOrOpts) + } + + async searchPlaces(queryOrOpts: string | serper.SearchParams) { + return this._fetch('places', queryOrOpts) + } + + async searchNews(queryOrOpts: string | serper.SearchParams) { + return this._fetch('news', queryOrOpts) + } + + async searchProducts(queryOrOpts: string | serper.SearchParams) { + return this._fetch('shopping', queryOrOpts) + } + + protected async _fetch( + endpoint: string, + queryOrOpts: string | serper.SearchParams + ): Promise { + const params = { + ...this.params, + ...(typeof queryOrOpts === 'string' ? { q: queryOrOpts } : queryOrOpts) + } + + return this.ky.post(endpoint, { json: params }).json() + } +} diff --git a/src/services/slack-client.ts b/src/services/slack-client.ts new file mode 100644 index 000000000..fcf638484 --- /dev/null +++ b/src/services/slack-client.ts @@ -0,0 +1,459 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { TimeoutError } from '../errors.js' +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, delay, getEnv } from '../utils.js' + +// TODO: need to expose more aiFunctions + +export namespace slack { + export const API_BASE_URL = 'https://slack.com/api' + + export const DEFAULT_TIMEOUT_MS = 120_000 + export const DEFAULT_INTERVAL_MS = 5000 + + export interface BotProfile { + id: string + app_id: string + name: string + icons: Record + deleted: boolean + updated: number + team_id: string + } + + export interface Replies { + messages: Message[] + has_more: boolean + ok: boolean + response_metadata: ResponseMetadata + } + + export interface Message { + bot_id?: string + client_msg_id?: string + type: string + text: string + user: string + ts: string + app_id?: string + blocks?: Record[] + reply_count?: number + subscribed?: boolean + last_read?: string + unread_count?: number + team?: string + thread_ts: string + parent_user_id?: string + bot_profile?: BotProfile + } + + export interface ResponseMetadata { + next_cursor: string + } + + export type Attachment = { + [key: string]: any + } + + export type Block = { + [key: string]: any + } + + /** + * Parameters for the Slack API's `chat.postMessage` method. + * + * @see {@link https://api.slack.com/methods/chat.postMessage} + */ + export type PostMessageParams = { + /** + * The formatted text of the message to be published. + */ + text: string + + /** + * Channel, private group, or IM channel to send the message to. Can be an encoded ID, or a name. + */ + channel?: string + + /** + * Provide another message's ts value to make this message a reply. Avoid using a reply's ts value; use its parent instead. + */ + thread_ts?: string + + /** + * A JSON-based array of structured attachments, presented as a URL-encoded string. + */ + attachments?: Attachment[] + + /** + * A JSON-based array of structured blocks, presented as a URL-encoded string. + */ + blocks?: Block[] + + /** + * Emoji to use as the icon for this message. Overrides icon_url. + */ + icon_emoji?: string + + /** + * URL to an image to use as the icon for this message. + */ + icon_url?: string + + /** + * If set to true, user group handles (to name just one example) will be linked in the message text. + */ + link_names?: boolean + + /** + * Change how messages are treated (default: 'none'). + */ + parse?: 'full' | 'none' + + /** + * Used in conjunction with thread_ts and indicates whether reply should be made visible to everyone in the channel or conversation. + */ + reply_broadcast?: boolean + + /** + * Pass true to enable unfurling of primarily text-based content. + */ + unfurl_links?: boolean + + /** + * Pass false to disable unfurling of media content. + */ + unfurl_media?: boolean + + /** + * Set your bot's user name. + */ + username?: string + } + + /** + * Parameters for the Slack API's `conversations.history` method. + * + * @see {@link https://api.slack.com/methods/conversations.history} + */ + export type ConversationHistoryParams = { + /** + * The conversation ID to fetch history for. + */ + channel: string + + /** + * Only messages after this Unix timestamp will be included in results (default: `0`). + */ + oldest?: string + + /** + * The cursor value used for pagination of results (default: first page). + */ + cursor?: string + + /** + * Only messages before this Unix timestamp will be included in results (default: now). + */ + latest?: string + + /** + * The maximum number of items to return (default: `100`). + */ + limit?: number + + /** + * Include messages with the oldest or latest timestamps in results. Ignored unless either timestamp is specified (default: `false`). + */ + inclusive?: boolean + + /** + * Return all metadata associated with the messages (default: `false`). + */ + include_all_metadata?: boolean + } + + /** + * Parameters for the Slack API's `conversations.replies` method. + * + * @see {@link https://api.slack.com/methods/conversations.replies} + */ + export type ConversationRepliesParams = { + /** + * The conversation ID to fetch the thread from. + */ + channel: string + + /** + * Unique identifier of either a thread’s parent message or a message in the thread. + * + * ### Notes + * + * - ts must be the timestamp of an existing message with 0 or more replies. + * - If there are no replies then just the single message referenced by ts will return - it is just an ordinary, unthreaded message. + */ + ts: string + + /** + * The cursor value used for pagination of results. + * Set this to the `next_cursor` attribute returned by a previous request's response_metadata. + */ + cursor?: string + + /** + * Only messages before this Unix timestamp will be included in results. + */ + latest?: string + + /** + * Only messages after this Unix timestamp will be included in results. + */ + oddest?: string + + /** + * The maximum number of items to return. + * Fewer than the requested number of items may be returned, even if the end of the users list hasn't been reached. + */ + limit?: number + + /** + * Include messages with the oldest or latest timestamps in results. Ignored unless either timestamp is specified. + */ + inclusive?: boolean + + /** + * Return all metadata associated with this message. + */ + include_thread_metadata?: boolean + } + + export type SendAndWaitOptions = { + /** + * The text of the message to send. + */ + text: string + + /** + * The ID of the channel to send the message to. + */ + channel?: string + + /** + * The timeout in milliseconds to wait for a reply before throwing an error. + */ + timeoutMs?: number + + /** + * The interval in milliseconds to poll for replies. + */ + intervalMs?: number + + /** + * A function to validate the reply message. If the function returns `true`, the reply is considered valid and the function will return the message. If the function returns `false`, the reply is considered invalid and the function will continue to wait for a reply until the timeout is reached. + */ + validate?: (message: Message) => boolean + + /** + * A stop signal from an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController), which can be used to abort retrying. More specifically, when `AbortController.abort(reason)` is called, the function will throw an error with the `reason` argument as the error message. + */ + stopSignal?: AbortSignal + } +} + +/** + * Minimal Slack API client for sending and receiving Slack messages. + * + * @see https://api.slack.com/docs + */ +export class SlackClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly defaultChannel?: string + + constructor({ + apiKey = getEnv('SLACK_API_KEY'), + apiBaseUrl = slack.API_BASE_URL, + defaultChannel = getEnv('SLACK_DEFAULT_CHANNEL'), + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + defaultChannel?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'SlackClient missing required "apiKey" (defaults to "SLACK_API_KEY")' + ) + + super() + + this.defaultChannel = defaultChannel + + this.ky = ky.extend({ + prefixUrl: apiBaseUrl, + headers: { + Authorization: `Bearer ${apiKey}` + } + }) + } + + /** + * Sends a message to a channel. + */ + @aiFunction({ + name: 'slack_send_message', + description: 'Sends a slack message to a slack channel', + inputSchema: z.object({ + text: z + .string() + .describe('Formatted text of the message to be published.'), + channel: z + .string() + .describe( + 'Channel, private group, or IM channel to send the message to. Can be an encoded ID, or a name.' + ) + }) + }) + public async sendMessage(options: slack.PostMessageParams) { + if (!options.channel && !this.defaultChannel) { + throw new Error('Error no channel specified') + } + + return this.ky + .post('chat.postMessage', { + json: { + channel: this.defaultChannel, + ...options + } + }) + .json() + } + + /** + * Fetches a conversation's history of messages and events. + */ + public async fetchConversationHistory( + options: slack.ConversationHistoryParams + ) { + return this.ky + .get('conversations.history', { + searchParams: options + }) + .json() + } + + /** + * Fetches replies to a message in a channel. + */ + protected async fetchReplies(options: slack.ConversationRepliesParams) { + return this.ky + .get('conversations.replies', { + searchParams: options + }) + .json() + } + + /** + * Returns a list of messages that were sent in a channel after a given + * timestamp both directly and in threads. + */ + private async fetchCandidates(channel: string, ts: string) { + const history = await this.fetchConversationHistory({ channel }) + const directReplies = await this.fetchReplies({ channel, ts }) + + let candidates: slack.Message[] = [] + + if (directReplies.ok) { + candidates = candidates.concat(directReplies.messages) + } + + if (history.ok) { + candidates = candidates.concat(history.messages) + } + + // Filter out older messages before the message was sent and drop bot messages: + candidates = candidates.filter( + (message) => message.ts > ts && !message.bot_id + ) + + // Sort by timestamp so that the most recent messages come first: + candidates.sort((a, b) => { + return Number.parseFloat(b.ts) - Number.parseFloat(a.ts) + }) + + return candidates + } + + /** + * Sends a message to a channel and waits for a reply to the message, which + * is returned if it passes validation. + */ + public async sendMessageAndWaitForReply({ + text, + channel = this.defaultChannel, + timeoutMs = slack.DEFAULT_TIMEOUT_MS, + intervalMs = slack.DEFAULT_INTERVAL_MS, + validate = () => true, + stopSignal + }: slack.SendAndWaitOptions) { + if (!channel) { + throw new Error('SlackClient missing required "channel"') + } + + let aborted = false + stopSignal?.addEventListener( + 'abort', + () => { + aborted = true + }, + { once: true } + ) + + const res = await this.sendMessage({ text, channel }) + + if (!res.ts) { + throw new Error('Missing ts in response') + } + + const start = Date.now() + let nUserMessages = 0 + + do { + if (aborted) { + const reason = stopSignal?.reason || 'Aborted waiting for reply' + + if (reason instanceof Error) { + throw reason + } else { + throw new TypeError(reason) + } + } + + const candidates = await this.fetchCandidates(channel, res.ts) + + if (candidates.length > 0) { + const candidate = candidates[0]! + + if (validate(candidate)) { + return candidate + } + + if (nUserMessages !== candidates.length) { + await this.sendMessage({ + text: `Invalid response: ${candidate.text}. Please try again following the instructions.`, + channel, + thread_ts: candidate.ts + }) + } + + nUserMessages = candidates.length + } + + await delay(intervalMs) + } while (Date.now() - start < timeoutMs) + + throw new TimeoutError('SlackClient timed out waiting for reply') + } +} diff --git a/src/services/tavily-client.ts b/src/services/tavily-client.ts new file mode 100644 index 000000000..957747575 --- /dev/null +++ b/src/services/tavily-client.ts @@ -0,0 +1,186 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, pruneNullOrUndefined, throttleKy } from '../utils.js' + +export namespace tavily { + export const API_BASE_URL = 'https://api.tavily.com' + + // Allow up to 20 requests per minute by default. + export const throttle = pThrottle({ + limit: 20, + interval: 60 * 1000 + }) + + export interface SearchOptions { + /** Search query. (required) */ + query: string + + /** The depth of the search. It can be basic or advanced. Default is basic for quick results and advanced for indepth high quality results but longer response time. Advanced calls equals 2 requests. */ + search_depth?: 'basic' | 'advanced' + + /** Include a synthesized answer in the search results. Default is `false`. */ + include_answer?: boolean + + /** Include a list of query related images in the response. Default is `false`. */ + include_images?: boolean + + /** Include raw content in the search results. Default is `false`. */ + include_raw_content?: boolean + + /** The number of maximum search results to return. Default is `5`. */ + max_results?: number + + /** A list of domains to specifically include in the search results. Default is `undefined`, which includes all domains. */ + include_domains?: string[] + + /** A list of domains to specifically exclude from the search results. Default is `undefined`, which doesn't exclude any domains. */ + exclude_domains?: string[] + } + + export interface SearchResponse { + /** The search query. */ + query: string + + /** A list of sorted search results ranked by relevancy. */ + results: SearchResult[] + + /** The answer to your search query. */ + answer?: string + + /** A list of query related image urls. */ + images?: string[] + + /** A list of suggested research follow up questions related to original query. */ + follow_up_questions?: string[] + + /** How long it took to generate a response. */ + response_time: string + } + + export interface SearchResult { + /** The url of the search result. */ + url: string + + /** The title of the search result page. */ + title: string + + /** + * The most query related content from the scraped url. We use proprietary AI and algorithms to extract only the most relevant content from each url, to optimize for context quality and size. + */ + content: string + + /** The parsed and cleaned HTML of the site. For now includes parsed text only. */ + raw_content?: string + + /** The relevance score of the search result. */ + score: string + } +} + +/** + * Tavily provides a web search API tailored for LLMs. + * + * @see https://tavily.com + */ +export class TavilyClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('TAVILY_API_KEY'), + apiBaseUrl = tavily.API_BASE_URL, + throttle = true, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + throttle?: boolean + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'TavilyClient missing required "apiKey" (defaults to "TAVILY_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + const throttledKy = throttle ? throttleKy(ky, tavily.throttle) : ky + + this.ky = throttledKy.extend({ + prefixUrl: this.apiBaseUrl + }) + } + + /** + * Searches the web for pages relevant to the given query and summarizes the results. + */ + @aiFunction({ + name: 'tavily_web_search', + description: + 'Searches the web to find the most relevant pages for a given query and summarizes the results. Very useful for finding up-to-date news and information about any topic.', + inputSchema: z.object({ + query: z + .string() + .describe('The query to search for. Accepts any Google search query.'), + search_depth: z + .enum(['basic', 'advanced']) + .optional() + .describe( + 'How deep of a search to perform. Use "basic" for quick results and "advanced" for slower, in-depth results.' + ), + include_answer: z + .boolean() + .optional() + .describe( + 'Whether or not to include an answer summary in the results.' + ), + include_images: z + .boolean() + .optional() + .describe('Whether or not to include images in the results.'), + max_results: z + .number() + .int() + .positive() + .default(5) + .optional() + .describe('Max number of search results to return.') + // include_domains: z + // .array(z.string()) + // .optional() + // .describe( + // 'List of domains to specifically include in the search results.' + // ), + // exclude_domains: z + // .array(z.string()) + // .optional() + // .describe( + // 'List of domains to specifically exclude from the search results.' + // ) + }) + }) + async search(queryOrOpts: string | tavily.SearchOptions) { + const options = + typeof queryOrOpts === 'string' ? { query: queryOrOpts } : queryOrOpts + + const res = await this.ky + .post('search', { + json: { + ...options, + api_key: this.apiKey + } + }) + .json() + + return pruneNullOrUndefined({ + ...res, + results: res.results?.map(pruneNullOrUndefined) + }) + } +} diff --git a/src/services/twilio-client.ts b/src/services/twilio-client.ts new file mode 100644 index 000000000..b8b618c3c --- /dev/null +++ b/src/services/twilio-client.ts @@ -0,0 +1,567 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { TimeoutError } from '../errors.js' +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, delay, getEnv } from '../utils.js' + +export namespace twilio { + export const CONVERSATION_API_BASE_URL = 'https://conversations.twilio.com/v1' + + export const DEFAULT_TIMEOUT_MS = 1_800_000 + export const DEFAULT_INTERVAL_MS = 5000 + export const DEFAULT_BOT_NAME = 'agentic' + + /** + * Twilio recommends keeping SMS messages to a length of 320 characters or less, so we'll use that as the maximum. + * + * @see {@link https://support.twilio.com/hc/en-us/articles/360033806753-Maximum-Message-Length-with-Twilio-Programmable-Messaging} + */ + export const SMS_LENGTH_SOFT_LIMIT = 320 + export const SMS_LENGTH_HARD_LIMIT = 1600 + + export interface Conversation { + unique_name?: string + date_updated: Date + friendly_name: string + timers: null + account_sid: string + url: string + state: string + date_created: Date + messaging_service_sid: string + sid: string + attributes: string + bindings: null + chat_service_sid: string + links: ConversationLinks + } + + export interface ConversationLinks { + participants: string + messages: string + webhooks: string + } + + export interface ConversationMessage { + body: string + index: number + author: string + date_updated: Date + media: null + participant_sid: string | null + conversation_sid: string + account_sid: string + delivery: null + url: string + date_created: Date + content_sid: string | null + sid: string + attributes: string + links: { + delivery_receipts: string + } + } + + export interface ConversationParticipant { + last_read_message_index: null + date_updated: Date + last_read_timestamp: null + conversation_sid: string + account_sid: string + url: string + date_created: Date + role_sid: string + sid: string + attributes: string + identity?: string + messaging_binding: ConversationMessagingBinding + } + + export interface ConversationMessagingBinding { + proxy_address: string + type: string + address: string + } + + export interface ConversationMessages { + messages: ConversationMessage[] + meta: { + page: number + page_size: number + first_page_url: string + previous_page_url: string | null + url: string + next_page_url: string | null + key: string + } + } + + /** + * Participant Conversation Resource. + * + * This interface represents a participant in a conversation, along with the conversation details. + */ + export interface ParticipantConversation { + /** The unique ID of the Account responsible for this conversation. */ + account_sid: string + + /** The unique ID of the Conversation Service this conversation belongs to. */ + chat_service_sid: string + + /** The unique ID of the Participant. */ + participant_sid: string + + /** The unique string that identifies the conversation participant as Conversation User. */ + participant_user_sid: string + + /** + * A unique string identifier for the conversation participant as Conversation User. + * This parameter is non-null if (and only if) the participant is using the Conversations SDK to communicate. + */ + participant_identity: string + + /** + * Information about how this participant exchanges messages with the conversation. + * A JSON parameter consisting of type and address fields of the participant. + */ + participant_messaging_binding: object + + /** The unique ID of the Conversation this Participant belongs to. */ + conversation_sid: string + + /** An application-defined string that uniquely identifies the Conversation resource. */ + conversation_unique_name: string + + /** The human-readable name of this conversation, limited to 256 characters. */ + conversation_friendly_name: string + + /** + * An optional string metadata field you can use to store any data you wish. + * The string value must contain structurally valid JSON if specified. + */ + conversation_attributes: string + + /** The date that this conversation was created, given in ISO 8601 format. */ + conversation_date_created: string + + /** The date that this conversation was last updated, given in ISO 8601 format. */ + conversation_date_updated: string + + /** Identity of the creator of this Conversation. */ + conversation_created_by: string + + /** The current state of this User Conversation. One of inactive, active or closed. */ + conversation_state: 'inactive' | 'active' | 'closed' + + /** Timer date values representing state update for this conversation. */ + conversation_timers: object + + /** Contains absolute URLs to access the participant and conversation of this conversation. */ + links: { participant: string; conversation: string } + } + + export type SendAndWaitOptions = { + /** + * The recipient's phone number in E.164 format (e.g. +14565551234). + */ + recipientPhoneNumber?: string + + /** + * The text of the message to send (or an array of strings to send as separate messages). + */ + text: string | string[] + + /** + * Friendly name of the conversation. + */ + name: string + + /** + * The timeout in milliseconds to wait for a reply before throwing an error. + */ + timeoutMs?: number + + /** + * The interval in milliseconds to poll for replies. + */ + intervalMs?: number + + /** + * A function to validate the reply message. If the function returns `true`, the reply is considered valid and the function will return the message. If the function returns `false`, the reply is considered invalid and the function will continue to wait for a reply until the timeout is reached. + */ + validate?: (message: ConversationMessage) => boolean + + /** + * A stop signal from an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController), which can be used to abort retrying. More specifically, when `AbortController.abort(reason)` is called, the function will throw an error with the `reason` argument as the error message. + */ + stopSignal?: AbortSignal + } + + /** + * Chunks a string into an array of chunks. + * + * @param text - string to chunk + * @param maxLength - maximum length of each chunk + * + * @returns array of chunks + */ + export function chunkString(text: string, maxLength: number): string[] { + const words = text.split(' ') + const chunks: string[] = [] + let chunk = '' + + for (const word of words) { + if (word.length > maxLength) { + // Truncate the word if it's too long and indicate that it was truncated: + chunks.push(word.slice(0, Math.max(0, maxLength - 3)) + '...') + } else if ((chunk + ' ' + word).length > maxLength) { + chunks.push(chunk.trim()) + chunk = word + } else { + chunk += (chunk ? ' ' : '') + word + } + } + + if (chunk) { + chunks.push(chunk.trim()) + } + + return chunks + } + + /** + * Chunks an array of strings into an array of chunks while preserving + * existing sections. + * + * @param textSections - array of strings to chunk + * @param maxLength - maximum length of each chunk + * + * @returns array of chunks + */ + export function chunkMultipleStrings( + textSections: string[], + maxLength: number + ): string[] { + return textSections.flatMap((section) => chunkString(section, maxLength)) + } +} + +/** + * A client for interacting with the Twilio Conversations API to send automated + * messages and wait for replies. + * + * @see {@link https://www.twilio.com/docs/conversations/api} + */ +export class TwilioClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly phoneNumber: string + protected readonly botName: string + protected readonly defaultRecipientPhoneNumber?: string + + constructor({ + accountSid = getEnv('TWILIO_ACCOUNT_SID'), + authToken = getEnv('TWILIO_AUTH_TOKEN'), + phoneNumber = getEnv('TWILIO_PHONE_NUMBER'), + defaultRecipientPhoneNumber = getEnv( + 'TWILIO_DEFAULT_RECIPIENT_PHONE_NUMBER' + ), + apiBaseUrl = twilio.CONVERSATION_API_BASE_URL, + botName = twilio.DEFAULT_BOT_NAME, + ky = defaultKy + }: { + accountSid?: string + authToken?: string + phoneNumber?: string + defaultRecipientPhoneNumber?: string + apiBaseUrl?: string + botName?: string + ky?: KyInstance + } = {}) { + assert( + accountSid, + 'TwilioClient missing required "accountSid" (defaults to "TWILIO_ACCOUNT_SID")' + ) + assert( + authToken, + 'TwilioClient missing required "authToken" (defaults to "TWILIO_AUTH_TOKEN")' + ) + assert( + phoneNumber, + 'TwilioClient missing required "phoneNumber" (defaults to "TWILIO_PHONE_NUMBER")' + ) + super() + + if (defaultRecipientPhoneNumber) { + this.defaultRecipientPhoneNumber = defaultRecipientPhoneNumber + } + + this.botName = botName + this.phoneNumber = phoneNumber + + this.ky = ky.extend({ + prefixUrl: apiBaseUrl, + headers: { + Authorization: + 'Basic ' + + Buffer.from(`${accountSid}:${authToken}`).toString('base64'), + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + } + + /** + * Deletes a conversation and all its messages. + */ + async deleteConversation(conversationSid: string) { + return this.ky.delete(`Conversations/${conversationSid}`) + } + + /** + * Removes a participant from a conversation. + */ + async removeParticipant({ + conversationSid, + participantSid + }: { + conversationSid: string + participantSid: string + }) { + return this.ky.delete( + `Conversations/${conversationSid}/Participants/${participantSid}` + ) + } + + /** + * Fetches all conversations a participant as identified by their phone number is a part of. + */ + async findParticipantConversations(participantPhoneNumber: string) { + const encodedPhoneNumber = encodeURIComponent(participantPhoneNumber) + return this.ky + .get(`ParticipantConversations?Address=${encodedPhoneNumber}`) + .json<{ conversations: twilio.ParticipantConversation[] }>() + } + + /** + * Creates a new conversation. + */ + async createConversation(friendlyName: string) { + const params = new URLSearchParams() + params.set('FriendlyName', friendlyName) + return this.ky + .post('Conversations', { + body: params + }) + .json() + } + + /** + * Adds a participant to a conversation. + */ + async addParticipant({ + conversationSid, + recipientPhoneNumber + }: { + conversationSid: string + recipientPhoneNumber: string + }) { + const params = new URLSearchParams() + params.set('MessagingBinding.Address', recipientPhoneNumber) + params.set('MessagingBinding.ProxyAddress', this.phoneNumber) + return this.ky + .post(`Conversations/${conversationSid}/Participants`, { + body: params + }) + .json() + } + + /** + * Chunks a long text message into smaller parts and sends them as separate messages. + */ + async sendTextWithChunking({ + conversationSid, + text + }: { + conversationSid: string + text: string | string[] + maxChunkLength?: number + }) { + let chunks + if (Array.isArray(text)) { + chunks = twilio.chunkMultipleStrings(text, twilio.SMS_LENGTH_SOFT_LIMIT) + } else { + chunks = twilio.chunkString(text, twilio.SMS_LENGTH_SOFT_LIMIT) + } + + const out: twilio.ConversationMessage[] = [] + for (const chunk of chunks) { + const sent = await this.sendMessage({ + conversationSid, + text: chunk + }) + out.push(sent) + } + + return out + } + + /** + * Posts a message to a conversation. + */ + @aiFunction({ + name: 'twilio_send_message', + description: + 'Sends an text SMS message via the Twilio Conversation API to a specific conversation.', + inputSchema: z.object({ + text: z + .string() + .describe( + 'Text of the SMS content to sent. Must be brief as SMS has strict character limits.' + ), + conversationSid: z + .string() + .describe('ID of the Twilio Conversation to the send the emssage to.') + }) + }) + async sendMessage({ + conversationSid, + text + }: { + conversationSid: string + text: string + }) { + // Truncate the text if it exceeds the hard limit and add an ellipsis: + if (text.length > twilio.SMS_LENGTH_HARD_LIMIT) { + text = + text.slice(0, Math.max(0, twilio.SMS_LENGTH_HARD_LIMIT - 3)) + '...' + } + + const params = new URLSearchParams() + params.set('Body', text) + params.set('Author', this.botName) + return this.ky + .post(`Conversations/${conversationSid}/Messages`, { + body: params + }) + .json() + } + + /** + * Fetches all messages in a conversation. + */ + @aiFunction({ + name: 'twilio_get_messages', + description: + 'Retrieves all SMS messages contained within a specific Twilio Conversation.', + inputSchema: z.object({ + conversationSid: z + .string() + .describe( + 'ID of the Twilio Conversation to the retrieve the messages for.' + ) + }) + }) + async fetchMessages( + conversationSidOrOptions: string | { conversationSid: string } + ) { + const conversationSid = + typeof conversationSidOrOptions === 'string' + ? conversationSidOrOptions + : conversationSidOrOptions.conversationSid + + return this.ky + .get(`Conversations/${conversationSid}/Messages`) + .json() + } + + /** + * Sends a SMS to a recipient and waits for a reply to the message, which is returned if it passes validation. + */ + public async sendAndWaitForReply({ + text, + name, + recipientPhoneNumber = this.defaultRecipientPhoneNumber, + timeoutMs = twilio.DEFAULT_TIMEOUT_MS, + intervalMs = twilio.DEFAULT_INTERVAL_MS, + validate = () => true, + stopSignal + }: twilio.SendAndWaitOptions) { + if (!recipientPhoneNumber) { + throw new Error( + 'TwilioClient error missing required "recipientPhoneNumber"' + ) + } + + let aborted = false + stopSignal?.addEventListener( + 'abort', + () => { + aborted = true + }, + { once: true } + ) + + const { sid: conversationSid } = await this.createConversation(name) + + // Find and remove participant from conversation they are currently in, if any: + const { conversations } = + await this.findParticipantConversations(recipientPhoneNumber) + + for (const conversation of conversations) { + await this.removeParticipant({ + conversationSid: conversation.conversation_sid, + participantSid: conversation.participant_sid + }) + } + + const { sid: participantSid } = await this.addParticipant({ + conversationSid, + recipientPhoneNumber + }) + await this.sendTextWithChunking({ conversationSid, text }) + + const start = Date.now() + let nUserMessages = 0 + + do { + if (aborted) { + await this.removeParticipant({ conversationSid, participantSid }) + const reason = stopSignal?.reason || 'Aborted waiting for reply' + + if (reason instanceof Error) { + throw reason + } else { + throw new TypeError(reason) + } + } + + const response = await this.fetchMessages(conversationSid) + const candidates = response.messages.filter( + (message) => message.author !== this.botName + ) + + if (candidates.length > 0) { + const candidate = candidates.at(-1)! + + if (candidate && validate(candidate)) { + await this.removeParticipant({ conversationSid, participantSid }) + return candidate + } + + if (nUserMessages !== candidates.length) { + await this.sendMessage({ + text: `Invalid response: ${candidate.body}. Please try again with a valid response format.`, + conversationSid + }) + } + + nUserMessages = candidates.length + } + + await delay(intervalMs) + } while (Date.now() - start < timeoutMs) + + await this.removeParticipant({ conversationSid, participantSid }) + throw new TimeoutError('Twilio timeout waiting for reply') + } +} diff --git a/src/services/twitter/client.ts b/src/services/twitter/client.ts new file mode 100644 index 000000000..1ba99601d --- /dev/null +++ b/src/services/twitter/client.ts @@ -0,0 +1,78 @@ +import { auth, Client as TwitterV2Client } from 'twitter-api-sdk' + +import { getNango, validateNangoConnectionOAuthScopes } from '../../nango.js' +import { assert, getEnv } from '../../utils.js' + +// Auth new Nango accounts here: https://app.nango.dev/connections + +// The Twitter OAuth2User class requires a client id, which we don't have +// since we're using Nango for auth, so instead we just pass a dummy value +// and allow Nango to handle all auth/refresh/access token management. +const dummyTwitterClientId = 'agentic' + +export const defaultTwitterOAuthScopes = [ + 'tweet.read', + 'users.read', + 'offline.access', + 'tweet.write' +] + +async function createTwitterAuth({ + scopes, + nangoConnectionId, + nangoCallbackUrl, + nangoProviderConfigKey +}: { + scopes: string[] + nangoConnectionId: string + nangoCallbackUrl: string + nangoProviderConfigKey: string +}): Promise { + const nango = getNango() + const connection = await nango.getConnection( + nangoProviderConfigKey, + nangoConnectionId + ) + + validateNangoConnectionOAuthScopes({ + connection, + scopes + }) + + const token = connection.credentials.raw + assert(token) + + return new auth.OAuth2User({ + client_id: dummyTwitterClientId, + callback: nangoCallbackUrl, + scopes: scopes as any[], + token + }) +} + +export async function createTwitterV2Client({ + scopes = defaultTwitterOAuthScopes, + nangoConnectionId = getEnv('NANGO_CONNECTION_ID'), + nangoCallbackUrl = getEnv('NANGO_CALLBACK_URL') ?? + 'https://api.nango.dev/oauth/callback', + nangoProviderConfigKey = 'twitter-v2' +}: { + scopes?: string[] + nangoConnectionId?: string + nangoCallbackUrl?: string + nangoProviderConfigKey?: string +} = {}): Promise { + assert(nangoConnectionId, 'twitter client missing nangoConnectionId') + assert(nangoCallbackUrl, 'twitter client missing nangoCallbackUrl') + + // NOTE: Nango handles refreshing the oauth access token for us + const twitterAuth = await createTwitterAuth({ + scopes, + nangoConnectionId, + nangoCallbackUrl, + nangoProviderConfigKey + }) + + // Twitter API v2 using OAuth 2.0 + return new TwitterV2Client(twitterAuth) +} diff --git a/src/services/twitter/error.ts b/src/services/twitter/error.ts new file mode 100644 index 000000000..4fc8de560 --- /dev/null +++ b/src/services/twitter/error.ts @@ -0,0 +1,32 @@ +export type TwitterErrorType = + | 'twitter:forbidden' + | 'twitter:auth' + | 'twitter:rate-limit' + | 'twitter:unknown' + | 'network' + +export class TwitterError extends Error { + type: TwitterErrorType + isFinal: boolean + status?: number + + constructor( + message: string, + { + type, + isFinal = false, + status, + ...opts + }: ErrorOptions & { + type: TwitterErrorType + isFinal?: boolean + status?: number + } + ) { + super(message, opts) + + this.type = type + this.isFinal = isFinal + this.status = status ?? (opts.cause as any)?.status + } +} diff --git a/src/services/twitter/index.ts b/src/services/twitter/index.ts new file mode 100644 index 000000000..a002d7f40 --- /dev/null +++ b/src/services/twitter/index.ts @@ -0,0 +1,5 @@ +export * from './client.js' +export * from './error.js' +export * from './twitter-client.js' +export type * from './types.js' +export * from './utils.js' diff --git a/src/services/twitter/twitter-client.ts b/src/services/twitter/twitter-client.ts new file mode 100644 index 000000000..8c7ac9de0 --- /dev/null +++ b/src/services/twitter/twitter-client.ts @@ -0,0 +1,453 @@ +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import type * as types from './types.js' +import { aiFunction, AIFunctionsProvider } from '../../fns.js' +import { assert, getEnv } from '../../utils.js' +import { handleKnownTwitterErrors } from './utils.js' + +/** + * This file contains rate-limited wrappers around all of the core Twitter API + * methods that this project uses. + * + * NOTE: Twitter has different API rate limits and quotas per plan, so in order + * to rate-limit effectively, our throttles need to either use the lowest common + * denominator OR vary based on the twitter developer plan you're using. We + * chose to go with the latter. + * + * @see https://developer.twitter.com/en/docs/twitter-api/rate-limits + */ + +type TwitterApiMethod = + | 'createTweet' + | 'usersIdMentions' + | 'findTweetById' + | 'findTweetsById' + | 'searchRecentTweets' + | 'findUserById' + | 'findUserByUsername' + +const TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000 +const FIFTEEN_MINUTES_MS = 15 * 60 * 1000 + +const twitterApiRateLimitsByPlan: Record< + types.TwitterApiPlan, + Record< + TwitterApiMethod, + { + readonly limit: number + readonly interval: number + } + > +> = { + free: { + // 50 per 24h per user + // 50 per 24h per app + createTweet: { limit: 50, interval: TWENTY_FOUR_HOURS_MS }, + + // TODO: according to the twitter docs, this shouldn't be allowed on the + // free plan, but it seems to work... + usersIdMentions: { limit: 1, interval: FIFTEEN_MINUTES_MS }, + findTweetById: { limit: 1, interval: FIFTEEN_MINUTES_MS }, + findTweetsById: { limit: 1, interval: FIFTEEN_MINUTES_MS }, + searchRecentTweets: { limit: 1, interval: FIFTEEN_MINUTES_MS }, + findUserById: { limit: 1, interval: FIFTEEN_MINUTES_MS }, + findUserByUsername: { limit: 1, interval: FIFTEEN_MINUTES_MS } + }, + + basic: { + // 100 per 24h per user + // 1667 per 24h per app + createTweet: { limit: 100, interval: TWENTY_FOUR_HOURS_MS }, + + // https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions + // TODO: undocumented + // 180 per 15m per user + // 450 per 15m per app + usersIdMentions: { limit: 180, interval: FIFTEEN_MINUTES_MS }, + + // 15 per 15m per user + // 15 per 15m per app + findTweetById: { limit: 15, interval: FIFTEEN_MINUTES_MS }, + findTweetsById: { limit: 15, interval: FIFTEEN_MINUTES_MS }, + + // 60 per 15m per user + // 60 per 15m per app + searchRecentTweets: { limit: 60, interval: FIFTEEN_MINUTES_MS }, + + findUserById: { limit: 100, interval: TWENTY_FOUR_HOURS_MS }, + findUserByUsername: { limit: 100, interval: TWENTY_FOUR_HOURS_MS } + }, + + pro: { + // 100 per 15m per user + // 10k per 24h per app + createTweet: { limit: 100, interval: FIFTEEN_MINUTES_MS }, + + // 180 per 15m per user + // 450 per 15m per app + usersIdMentions: { limit: 180, interval: FIFTEEN_MINUTES_MS }, + + // TODO: why would the per-user rate-limit be less than the per-app one?! + // 900 per 15m per user + // 450 per 15m per app + findTweetById: { limit: 450, interval: FIFTEEN_MINUTES_MS }, + findTweetsById: { limit: 450, interval: FIFTEEN_MINUTES_MS }, + + // TODO: why would the per-user rate-limit be less than the per-app one?! + // 456 per 15m per user + // 300 per 15m per app + searchRecentTweets: { limit: 300, interval: FIFTEEN_MINUTES_MS }, + + findUserById: { limit: 300, interval: FIFTEEN_MINUTES_MS }, + findUserByUsername: { limit: 300, interval: FIFTEEN_MINUTES_MS } + }, + + enterprise: { + // NOTE: these are just placeholders; the enterprise plan seems to be + // completely customizable, but it's still useful to define rate limits + // for robustness. These values just 10x those of the pro plan. + createTweet: { limit: 1000, interval: FIFTEEN_MINUTES_MS }, + usersIdMentions: { limit: 1800, interval: FIFTEEN_MINUTES_MS }, + findTweetById: { limit: 4500, interval: FIFTEEN_MINUTES_MS }, + findTweetsById: { limit: 4500, interval: FIFTEEN_MINUTES_MS }, + searchRecentTweets: { limit: 3000, interval: FIFTEEN_MINUTES_MS }, + findUserById: { limit: 3000, interval: FIFTEEN_MINUTES_MS }, + findUserByUsername: { limit: 3000, interval: FIFTEEN_MINUTES_MS } + } +} + +export class TwitterClient extends AIFunctionsProvider { + readonly client: types.TwitterV2Client + readonly twitterApiPlan: types.TwitterApiPlan + + constructor({ + client, + twitterApiPlan = (getEnv('TWITTER_API_PLAN') as types.TwitterApiPlan) ?? + 'free' + }: { + client: types.TwitterV2Client + twitterApiPlan?: types.TwitterApiPlan + }) { + assert( + client, + 'TwitterClient missing required "client" which should be an instance of "twitter-api-sdk" (use `getTwitterV2Client` to initialize the underlying V2 Twitter SDK using Nango OAuth)' + ) + assert(twitterApiPlan, 'TwitterClient missing required "twitterApiPlan"') + + super() + + this.client = client + this.twitterApiPlan = twitterApiPlan + + const twitterApiRateLimits = twitterApiRateLimitsByPlan[twitterApiPlan]! + assert(twitterApiRateLimits, `Invalid twitter api plan: ${twitterApiPlan}`) + + const createTweetThrottle = pThrottle(twitterApiRateLimits.createTweet) + const findTweetByIdThrottle = pThrottle(twitterApiRateLimits.findTweetById) + const findTweetsByIdThrottle = pThrottle( + twitterApiRateLimits.findTweetsById + ) + const searchRecentTweetsThrottle = pThrottle( + twitterApiRateLimits.searchRecentTweets + ) + const findUserByIdThrottle = pThrottle(twitterApiRateLimits.findUserById) + const findUserByUsernameThrottle = pThrottle( + twitterApiRateLimits.findUserByUsername + ) + + this._createTweet = createTweetThrottle(createTweetImpl(this.client)) + this._findTweetById = findTweetByIdThrottle(findTweetByIdImpl(this.client)) + this._findTweetsById = findTweetsByIdThrottle( + findTweetsByIdImpl(this.client) + ) + this._searchRecentTweets = searchRecentTweetsThrottle( + searchRecentTweetsImpl(this.client) + ) + this._findUserById = findUserByIdThrottle(findUserByIdImpl(this.client)) + this._findUserByUsername = findUserByUsernameThrottle( + findUserByUsernameImpl(this.client) + ) + } + + protected _createTweet: ReturnType + protected _findTweetById: ReturnType + protected _findTweetsById: ReturnType + protected _searchRecentTweets: ReturnType + protected _findUserById: ReturnType + protected _findUserByUsername: ReturnType + + @aiFunction({ + name: 'create_tweet', + description: 'Creates a new tweet', + inputSchema: z.object({ + text: z.string().min(1) + }) + }) + async createTweet( + params: types.CreateTweetParams + ): Promise { + return this._createTweet(params) + } + + @aiFunction({ + name: 'get_tweet_by_id', + description: 'Fetch a tweet by its ID', + inputSchema: z.object({ + id: z.string().min(1) + }) + }) + async findTweetById({ + id, + ...params + }: { id: string } & types.FindTweetByIdParams) { + assert( + this.twitterApiPlan !== 'free', + 'TwitterClient.findTweetById not supported on free plan' + ) + + return this._findTweetById(id, params) + } + + @aiFunction({ + name: 'get_tweets_by_id', + description: 'Fetch an array of tweets by their IDs', + inputSchema: z.object({ + ids: z.array(z.string().min(1)) + }) + }) + async findTweetsById({ ids, ...params }: types.FindTweetsByIdParams) { + assert( + this.twitterApiPlan !== 'free', + 'TwitterClient.findTweetsById not supported on free plan' + ) + + return this._findTweetsById(ids, params) + } + + @aiFunction({ + name: 'search_recent_tweets', + description: 'Searches for recent tweets', + inputSchema: z.object({ + query: z.string().min(1), + sort_order: z + .enum(['recency', 'relevancy']) + .default('relevancy') + .optional() + }) + }) + async searchRecentTweets(params: types.SearchRecentTweetsParams) { + assert( + this.twitterApiPlan !== 'free', + 'TwitterClient.searchRecentTweets not supported on free plan' + ) + + return this._searchRecentTweets(params) + } + + @aiFunction({ + name: 'get_twitter_user_by_id', + description: 'Fetch a twitter user by ID', + inputSchema: z.object({ + id: z.string().min(1) + }) + }) + async findUserById({ + id, + ...params + }: { id: string } & types.FindUserByIdParams) { + assert( + this.twitterApiPlan !== 'free', + 'TwitterClient.findUserById not supported on free plan' + ) + + return this._findUserById(id, params) + } + + @aiFunction({ + name: 'get_twitter_user_by_username', + description: 'Fetch a twitter user by username', + inputSchema: z.object({ + username: z.string().min(1) + }) + }) + async findUserByUsername({ + username, + ...params + }: { username: string } & types.FindUserByUsernameParams) { + assert( + this.twitterApiPlan !== 'free', + 'TwitterClient.findUserByUsername not supported on free plan' + ) + + return this._findUserByUsername(username, params) + } +} + +const defaultTwitterQueryTweetFields: types.TwitterQueryTweetFields = [ + 'attachments', + 'author_id', + 'conversation_id', + 'created_at', + 'entities', + 'geo', + 'id', + 'in_reply_to_user_id', + 'lang', + 'public_metrics', + 'possibly_sensitive', + 'referenced_tweets', + 'text' + // 'context_annotations', // not needed (way too verbose and noisy) + // 'edit_controls', / not needed + // 'non_public_metrics', // don't have access to + // 'organic_metrics', // don't have access to + // 'promoted_metrics, // don't have access to + // 'reply_settings', / not needed + // 'source', // not needed + // 'withheld' // not needed +] + +const defaultTwitterQueryUserFields: types.TwitterQueryUserFields = [ + 'created_at', + 'description', + 'entities', + 'id', + 'location', + 'name', + 'pinned_tweet_id', + 'profile_image_url', + 'protected', + 'public_metrics', + 'url', + 'username', + 'verified' + // 'most_recent_tweet_id', + // 'verified_type', + // 'withheld' +] + +const defaultTweetQueryParams: types.TweetsQueryOptions = { + // https://developer.twitter.com/en/docs/twitter-api/expansions + expansions: [ + 'author_id', + 'in_reply_to_user_id', + 'referenced_tweets.id', + 'referenced_tweets.id.author_id', + 'entities.mentions.username', + // TODO + 'attachments.media_keys', + 'geo.place_id', + 'attachments.poll_ids' + ], + 'tweet.fields': defaultTwitterQueryTweetFields, + 'user.fields': defaultTwitterQueryUserFields +} + +const defaultUserQueryParams: types.TwitterUserQueryOptions = { + // https://developer.twitter.com/en/docs/twitter-api/expansions + expansions: ['pinned_tweet_id'], + 'tweet.fields': defaultTwitterQueryTweetFields, + 'user.fields': defaultTwitterQueryUserFields +} + +function createTweetImpl(client: types.TwitterV2Client) { + return async ( + params: types.CreateTweetParams + ): Promise => { + try { + const { data: tweet } = await client.tweets.createTweet(params) + + if (!tweet?.id) { + throw new Error('invalid createTweet response') + } + + return tweet + } catch (err: any) { + console.error('error creating tweet', JSON.stringify(err, null, 2)) + + handleKnownTwitterErrors(err, { label: 'creating tweet' }) + throw err + } + } +} + +function findTweetByIdImpl(client: types.TwitterV2Client) { + return async (tweetId: string, params?: types.FindTweetByIdParams) => { + try { + return await client.tweets.findTweetById(tweetId, { + ...defaultTweetQueryParams, + ...params + }) + } catch (err: any) { + handleKnownTwitterErrors(err, { label: `fetching tweet ${tweetId}` }) + throw err + } + } +} + +function findTweetsByIdImpl(client: types.TwitterV2Client) { + return async ( + ids: string[], + params?: Omit + ) => { + try { + return await client.tweets.findTweetsById({ + ...defaultTweetQueryParams, + ...params, + ids + }) + } catch (err: any) { + handleKnownTwitterErrors(err, { label: `fetching ${ids.length} tweets` }) + throw err + } + } +} + +function searchRecentTweetsImpl(client: types.TwitterV2Client) { + return async (params: types.SearchRecentTweetsParams) => { + try { + return await client.tweets.tweetsRecentSearch({ + ...defaultTweetQueryParams, + ...params + }) + } catch (err: any) { + handleKnownTwitterErrors(err, { + label: `searching tweets query "${params.query}"` + }) + throw err + } + } +} + +function findUserByIdImpl(client: types.TwitterV2Client) { + return async (userId: string, params?: types.FindUserByIdParams) => { + try { + return await client.users.findUserById(userId, { + ...defaultUserQueryParams, + ...params + }) + } catch (err: any) { + handleKnownTwitterErrors(err, { + label: `fetching user with id ${userId}` + }) + throw err + } + } +} + +function findUserByUsernameImpl(client: types.TwitterV2Client) { + return async (username: string, params?: types.FindUserByUsernameParams) => { + try { + return await client.users.findUserByUsername(username, { + ...defaultUserQueryParams, + ...params + }) + } catch (err: any) { + handleKnownTwitterErrors(err, { + label: `fetching user with username ${username}` + }) + throw err + } + } +} diff --git a/src/services/twitter/types.ts b/src/services/twitter/types.ts new file mode 100644 index 000000000..18ebbad10 --- /dev/null +++ b/src/services/twitter/types.ts @@ -0,0 +1,75 @@ +import type { AsyncReturnType, Simplify } from 'type-fest' +import { type Client as TwitterV2Client } from 'twitter-api-sdk' + +export { type Client as TwitterV2Client } from 'twitter-api-sdk' + +export type TwitterApiPlan = 'free' | 'basic' | 'pro' | 'enterprise' + +export type TweetsQueryOptions = Simplify< + Pick< + Parameters[0], + 'expansions' | 'tweet.fields' | 'user.fields' + > +> + +export type TwitterUserQueryOptions = Simplify< + Pick< + NonNullable[1]>, + 'expansions' | 'tweet.fields' | 'user.fields' + > +> + +export type TwitterQueryTweetFields = TweetsQueryOptions['tweet.fields'] +export type TwitterQueryUserFields = TweetsQueryOptions['user.fields'] + +export type TwitterUserIdMentionsQueryOptions = Simplify< + NonNullable[1]> +> + +export type CreateTweetParams = Simplify< + Parameters[0] +> + +export type UsersIdMentionsParams = Simplify< + Parameters[1] +> + +export type FindTweetByIdParams = Simplify< + Parameters[1] +> + +export type FindTweetsByIdParams = Simplify< + Parameters[0] +> + +export type SearchRecentTweetsParams = Simplify< + Parameters[0] +> + +export type FindUserByIdParams = Simplify< + Parameters[1] +> + +export type FindUserByUsernameParams = Simplify< + Parameters[1] +> + +type Unpacked = T extends (infer U)[] ? U : T + +export type Tweet = Simplify< + NonNullable< + Unpacked< + AsyncReturnType['data'] + > + > +> +export type TwitterUser = Simplify< + NonNullable['data']> +> +export type CreatedTweet = Simplify< + NonNullable['data']> +> + +export type TwitterUrl = Simplify< + Unpacked['urls']>> +> diff --git a/src/services/twitter/utils.ts b/src/services/twitter/utils.ts new file mode 100644 index 000000000..a4a97dd0e --- /dev/null +++ b/src/services/twitter/utils.ts @@ -0,0 +1,140 @@ +import type * as types from './types.js' +import { omit } from '../../utils.js' +import { TwitterError } from './error.js' + +/** + * Error handler which takes in an unknown Error object and converts it to a + * structured TwitterError object for a set of common Twitter API errors. + * + * Re-throws the error and will never return. + */ +export function handleKnownTwitterErrors( + err: any, + { label = '' }: { label?: string } = {} +) { + if (err.status === 403) { + // user may have deleted the tweet we're trying to respond to + throw new TwitterError( + err.error?.detail || `error ${label}: 403 forbidden`, + { + type: 'twitter:forbidden', + isFinal: true, + cause: err + } + ) + } else if (err.status === 401) { + throw new TwitterError(`error ${label}: unauthorized`, { + type: 'twitter:auth', + cause: err + }) + } else if (err.status === 400) { + if ( + /value passed for the token was invalid/i.test( + err.error?.error_description + ) + ) { + throw new TwitterError(`error ${label}: invalid auth token`, { + type: 'twitter:auth', + cause: err + }) + } + } else if (err.status === 429) { + throw new TwitterError(`error ${label}: too many requests`, { + type: 'twitter:rate-limit', + cause: err + }) + } else if (err.status === 404) { + throw new TwitterError(err.toString(), { + type: 'twitter:forbidden', + isFinal: true, + cause: err + }) + } + + if (err.status >= 400 && err.status < 500) { + throw new TwitterError( + `error ${label}: ${err.status} ${ + err.error?.description || err.toString() + }`, + { + type: 'twitter:unknown', + isFinal: true, + cause: err + } + ) + } else if (err.status >= 500) { + throw new TwitterError( + `error ${label}: ${err.status} ${ + err.error?.description || err.toString() + }`, + { + type: 'twitter:unknown', + isFinal: false, + cause: err + } + ) + } + + const reason = err.toString().toLowerCase() + + if (reason.includes('fetcherror') || reason.includes('enotfound')) { + throw new TwitterError(err.toString(), { + type: 'network', + cause: err + }) + } + + // Otherwise, propagate the original error + throw err +} + +export function getPrunedTweet( + tweet: Partial +): Partial { + const urls = tweet.entities?.urls + let text = tweet.text + if (text && urls) { + for (const url of urls) { + if (!url.expanded_url || !url.url) continue + text = text!.replaceAll(url.url, url.expanded_url!) + } + } + + return { + ...omit( + tweet, + 'conversation_id', + 'public_metrics', + 'created_at', + 'entities', + 'possibly_sensitive' + ), + text + } +} + +export function getPrunedTwitterUser( + twitterUser: Partial +): Partial { + const urls = twitterUser.entities?.description?.urls + let description = twitterUser.description + if (description && urls) { + for (const url of urls) { + if (!url.expanded_url || !url.url) continue + description = description!.replaceAll(url.url, url.expanded_url!) + } + } + + return { + ...omit( + twitterUser, + 'public_metrics', + 'created_at', + 'verified', + 'protected', + 'url', + 'entities' + ), + description + } +} diff --git a/src/services/weather-client.ts b/src/services/weather-client.ts new file mode 100644 index 000000000..cde8dbd58 --- /dev/null +++ b/src/services/weather-client.ts @@ -0,0 +1,134 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv } from '../utils.js' + +export namespace weatherapi { + export const BASE_URL = 'https://api.weatherapi.com/v1' + + export interface CurrentWeatherResponse { + current: CurrentWeather + location: WeatherLocation + } + + export interface CurrentWeather { + cloud: number + condition: WeatherCondition + feelslike_c: number + feelslike_f: number + gust_kph: number + gust_mph: number + humidity: number + is_day: number + last_updated: string + last_updated_epoch: number + precip_in: number + precip_mm: number + pressure_in: number + pressure_mb: number + temp_c: number + temp_f: number + uv: number + vis_km: number + vis_miles: number + wind_degree: number + wind_dir: string + wind_kph: number + wind_mph: number + } + + export interface WeatherCondition { + code: number + icon: string + text: string + } + + export interface WeatherLocation { + country: string + lat: number + localtime: string + localtime_epoch: number + lon: number + name: string + region: string + tz_id: string + } + + export interface WeatherIPInfoResponse { + ip: string + type: string + continent_code: string + continent_name: string + country_code: string + country_name: string + is_eu: string + geoname_id: number + city: string + region: string + lat: number + lon: number + tz_id: string + localtime_epoch: number + localtime: string + } +} + +/** + * Simple Weather API client for accessing weather data based on location. + * + * @see https://www.weatherapi.com + */ +export class WeatherClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiKey: string + protected readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('WEATHER_API_KEY'), + apiBaseUrl = weatherapi.BASE_URL, + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'WeatherClient missing required "apiKey" (defaults to "WEATHER_API_KEY")' + ) + super() + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ prefixUrl: apiBaseUrl }) + } + + @aiFunction({ + name: 'get_current_weather', + description: 'Gets info about the current weather at a given location.', + inputSchema: z.object({ + q: z + .string() + .describe( + 'Location to get the weather for. Can be a city name, zipcode, IP address, or lat/lng coordinates. Example: "London"' + ) + }) + }) + async getCurrentWeather(queryOrOptions: string | { q: string }) { + const options = + typeof queryOrOptions === 'string' + ? { q: queryOrOptions } + : queryOrOptions + + return this.ky + .get('current.json', { + searchParams: { + key: this.apiKey, + ...options + } + }) + .json() + } +} diff --git a/src/services/wikipedia-client.ts b/src/services/wikipedia-client.ts new file mode 100644 index 000000000..7548d8e3c --- /dev/null +++ b/src/services/wikipedia-client.ts @@ -0,0 +1,187 @@ +import defaultKy, { type KyInstance } from 'ky' +import pThrottle from 'p-throttle' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv, throttleKy } from '../utils.js' + +export namespace wikipedia { + // Allow up to 200 requests per second by default. + export const throttle = pThrottle({ + limit: 200, + interval: 1000 + }) + + export interface SearchOptions { + query: string + limit?: number + } + + export interface PageSearchResponse { + pages: Page[] + } + + export interface Page { + id: number + key: string + title: string + matched_title: null + excerpt: string + description: null | string + thumbnail: Thumbnail | null + } + + export interface Thumbnail { + url: string + width: number + height: number + mimetype: string + duration: null + } + + export interface PageSummaryOptions { + title: string + redirect?: boolean + acceptLanguage?: string + } + + export interface PageSummary { + ns?: number + index?: number + type: string + title: string + displaytitle: string + namespace: { id: number; text: string } + wikibase_item: string + titles: { canonical: string; normalized: string; display: string } + pageid: number + thumbnail: { + source: string + width: number + height: number + } + originalimage: { + source: string + width: number + height: number + } + lang: string + dir: string + revision: string + tid: string + timestamp: string + description: string + description_source: string + content_urls: { + desktop: { + page: string + revisions: string + edit: string + talk: string + } + mobile: { + page: string + revisions: string + edit: string + talk: string + } + } + extract: string + extract_html: string + normalizedtitle?: string + coordinates?: { + lat: number + lon: number + } + } +} + +/** + * Basic Wikipedia API client for searching wiki pages and resolving page data. + * + * @see https://www.mediawiki.org/wiki/API + */ +export class WikipediaClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly apiBaseUrl: string + protected readonly apiUserAgent: string + + constructor({ + apiBaseUrl = getEnv('WIKIPEDIA_API_BASE_URL') ?? + 'https://en.wikipedia.org/api/rest_v1', + apiUserAgent = getEnv('WIKIPEDIA_API_USER_AGENT') ?? + 'Agentic (https://github.com/transitive-bullshit/agentic)', + throttle = true, + ky = defaultKy + }: { + apiBaseUrl?: string + apiUserAgent?: string + throttle?: boolean + ky?: KyInstance + } = {}) { + assert(apiBaseUrl, 'WikipediaClient missing required "apiBaseUrl"') + assert(apiUserAgent, 'WikipediaClient missing required "apiUserAgent"') + super() + + this.apiBaseUrl = apiBaseUrl + this.apiUserAgent = apiUserAgent + + const throttledKy = throttle ? throttleKy(ky, wikipedia.throttle) : ky + + this.ky = throttledKy.extend({ + headers: { + 'api-user-agent': apiUserAgent + } + }) + } + + @aiFunction({ + name: 'wikipedia_search', + description: 'Searches Wikipedia for pages matching the given query.', + inputSchema: z.object({ + query: z.string().describe('Search query') + }) + }) + async search({ query, ...opts }: wikipedia.SearchOptions) { + return ( + // https://www.mediawiki.org/wiki/API:REST_API + this.ky + .get('https://en.wikipedia.org/w/rest.php/v1/search/page', { + searchParams: { q: query, ...opts } + }) + .json() + ) + } + + @aiFunction({ + name: 'wikipedia_get_page_summary', + description: 'Gets a summary of the given Wikipedia page.', + inputSchema: z.object({ + title: z.string().describe('Wikipedia page title'), + acceptLanguage: z + .string() + .optional() + .default('en-us') + .describe('Locale code for the language to use.') + }) + }) + async getPageSummary({ + title, + acceptLanguage = 'en-us', + redirect = true, + ...opts + }: wikipedia.PageSummaryOptions) { + title = title.trim().replaceAll(' ', '_') + + // https://en.wikipedia.org/api/rest_v1/ + return this.ky + .get(`page/summary/${title}`, { + prefixUrl: this.apiBaseUrl, + searchParams: { redirect, ...opts }, + headers: { + 'accept-language': acceptLanguage + } + }) + .json() + } +} diff --git a/src/services/wolfram-alpha-client.ts b/src/services/wolfram-alpha-client.ts new file mode 100644 index 000000000..980d51109 --- /dev/null +++ b/src/services/wolfram-alpha-client.ts @@ -0,0 +1,90 @@ +import defaultKy, { type KyInstance } from 'ky' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { assert, getEnv } from '../utils.js' + +export namespace wolframalpha { + export const API_BASE_URL = 'https://www.wolframalpha.com/api/' + + export const AskWolframAlphaOptionsSchema = z.object({ + input: z.string().describe('english query'), + maxchars: z + .number() + .int() + .positive() + .default(6000) + .optional() + .describe('max characters to generate in the response') + }) + export type AskWolframAlphaOptions = z.infer< + typeof AskWolframAlphaOptionsSchema + > +} + +/** + * Wolfram Alpha LLM API client for answering computational, mathematical, and + * scientific questions. + * + * @see https://products.wolframalpha.com/llm-api/documentation + */ +export class WolframAlphaClient extends AIFunctionsProvider { + protected readonly ky: KyInstance + protected readonly appId: string + protected readonly apiBaseUrl: string + + constructor({ + appId = getEnv('WOLFRAM_APP_ID'), + apiBaseUrl = wolframalpha.API_BASE_URL, + ky = defaultKy + }: { + appId?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + appId, + 'WolframAlphaClient missing required "appId" (defaults to "WOLFRAM_APP_ID")' + ) + super() + + this.appId = appId + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ + prefixUrl: apiBaseUrl, + headers: { + Authorization: `Bearer ${appId}` + } + }) + } + + @aiFunction({ + name: 'ask_wolfram_alpha', + description: ` +- WolframAlpha understands natural language queries about entities in chemistry, physics, geography, history, art, astronomy, and more. +- WolframAlpha performs mathematical calculations, date and unit conversions, formula solving, etc. +- Convert inputs to simplified keyword queries whenever possible (e.g. convert "how many people live in France" to "France population"). +- Send queries in English only; translate non-English queries before sending, then respond in the original language. +- ALWAYS use this exponent notation: \`6*10^14\`, NEVER \`6e14\`. +- ALWAYS use proper Markdown formatting for all math, scientific, and chemical formulas, symbols, etc.: '$$\n[expression]\n$$' for standalone cases and '( [expression] )' when inline. +- Use ONLY single-letter variable names, with or without integer subscript (e.g., n, n1, n_1). +- Use named physical constants (e.g., 'speed of light') without numerical substitution. +- Include a space between compound units (e.g., "Ω m" for "ohm*meter"). +- To solve for a variable in an equation with units, consider solving a corresponding equation without units; exclude counting units (e.g., books), include genuine units (e.g., kg). +- If a WolframAlpha result is not relevant to the query: + - If Wolfram provides multiple 'Assumptions' for a query, choose the more relevant one(s) without explaining the initial result. If you are unsure, ask the user to choose. + - Re-send the exact same 'input' with NO modifications, and add the 'assumption' parameter, formatted as a list, with the relevant values. + - ONLY simplify or rephrase the initial query if a more relevant 'Assumption' or other input suggestions are not provided. +`.trim(), + inputSchema: wolframalpha.AskWolframAlphaOptionsSchema + }) + async ask(queryOrOptions: string | wolframalpha.AskWolframAlphaOptions) { + const options = + typeof queryOrOptions === 'string' + ? { input: queryOrOptions } + : queryOrOptions + + return this.ky.get('v1/llm-api', { searchParams: { ...options } }).text() + } +} diff --git a/src/tools/calculator.ts b/src/tools/calculator.ts new file mode 100644 index 000000000..7f7bf7ad5 --- /dev/null +++ b/src/tools/calculator.ts @@ -0,0 +1,25 @@ +import { Parser } from 'expr-eval' +import { z } from 'zod' + +import { createAIFunction } from '../create-ai-function.js' + +// TODO: consider using https://github.com/josdejong/mathjs +// TODO: ensure `expr` is sanitized to not run arbitrary code + +export const CalculatorInputSchema = z.object({ + expr: z.string().describe('mathematical expression to evaluate') +}) +export type CalculatorInput = z.infer + +export const calculator = createAIFunction( + { + name: 'calculator', + description: + 'Computes the result of simple mathematical expressions. Handles basic arithmetic operations like addition, subtraction, multiplication, division, exponentiation, and common functions like sin, cos, abs, exp, and random.', + inputSchema: CalculatorInputSchema + }, + async (input: CalculatorInput) => { + const result: number = Parser.evaluate(input.expr) + return result + } +) diff --git a/src/tools/e2b.ts b/src/tools/e2b.ts new file mode 100644 index 000000000..f4a20a15f --- /dev/null +++ b/src/tools/e2b.ts @@ -0,0 +1,56 @@ +import { CodeInterpreter, type ProcessMessage } from '@e2b/code-interpreter' +import { z } from 'zod' + +import { createAIFunction } from '../create-ai-function.js' +import { getEnv } from '../utils.js' + +/** + * E2B Python code interpreter sandbox. + * + * @see https://e2b.dev + */ +export const e2b = createAIFunction( + { + name: 'execute_python', + description: ` +Execute python code in a Jupyter notebook cell and returns any result, stdout, stderr, display_data, and error. + +- code has access to the internet and can make api requests +- code has access to the filesystem and can read/write files +- coce can install any pip package (if it exists) if you need to, but the usual packages for data analysis are already preinstalled +- code uses python3 +- code is executed in a secure sandbox environment, so you don't need to worry about safety + `.trim(), + inputSchema: z.object({ + code: z + .string() + .describe('Python code to execute in a single notebook cell.') + }) + }, + async ({ code }) => { + const sandbox = await CodeInterpreter.create({ + apiKey: getEnv('E2B_API_KEY') + }) + + try { + const exec = await sandbox.notebook.execCell(code, { + onStderr: (msg: ProcessMessage) => { + console.warn('[Code Interpreter stderr]', msg) + }, + + onStdout: (stdout: ProcessMessage) => { + console.log('[Code Interpreter stdout]', stdout) + } + }) + + if (exec.error) { + console.error('[Code Interpreter error]', exec.error) + throw new Error(exec.error.value) + } + + return exec.results.map((result) => result.toJSON()) + } finally { + await sandbox.close() + } + } +) diff --git a/src/tools/search-and-crawl.ts b/src/tools/search-and-crawl.ts new file mode 100644 index 000000000..db5866ad4 --- /dev/null +++ b/src/tools/search-and-crawl.ts @@ -0,0 +1,138 @@ +import pMap from 'p-map' +import { z } from 'zod' + +import { aiFunction, AIFunctionsProvider } from '../fns.js' +import { type diffbot, DiffbotClient } from '../services/diffbot-client.js' +import { SerpAPIClient } from '../services/serpapi-client.js' +import { isValidCrawlableUrl, normalizeUrl } from '../url-utils.js' +import { omit, pick } from '../utils.js' + +// TODO: allow `search` tool to support other search clients +// (e.g. Bing, Exa, Searxng, Serper, Tavily) + +export class SearchAndCrawl extends AIFunctionsProvider { + readonly serpapi: SerpAPIClient + readonly diffbot: DiffbotClient + + constructor(opts: { serpapi?: SerpAPIClient; diffbot?: DiffbotClient } = {}) { + super() + + this.serpapi = opts.serpapi ?? new SerpAPIClient() + this.diffbot = opts.diffbot ?? new DiffbotClient() + } + + @aiFunction({ + name: 'search_and_crawl', + description: + 'Uses Google to search the web, crawls the results, and then summarizes the most relevant results. Useful for creating in-depth summaries of topics along with sources.', + inputSchema: z.object({ + query: z.string().describe('search query') + }) + }) + async searchAndCrawl({ + query, + numSearchResults = 3, + maxCrawlDepth = 1, + maxListItems = 3 + }: { + query: string + numSearchResults?: number + maxCrawlDepth?: number + maxListItems?: number + }) { + const crawledUrls = new Set() + + const crawlAndScrape = async ( + url: string | undefined, + { + depth = 0 + }: { + depth?: number + } + ): Promise => { + try { + if (!url) return [] + if (!isValidCrawlableUrl(url)) return [] + if (crawledUrls.has(url)) return [] + + const normalizedUrl = normalizeUrl(url) + if (!normalizedUrl) return [] + if (crawledUrls.has(normalizedUrl)) return [] + + crawledUrls.add(url) + crawledUrls.add(normalizedUrl) + + console.log('\n\n') + const scrapeResult = await this.diffbot.analyzeUrl({ url }) + console.log( + `SearchAndCrawl depth ${depth} - "${url}"`, + pick(scrapeResult, 'type', 'title') + ) + + if (scrapeResult.type !== 'list') { + return [scrapeResult] + } + + if (depth >= maxCrawlDepth) { + return [scrapeResult] + } + + const object = scrapeResult.objects?.[0] + if (!object) return [scrapeResult] + + const items = object.items + ?.filter((item) => item.link) + .slice(0, maxListItems) + if (!items?.length) return [scrapeResult] + + const innerScrapeResults = ( + await pMap( + items, + async (item) => { + const innerScrapeResult = await crawlAndScrape(item.link, { + depth: depth + 1 + }) + return innerScrapeResult + }, + { + concurrency: 4 + } + ) + ).flat() + + return innerScrapeResults + } catch (err) { + console.warn('crawlAndScrape error', url, err) + return [] + } + } + + const searchResponse = await this.serpapi.search({ + q: query, + num: numSearchResults + }) + + console.log(`SearchAndCrawl search results "${query}"`, searchResponse) + const scrapeResults = ( + await pMap( + (searchResponse.organic_results || []).slice(0, numSearchResults), + async (searchResult) => { + return crawlAndScrape(searchResult.link, { + depth: 0 + }) + }, + { + concurrency: 5 + } + ) + ).flat() + + const output = { + ...omit(searchResponse, 'organic_results'), + scrape_results: scrapeResults + } + + console.log(`SearchAndCrawl response for query "${query}"`, output) + return output + } +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 000000000..f4e0b04cd --- /dev/null +++ b/src/types.ts @@ -0,0 +1,62 @@ +import type { Jsonifiable } from 'type-fest' +import type { z } from 'zod' + +import type { AIFunctionSet } from './ai-function-set.js' +import type { AIFunctionsProvider } from './fns.js' +import type { Msg } from './message.js' + +export type { Msg } from './message.js' +export type { KyInstance } from 'ky' +export type { ThrottledFunction } from 'p-throttle' + +export type Nullable = T | null + +export type DeepNullable = T extends object + ? { [K in keyof T]: DeepNullable } + : Nullable + +export type MaybePromise = T | Promise + +export type RelaxedJsonifiable = Jsonifiable | Record + +export interface AIFunctionSpec { + name: string + description: string + parameters: Record +} + +export interface AIToolSpec { + type: 'function' + function: AIFunctionSpec +} + +/** The implementation of the function, with arg parsing and validation. */ +export type AIFunctionImpl = Omit< + (input: string | Msg) => MaybePromise, + 'name' | 'toString' | 'arguments' | 'caller' | 'prototype' | 'length' +> + +export type AIFunctionLike = AIFunctionsProvider | AIFunction | AIFunctionSet + +/** + * A function meant to be used with LLM function calling. + */ +export interface AIFunction< + InputSchema extends z.ZodObject = z.ZodObject, + Return = any +> { + (input: string | Msg): MaybePromise + + /** The Zod schema for the input object. */ + inputSchema: InputSchema + + /** Parse the function arguments from a message. */ + parseInput(input: string | Msg): z.infer + + /** The function spec for the OpenAI API `functions` property. */ + spec: AIFunctionSpec + + /** The underlying function implementation without any arg parsing or validation. */ + // TODO: this `any` shouldn't be necessary, but it is for `createAIFunction` results to be assignable to `AIFunctionLike` + impl: (params: z.infer | any) => MaybePromise +} diff --git a/src/url-utils.test.ts b/src/url-utils.test.ts new file mode 100644 index 000000000..3523821de --- /dev/null +++ b/src/url-utils.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test } from 'vitest' + +import { normalizeUrl } from './url-utils.js' + +describe('normalizeUrl', () => { + test('valid urls', async () => { + expect(normalizeUrl('https://www.google.com')).toBe( + 'https://www.google.com' + ) + expect(normalizeUrl('//www.google.com')).toBe('https://www.google.com') + expect(normalizeUrl('https://www.google.com/foo?')).toBe( + 'https://www.google.com/foo' + ) + expect(normalizeUrl('https://www.google.com/?foo=bar&dog=cat')).toBe( + 'https://www.google.com/?dog=cat&foo=bar' + ) + expect(normalizeUrl('https://google.com/abc/123//')).toBe( + 'https://google.com/abc/123' + ) + }) + + test('invalid urls', async () => { + expect(normalizeUrl('/foo')).toBe(null) + expect(normalizeUrl('/foo/bar/baz')).toBe(null) + expect(normalizeUrl('://foo.com')).toBe(null) + expect(normalizeUrl('foo')).toBe(null) + expect(normalizeUrl('')).toBe(null) + expect(normalizeUrl(undefined as unknown as string)).toBe(null) + expect(normalizeUrl(null as unknown as string)).toBe(null) + }) +}) diff --git a/src/url-utils.ts b/src/url-utils.ts new file mode 100644 index 000000000..aabb74982 --- /dev/null +++ b/src/url-utils.ts @@ -0,0 +1,88 @@ +import isRelativeUrlImpl from 'is-relative-url' +import normalizeUrlImpl, { + type Options as NormalizeUrlOptions +} from 'normalize-url' +import QuickLRU from 'quick-lru' + +import { hashObject } from './utils.js' + +const protocolAllowList = new Set(['https:', 'http:']) +const normalizedUrlCache = new QuickLRU({ + maxSize: 4000 +}) + +export function isValidCrawlableUrl(url: string): boolean { + try { + if (!url || isRelativeUrl(url)) { + return false + } + + const parsedUrl = new URL(url) + if (!protocolAllowList.has(parsedUrl.protocol)) { + return false + } + + const normalizedUrl = normalizeUrl(url) + if (!normalizedUrl) { + return false + } + + return true + } catch { + return false + } +} + +export function isRelativeUrl(url: string): boolean { + if (!url || typeof url !== 'string') return false + + return isRelativeUrlImpl(url) && !url.startsWith('//') +} + +export function normalizeUrl( + url: string, + options?: NormalizeUrlOptions +): string | null { + let normalizedUrl: string | null | undefined + + if (!url || isRelativeUrl(url)) { + return null + } + + const opts = { + stripWWW: false, + defaultProtocol: 'https', + normalizeProtocol: true, + forceHttps: false, + stripHash: false, + stripTextFragment: true, + removeQueryParameters: [/^utm_\w+/i, 'ref', 'ref_src'], + removeTrailingSlash: true, + removeSingleSlash: true, + removeExplicitPort: true, + sortQueryParameters: true, + ...options + } as Required + + const optionsHash = hashObject(opts) + const cacheKey = `${url}-${optionsHash}` + + try { + normalizedUrl = normalizedUrlCache.get(cacheKey) + + if (normalizedUrl !== undefined) { + return normalizedUrl + } + + normalizedUrl = normalizeUrlImpl(url, opts) + if (!normalizeUrl) { + normalizedUrl = null + } + } catch { + // ignore invalid urls + normalizedUrl = null + } + + normalizedUrlCache.set(cacheKey, normalizedUrl!) + return normalizedUrl +} diff --git a/src/utils.test.ts b/src/utils.test.ts new file mode 100644 index 000000000..b234243ff --- /dev/null +++ b/src/utils.test.ts @@ -0,0 +1,106 @@ +import ky from 'ky' +import pThrottle from 'p-throttle' +import { describe, expect, test } from 'vitest' + +import { mockKyInstance } from './_utils.js' +import { + omit, + pick, + sanitizeSearchParams, + stringifyForModel, + throttleKy +} from './utils.js' + +test('pick', () => { + expect(pick({ a: 1, b: 2, c: 3 }, 'a', 'c')).toEqual({ a: 1, c: 3 }) + expect( + pick({ a: { b: 'foo' }, d: -1, foo: null } as any, 'b', 'foo') + ).toEqual({ foo: null }) +}) + +test('omit', () => { + expect(omit({ a: 1, b: 2, c: 3 }, 'a', 'c')).toEqual({ b: 2 }) + expect( + omit({ a: { b: 'foo' }, d: -1, foo: null } as any, 'b', 'foo') + ).toEqual({ a: { b: 'foo' }, d: -1 }) +}) + +test('sanitizeSearchParams', () => { + expect( + sanitizeSearchParams({ a: 1, b: undefined, c: 13 }).toString() + ).toMatchSnapshot() + + expect(sanitizeSearchParams({ a: [1, 2, 3] }).toString()).toMatchSnapshot() + + expect( + sanitizeSearchParams({ b: ['a', 'b'], foo: true }).toString() + ).toMatchSnapshot() + + expect( + sanitizeSearchParams({ b: [false, true, false] }).toString() + ).toMatchSnapshot() + + expect( + sanitizeSearchParams({ + flag: ['foo', 'bar', 'baz'], + token: 'test' + }).toString() + ).toMatchSnapshot() + + expect(sanitizeSearchParams({}).toString()).toMatchSnapshot() + + expect(sanitizeSearchParams({ a: [] }).toString()).toMatchSnapshot() +}) + +test( + 'throttleKy should rate-limit requests to ky properly', + async () => { + const interval = 1000 + const throttle = pThrottle({ + limit: 1, + interval, + strict: true + }) + + const ky2 = mockKyInstance(throttleKy(ky, throttle)) + + const url = 'https://httpbin.org/get' + + for (let i = 0; i < 10; i++) { + const before = Date.now() + const res = await ky2.get(url) + const after = Date.now() + + const duration = after - before + // console.log(duration, res.status) + expect(res.status).toBe(200) + + // leave a bit of wiggle room for the interval + if (i > 0) { + expect(duration >= interval - interval / 5).toBeTruthy() + } + } + }, + { + timeout: 60_000 + } +) + +describe('stringifyForModel', () => { + test('handles basic objects', () => { + const input = { + foo: 'bar', + nala: ['is', 'cute'], + kittens: null, + cats: undefined, + paws: 4.3 + } + const result = stringifyForModel(input) + expect(result).toEqual(JSON.stringify(input, null)) + }) + + test('handles empty input', () => { + const result = stringifyForModel() + expect(result).toEqual('') + }) +}) diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 000000000..3cd4b82b6 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,160 @@ +import type { Jsonifiable } from 'type-fest' +import dedent from 'dedent' +import hashObjectImpl, { type Options as HashObjectOptions } from 'hash-object' + +import type * as types from './types.js' + +export { assert } from './assert.js' +export { default as delay } from 'delay' + +/** + * From `inputObj`, create a new object that does not include `keys`. + * + * @example + * ```js + * omit({ a: 1, b: 2, c: 3 }, 'a', 'c') // { b: 2 } + * ``` + */ +export const omit = < + T extends Record | object, + K extends keyof T = keyof T +>( + inputObj: T, + ...keys: K[] +): Omit => { + const keysSet = new Set(keys) + return Object.fromEntries( + Object.entries(inputObj).filter(([k]) => !keysSet.has(k as any)) + ) as any +} + +/** + * From `inputObj`, create a new object that only includes `keys`. + * + * @example + * ```js + * pick({ a: 1, b: 2, c: 3 }, 'a', 'c') // { a: 1, c: 3 } + * ``` + */ +export const pick = < + T extends Record | object, + K extends keyof T = keyof T +>( + inputObj: T, + ...keys: K[] +): Pick => { + const keysSet = new Set(keys) + return Object.fromEntries( + Object.entries(inputObj).filter(([k]) => keysSet.has(k as any)) + ) as any +} + +export function pruneUndefined>( + obj: T +): NonNullable<{ [K in keyof T]: Exclude }> { + return Object.fromEntries( + Object.entries(obj).filter(([, value]) => value !== undefined) + ) as NonNullable +} + +export function pruneNullOrUndefined>( + obj: T +): NonNullable<{ [K in keyof T]: Exclude }> { + return Object.fromEntries( + Object.entries(obj).filter( + ([, value]) => value !== undefined && value !== null + ) + ) as NonNullable +} + +export function getEnv(name: string): string | undefined { + try { + return typeof process !== 'undefined' + ? // eslint-disable-next-line no-process-env + process.env?.[name] + : undefined + } catch { + return undefined + } +} + +/** + * Function that does nothing. + */ +export const noop = () => undefined + +/** + * Throttles HTTP requests made by a ky instance. + * + * Very useful for enforcing rate limits. + */ +export function throttleKy( + ky: types.KyInstance, + throttleFn: ( + function_: (...args_: Arguments) => ReturnValue + ) => types.ThrottledFunction<(...args_: Arguments) => ReturnValue> +) { + return ky.extend({ + hooks: { + beforeRequest: [throttleFn(noop)] + } + }) +} + +/** + * Creates a new `URLSearchParams` object with all values coerced to strings + * that correctly handles arrays of values as repeated keys. + */ +export function sanitizeSearchParams( + searchParams: Record< + string, + string | number | boolean | string[] | number[] | boolean[] | undefined + > +): URLSearchParams { + return new URLSearchParams( + Object.entries(searchParams).flatMap(([key, value]) => { + if (key === undefined || value === undefined) { + return [] + } + + if (Array.isArray(value)) { + return value.map((v) => [key, String(v)]) + } + + return [[key, String(value)]] + }) as [string, string][] + ) +} + +/** + * Stringifies a JSON value in a way that's optimized for use with LLM prompts. + */ +export function stringifyForModel(jsonObject?: Jsonifiable): string { + if (jsonObject === undefined) { + return '' + } + + if (typeof jsonObject === 'string') { + return jsonObject + } + + return JSON.stringify(jsonObject, null, 0) +} + +const dedenter = dedent.withOptions({ escapeSpecialCharacters: true }) + +/** + * Clean a string by removing extra newlines and indentation. + * + * @see: https://github.com/dmnd/dedent + */ +export function cleanStringForModel(text: string): string { + return dedenter(text).trim() +} + +export function hashObject( + object: Record, + options?: HashObjectOptions +): string { + return hashObjectImpl(object, { algorithm: 'sha256', ...options }) +} diff --git a/src/zod-to-json-schema.test.ts b/src/zod-to-json-schema.test.ts new file mode 100644 index 000000000..24f8c2fa0 --- /dev/null +++ b/src/zod-to-json-schema.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from 'vitest' +import { z } from 'zod' + +import { zodToJsonSchema } from './zod-to-json-schema.js' + +describe('zodToJsonSchema', () => { + it('handles basic objects', () => { + const params = zodToJsonSchema( + z.object({ + name: z.string().min(1).describe('Name of the person'), + age: z.number().int().optional().describe('Age in years') + }) + ) + + expect(params).toEqual({ + additionalProperties: false, + type: 'object', + required: ['name'], + properties: { + name: { + type: 'string', + description: 'Name of the person', + minLength: 1 + }, + age: { + type: 'integer', + description: 'Age in years' + } + } + }) + }) + + it('handles enums and unions', () => { + const params = zodToJsonSchema( + z.object({ + name: z.string().min(1).describe('Name of the person'), + sexEnum: z.enum(['male', 'female']), + sexUnion: z.union([z.literal('male'), z.literal('female')]) + }) + ) + + expect(params).toEqual({ + additionalProperties: false, + type: 'object', + required: ['name', 'sexEnum', 'sexUnion'], + properties: { + name: { + type: 'string', + description: 'Name of the person', + minLength: 1 + }, + sexEnum: { + type: 'string', + enum: ['male', 'female'] + }, + sexUnion: { + type: 'string', + enum: ['male', 'female'] + } + } + }) + }) +}) diff --git a/src/zod-to-json-schema.ts b/src/zod-to-json-schema.ts new file mode 100644 index 000000000..30a13077d --- /dev/null +++ b/src/zod-to-json-schema.ts @@ -0,0 +1,16 @@ +import type { z } from 'zod' +import { zodToJsonSchema as zodToJsonSchemaImpl } from 'zod-to-json-schema' + +import { omit } from './utils.js' + +/** Generate a JSON Schema from a Zod schema. */ +export function zodToJsonSchema(schema: z.ZodType): Record { + return omit( + zodToJsonSchemaImpl(schema, { $refStrategy: 'none' }), + '$schema', + 'default', + 'definitions', + 'description', + 'markdownDescription' + ) +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..c47b9c4ea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ESNext"], + "esModuleInterop": true, + "skipLibCheck": true, + "verbatimModuleSyntax": true, + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "useDefineForClassFields": true, + "jsx": "preserve", + + // NOTE: these are deprecated + // "experimentalDecorators": true, + // "emitDecoratorMetadata": true, + + "strict": true, + "noUncheckedIndexedAccess": true, + "forceConsistentCasingInFileNames": true, + + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "sourceMap": true + }, + "include": ["src"], + "ts-node": { + "transpileOnly": true + } +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 000000000..672ef7213 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'tsup' + +export default defineConfig([ + { + entry: [ + 'src/index.ts', + 'src/sdks/ai-sdk.ts', + 'src/sdks/dexter.ts', + 'src/sdks/genkit.ts', + 'src/sdks/langchain.ts', + 'src/sdks/llamaindex.ts', + 'src/services/twitter/index.ts', + 'src/tools/calculator.ts', + 'src/tools/e2b.ts' + ], + outDir: 'dist', + target: 'node18', + platform: 'node', + format: ['esm'], + splitting: false, + sourcemap: true, + minify: false, + shims: true, + dts: true + } +]) diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 000000000..9bcd5c941 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + esbuild: { + target: 'es2022' + } +})