diff --git a/integrations/browser/integration.definition.ts b/integrations/browser/integration.definition.ts index 22c9edefe04..89ab762eab3 100644 --- a/integrations/browser/integration.definition.ts +++ b/integrations/browser/integration.definition.ts @@ -5,7 +5,7 @@ import { actionDefinitions } from 'src/definitions/actions' export default new IntegrationDefinition({ name: 'browser', title: 'Browser', - version: '0.7.0', + version: '0.8.0', description: 'Capture screenshots and retrieve web page content with metadata for automated browsing and data extraction.', readme: 'hub.md', diff --git a/integrations/browser/package.json b/integrations/browser/package.json index ecc9a9428ea..f243c38597e 100644 --- a/integrations/browser/package.json +++ b/integrations/browser/package.json @@ -8,6 +8,7 @@ "private": true, "dependencies": { "@botpress/sdk": "workspace:*", + "@mendable/firecrawl-js": "^4.3.8", "axios": "^1.7.2" }, "devDependencies": { diff --git a/integrations/browser/src/actions/browse-pages.ts b/integrations/browser/src/actions/browse-pages.ts index c579f82e2a1..e46ecd47c34 100644 --- a/integrations/browser/src/actions/browse-pages.ts +++ b/integrations/browser/src/actions/browse-pages.ts @@ -1,24 +1,8 @@ -import { IntegrationLogger } from '@botpress/sdk' -import axios from 'axios' +import { IntegrationLogger, RuntimeError } from '@botpress/sdk' +import Firecrawl from '@mendable/firecrawl-js' import { FullPage } from 'src/definitions/actions' import * as bp from '.botpress' -type FireCrawlResponse = { - success: boolean - data: { - markdown: string - metadata: { - ogLocaleAlternate: string[] - favicon?: string - title?: string | string[] | null - description?: string | string[] | null - sourceURL: string - error: string | null - statusCode: number - } - } -} - const COST_PER_PAGE = 0.0015 const fixOutput = (val: unknown): string => { @@ -37,37 +21,35 @@ const getPageContent = async (props: { timeout?: number maxAge?: number }): Promise => { + const firecrawl = new Firecrawl({ apiKey: bp.secrets.FIRECRAWL_API_KEY }) + const startTime = Date.now() - const { data: result } = await axios.post( - 'https://api.firecrawl.dev/v1/scrape', - { - url: props.url, + + try { + const result = await firecrawl.scrape(props.url, { + fastMode: true, onlyMainContent: true, + maxAge: 60 * 60 * 24 * 7, // 1 week + removeBase64Images: true, waitFor: props.waitFor, timeout: props.timeout, - maxAge: 60 * 60 * 24 * 7, // 1 week - }, - { - headers: { - Authorization: `Bearer ${bp.secrets.FIRECRAWL_API_KEY}`, - }, - } - ) - - const { metadata, markdown } = result.data + formats: ['markdown', 'rawHtml'], + storeInCache: true, + }) - props.logger.forBot().info(`Browsing ${props.url} took ${Date.now() - startTime}ms`, { - size: markdown.length, - statusCode: metadata.statusCode, - error: metadata.error, - }) + props.logger.forBot().debug(`Firecrawl API call took ${Date.now() - startTime}ms for url: ${props.url}`) - return { - url: props.url, - content: markdown, - favicon: fixOutput(metadata.favicon), - title: fixOutput(metadata.title), - description: fixOutput(metadata.description), + return { + url: props.url, + content: result.markdown!, + raw: result.rawHtml!, + favicon: fixOutput(result.metadata?.favicon), + title: fixOutput(result.metadata?.title), + description: fixOutput(result.metadata?.description), + } + } catch (err) { + props.logger.error('There was an error while calling Firecrawl API.', err) + throw new RuntimeError(`There was an error while browsing the page: ${props.url}`) } } diff --git a/integrations/browser/src/actions/discover-urls.ts b/integrations/browser/src/actions/discover-urls.ts index 700ae0c77ba..2b4eff9942b 100644 --- a/integrations/browser/src/actions/discover-urls.ts +++ b/integrations/browser/src/actions/discover-urls.ts @@ -1,6 +1,6 @@ import { RuntimeError } from '@botpress/client' import { IntegrationLogger, z, ZodIssueCode } from '@botpress/sdk' -import axios from 'axios' +import Firecrawl from '@mendable/firecrawl-js' import { isValidGlob, matchGlob } from '../utils/globs' import * as bp from '.botpress' @@ -8,28 +8,6 @@ const LAMBDA_TIMEOUT = 55_000 const COST_PER_FIRECRAWL_MAP = 0.001 -type FirecrawlMapInput = { - /** The base URL to start crawling from */ - url: string - /** Search query to use for mapping. During the Alpha phase, the 'smart' part of the search functionality is limited to 1000 search results. However, if map finds more results, there is no limit applied. */ - search?: string - /** Ignore the website sitemap when crawling */ - ignoreSitemap?: boolean - /** Only return links found in the website sitemap */ - sitemapOnly?: boolean - /** In milliseconds */ - timeout?: number - /** Max 30_000 */ - limit?: number - /** Defaults to true */ - includeSubdomains?: boolean -} - -type FireCrawlResponse = { - success: boolean - links: string[] -} - type StopReason = Awaited>['stopReason'] export const urlSchema = z.string().transform((url, ctx) => { @@ -149,25 +127,16 @@ class Accumulator { } const firecrawlMap = async (props: { url: string; logger: IntegrationLogger; timeout: number }): Promise => { - const { data: result } = await axios.post( - 'https://api.firecrawl.dev/v1/map', - { - url: props.url, - ignoreSitemap: false, - includeSubdomains: true, - sitemapOnly: false, - limit: 10_000, - timeout: Math.max(1000, props.timeout - 2000), - } satisfies FirecrawlMapInput, - { - signal: AbortSignal.timeout(Math.max(1000, props.timeout - 1000)), - headers: { - Authorization: `Bearer ${bp.secrets.FIRECRAWL_API_KEY}`, - }, - } - ) + const firecrawl = new Firecrawl({ apiKey: bp.secrets.FIRECRAWL_API_KEY }) + + const result = await firecrawl.map(props.url, { + sitemap: 'include', + limit: 10_000, + timeout: Math.max(1000, props.timeout - 2000), + includeSubdomains: true, + }) - return result.links + return result.links.map((x) => x.url) } export const discoverUrls: bp.IntegrationProps['actions']['discoverUrls'] = async ({ input, logger, metadata }) => { diff --git a/integrations/browser/src/definitions/actions.ts b/integrations/browser/src/definitions/actions.ts index 8235c813a5b..f4644825311 100644 --- a/integrations/browser/src/definitions/actions.ts +++ b/integrations/browser/src/definitions/actions.ts @@ -30,6 +30,7 @@ const captureScreenshot: ActionDefinition = { const fullPage = z.object({ url: z.string(), content: z.string(), + raw: z.string(), favicon: z.string().optional(), title: z.string().optional(), description: z.string().optional(), diff --git a/packages/cognitive/package.json b/packages/cognitive/package.json index 7de697d6aa0..7fa83c8374f 100644 --- a/packages/cognitive/package.json +++ b/packages/cognitive/package.json @@ -1,6 +1,6 @@ { "name": "@botpress/cognitive", - "version": "0.1.44", + "version": "0.1.45", "description": "Wrapper around the Botpress Client to call LLMs", "main": "./dist/index.cjs", "module": "./dist/index.mjs", diff --git a/packages/cognitive/src/client.ts b/packages/cognitive/src/client.ts index e51c29f4257..257e19372a6 100644 --- a/packages/cognitive/src/client.ts +++ b/packages/cognitive/src/client.ts @@ -40,6 +40,7 @@ export class Cognitive { protected _provider: ModelProvider protected _downtimes: ModelPreferences['downtimes'] = [] protected _useBeta: boolean = false + protected _debug = false private _events = createNanoEvents() @@ -61,11 +62,14 @@ export class Cognitive { provider: this._provider, timeout: this._timeoutMs, maxRetries: this._maxRetries, + __debug: this._debug, + __experimental_beta: this._useBeta, }) copy._models = [...this._models] copy._preferences = this._preferences ? { ...this._preferences } : null copy._downtimes = [...this._downtimes] + copy.interceptors.request = this.interceptors.request copy.interceptors.response = this.interceptors.response diff --git a/packages/cognitive/src/cognitive-v2/index.ts b/packages/cognitive/src/cognitive-v2/index.ts index 26a2df1cbb4..f1ea57f44cb 100644 --- a/packages/cognitive/src/cognitive-v2/index.ts +++ b/packages/cognitive/src/cognitive-v2/index.ts @@ -11,6 +11,7 @@ type ClientProps = { botId?: string token?: string withCredentials?: boolean + debug?: boolean headers?: Record } @@ -21,12 +22,15 @@ type RequestOptions = { const isBrowser = () => typeof window !== 'undefined' && typeof window.fetch === 'function' +export { Models } from './types' + export class CognitiveBeta { private _axiosClient: AxiosInstance private readonly _apiUrl: string private readonly _timeout: number private readonly _withCredentials: boolean private readonly _headers: Record + private readonly _debug: boolean = false public constructor(props: ClientProps) { this._apiUrl = props.apiUrl || 'https://api.botpress.cloud' @@ -42,6 +46,11 @@ export class CognitiveBeta { this._headers['Authorization'] = `Bearer ${props.token}` } + if (props.debug) { + this._debug = true + this._headers['X-Debug'] = '1' + } + this._axiosClient = axios.create({ headers: this._headers, withCredentials: this._withCredentials, @@ -49,6 +58,16 @@ export class CognitiveBeta { }) } + public clone(): CognitiveBeta { + return new CognitiveBeta({ + apiUrl: this._apiUrl, + timeout: this._timeout, + withCredentials: this._withCredentials, + headers: this._headers, + debug: this._debug, + }) + } + public async generateText(input: CognitiveRequest, options: RequestOptions = {}) { const signal = options.signal ?? AbortSignal.timeout(this._timeout) diff --git a/packages/cognitive/src/cognitive-v2/types.ts b/packages/cognitive/src/cognitive-v2/types.ts index a134b584d69..7a16de01ace 100644 --- a/packages/cognitive/src/cognitive-v2/types.ts +++ b/packages/cognitive/src/cognitive-v2/types.ts @@ -1,21 +1,7 @@ -type Models = +export type Models = | 'auto' | 'best' | 'fast' - | 'reasoning' - | 'cheapest' - | 'balance' - | 'recommended' - | 'reasoning' - | 'general-purpose' - | 'low-cost' - | 'vision' - | 'coding' - | 'function-calling' - | 'agents' - | 'storytelling' - | 'preview' - | 'roleplay' | 'anthropic:claude-3-5-haiku-20241022' | 'anthropic:claude-3-5-sonnet-20240620' | 'anthropic:claude-3-5-sonnet-20241022' @@ -70,6 +56,7 @@ type Models = | 'xai:grok-4-fast-reasoning' | 'xai:grok-code-fast-1' | ({} & string) + export type CognitiveRequest = { /** * @minItems 1 diff --git a/packages/cognitive/src/types.ts b/packages/cognitive/src/types.ts index 6a5af52638c..25747bea108 100644 --- a/packages/cognitive/src/types.ts +++ b/packages/cognitive/src/types.ts @@ -49,6 +49,7 @@ export type CognitiveProps = { maxRetries?: number /** Whether to use the beta client. Restricted to authorized users. */ __experimental_beta?: boolean + __debug?: boolean } export type Events = { diff --git a/packages/llmz/package.json b/packages/llmz/package.json index 57a2651b022..27d20c56b96 100644 --- a/packages/llmz/package.json +++ b/packages/llmz/package.json @@ -2,7 +2,7 @@ "name": "llmz", "type": "module", "description": "LLMz – An LLM-native Typescript VM built on top of Zui", - "version": "0.0.25", + "version": "0.0.26", "types": "./dist/index.d.ts", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -67,7 +67,7 @@ }, "peerDependencies": { "@botpress/client": "^1.25.0", - "@botpress/cognitive": "^0.1.44", + "@botpress/cognitive": "^0.1.45", "@bpinternal/thicktoken": "^1.0.5", "@bpinternal/zui": "^1.0.1" }, diff --git a/packages/llmz/src/context.ts b/packages/llmz/src/context.ts index 26e4c25a89e..6244e545780 100644 --- a/packages/llmz/src/context.ts +++ b/packages/llmz/src/context.ts @@ -1,3 +1,4 @@ +import { Models } from '@botpress/cognitive' import { z } from '@bpinternal/zui' import { cloneDeep, isPlainObject } from 'lodash-es' import { ulid } from 'ulid' @@ -16,8 +17,6 @@ import { Transcript, TranscriptArray } from './transcript.js' import { wrapContent } from './truncator.js' import { ObjectMutation, Serializable, Trace } from './types.js' -export type Model = 'best' | 'fast' | `${string}:${string}` | (string & {}) - export type IterationParameters = { transcript: TranscriptArray tools: Tool[] @@ -25,7 +24,7 @@ export type IterationParameters = { exits: Exit[] instructions?: string components: Component[] - model: Model + model: Models | Models[] temperature: number } @@ -350,7 +349,7 @@ export namespace Iteration { messages: LLMzPrompts.Message[] code?: string traces: Trace[] - model: Model + model: Models | Models[] temperature: number variables: Record started_ts: number @@ -584,7 +583,7 @@ export class Context implements Serializable { public objects?: ValueOrGetter public tools?: ValueOrGetter public exits?: ValueOrGetter - public model?: ValueOrGetter + public model?: ValueOrGetter public temperature: ValueOrGetter public version: Prompt = DualModePrompt @@ -910,7 +909,7 @@ export class Context implements Serializable { exits?: ValueOrGetter loop?: number temperature?: ValueOrGetter - model?: ValueOrGetter + model?: ValueOrGetter metadata?: Record snapshot?: Snapshot timeout?: number diff --git a/packages/llmz/src/errors.ts b/packages/llmz/src/errors.ts index 9fe1352f2cc..d98cff740bd 100644 --- a/packages/llmz/src/errors.ts +++ b/packages/llmz/src/errors.ts @@ -135,6 +135,7 @@ export class ThinkSignal extends VMLoopSignal { ) { super('Think signal received: ' + reason) this.message = Signals.serializeError(this) + this.stack = '' } public toString() { @@ -164,6 +165,7 @@ export class InvalidCodeError extends Error { ) { super(message) this.message = Signals.serializeError(this) + this.stack = '' } } @@ -171,6 +173,7 @@ export class LoopExceededError extends Error { public constructor() { super('Loop exceeded error') this.message = Signals.serializeError(this) + this.stack = '' } } @@ -182,6 +185,7 @@ export class CodeFormattingError extends Error { super(message, { cause: 'Code formatting error', }) + this.stack = '' } } @@ -192,9 +196,18 @@ export class AssignmentError extends Error { } } +export class CognitiveError extends Error { + public constructor(message: string) { + super(message) + this.message = Signals.serializeError(this) + this.stack = '' + } +} + registerErrorClass('VMSignal', VMSignal) registerErrorClass('SnapshotSignal', SnapshotSignal) registerErrorClass('VMLoopSignal', VMLoopSignal) registerErrorClass('ThinkSignal', ThinkSignal) registerErrorClass('CodeExecutionError', CodeExecutionError) registerErrorClass('AssignmentError', AssignmentError) +registerErrorClass('CognitiveError', CognitiveError) diff --git a/packages/llmz/src/index.ts b/packages/llmz/src/index.ts index bec9e691b01..5cac78c8d6c 100644 --- a/packages/llmz/src/index.ts +++ b/packages/llmz/src/index.ts @@ -56,7 +56,7 @@ export const utils = { * @param props.exits - Array of Exit definitions for structured completion (static or dynamic) * @param props.snapshot - Optional Snapshot to resume paused execution * @param props.signal - Optional AbortSignal to cancel execution - * @param props.model - Optional model name (static or dynamic function) + * @param props.model - Optional model name (or array or models to use as fallback) (static or dynamic function) * @param props.temperature - Optional temperature value (static or dynamic function) * @param props.options - Optional execution options (loop limit, timeout) * @param props.onTrace - Optional non-blocking hook for monitoring traces during execution diff --git a/packages/llmz/src/llmz.ts b/packages/llmz/src/llmz.ts index be1c4479799..fdb017616b7 100644 --- a/packages/llmz/src/llmz.ts +++ b/packages/llmz/src/llmz.ts @@ -1,4 +1,4 @@ -import { Cognitive, type BotpressClientLike } from '@botpress/cognitive' +import { Cognitive, Models, type BotpressClientLike } from '@botpress/cognitive' import { z } from '@bpinternal/zui' import { clamp, isEqual, isPlainObject, omit } from 'lodash-es' @@ -7,10 +7,11 @@ import ms from 'ms' import { ulid } from 'ulid' import { createJoinedAbortController } from './abort-signal.js' import { Chat } from './chat.js' -import { Context, Iteration, Model } from './context.js' +import { Context, Iteration } from './context.js' import { AssignmentError, CodeExecutionError, + CognitiveError, InvalidCodeError, LoopExceededError, Signals, @@ -224,7 +225,7 @@ export type ExecutionProps = { * The model to use for the LLM. * This can be a static model name or a function that returns a model name based on the current context. */ - model?: ValueOrGetter + model?: ValueOrGetter /** * The temperature to use for the LLM. @@ -378,8 +379,8 @@ const executeIteration = async ({ } & ExecutionHooks): Promise => { let startedAt = Date.now() const traces = iteration.traces - const model = await cognitive.getModelDetails(iteration.model ?? 'best') - const modelLimit = model.input.maxTokens + const model = await cognitive.getModelDetails(Array.isArray(iteration.model) ? iteration.model[0]! : iteration.model) + const modelLimit = Math.max(model.input.maxTokens, 8_000) const responseLengthBuffer = getModelOutputLimit(modelLimit) const messages = truncateWrappedContent({ @@ -416,7 +417,7 @@ const executeIteration = async ({ : null if (!out) { - throw new Error('No output from LLM') + throw new CognitiveError('LLM did not return any text output') } const assistantResponse = ctx.version.parseAssistantResponse(out) diff --git a/packages/llmz/src/stack-traces.test.ts b/packages/llmz/src/stack-traces.test.ts index a87e17a6520..e0b88dbf950 100644 --- a/packages/llmz/src/stack-traces.test.ts +++ b/packages/llmz/src/stack-traces.test.ts @@ -4,6 +4,7 @@ import { cleanStackTrace } from './stack-traces.js' describe('clean transcript stack traces', () => { test('replaces OSX files', () => { const stack = `Error: Error + at /Users/adam/my_project/is/cool.ts:1:1 at /Users/adam/llmz/src/__tests__/index.ts:1:1 at (/Users/adam/llmz/src/__tests__/index.ts:2:2) at Object. /Users/adam/llmz/src/__tests__/index.ts:3:3 @@ -13,6 +14,7 @@ describe('clean transcript stack traces', () => { expect(cleanStackTrace(stack, false)).toMatchInlineSnapshot(` "Error: Error + at /Users/adam/my_project/is/cool.ts:1:1 at /llmz/src/__tests__/index.ts:1:1 at (/llmz/src/__tests__/index.ts:2:2) at Object. /llmz/src/__tests__/index.ts:3:3 @@ -20,11 +22,16 @@ describe('clean transcript stack traces', () => { at /llmz/src/__tests__/index.ts:5:5 at file://hello/world/node_modules/library/index.js:1:1" `) - expect(cleanStackTrace(stack)).toMatchInlineSnapshot(`"Error: Error"`) + + expect(cleanStackTrace(stack)).toMatchInlineSnapshot(` + "Error: Error + at /Users/adam/my_project/is/cool.ts:1:1" + `) }) test('replaces Windows files', () => { const stack = `Error: Error + at C:\\Users\\adam\\my_project\\is\\cool\\index.ts:1:1 at C:\\Users\\adam\\llmz\\src\\__tests__\\index.ts:1:1 at (C:\\Users\\adam\\llmz\\src\\__tests__\\index.ts:2:2) at Object. C:\\Users\\adam\\llmz\\src\\__tests__\\index.ts:3:3 @@ -33,6 +40,7 @@ describe('clean transcript stack traces', () => { at file://hello/world/node_modules/library/index.js:1:1` expect(cleanStackTrace(stack, false)).toMatchInlineSnapshot(` "Error: Error + at C:\\Users\\adam\\my_project\\is\\cool\\index.ts:1:1 at \\llmz\\src\\__tests__\\index.ts:1:1 at (\\llmz\\src\\__tests__\\index.ts:2:2) at Object. \\llmz\\src\\__tests__\\index.ts:3:3 @@ -40,6 +48,9 @@ describe('clean transcript stack traces', () => { at \\llmz\\src\\__tests__\\index.ts:5:5 at file://hello/world/node_modules/library/index.js:1:1" `) - expect(cleanStackTrace(stack)).toMatchInlineSnapshot(`"Error: Error"`) + expect(cleanStackTrace(stack)).toMatchInlineSnapshot(` + "Error: Error + at C:\\Users\\adam\\my_project\\is\\cool\\index.ts:1:1" + `) }) }) diff --git a/packages/llmz/src/stack-traces.ts b/packages/llmz/src/stack-traces.ts index b3fae608022..735520e3960 100644 --- a/packages/llmz/src/stack-traces.ts +++ b/packages/llmz/src/stack-traces.ts @@ -3,30 +3,34 @@ const isInternalLine = (line: string) => { } export function cleanStackTrace(stack: string, cleanInternal = true) { - const lines = stack.split('\n') + let lines = stack.split('\n') + const until = lines.findIndex((line) => isInternalLine(line)) - for (let i = 0; i < lines.length; i++) { - const line = lines[i]! - let llmzIndex = line.indexOf('/llmz/') + if (cleanInternal && until >= 0) { + lines = lines.slice(0, until) + } else { + lines = lines.map((line) => { + let llmzIndex = line.indexOf('/llmz/') - if (llmzIndex === -1) { - llmzIndex = line.indexOf('\\llmz\\') - } + if (llmzIndex === -1) { + llmzIndex = line.indexOf('\\llmz\\') + } - if (llmzIndex === -1) { - continue - } + if (llmzIndex === -1) { + return line + } - let lastSpaceIndex = line.lastIndexOf(' ', llmzIndex) + let lastSpaceIndex = line.lastIndexOf(' ', llmzIndex) - if (lastSpaceIndex === -1) { - lastSpaceIndex = 0 - } + if (lastSpaceIndex === -1) { + lastSpaceIndex = 0 + } - const maybeParen = line[lastSpaceIndex + 1] === '(' ? '(' : '' + const maybeParen = line[lastSpaceIndex + 1] === '(' ? '(' : '' - lines[i] = line.slice(0, lastSpaceIndex + 1) + maybeParen + line.slice(llmzIndex) + return line.slice(0, lastSpaceIndex + 1) + maybeParen + line.slice(llmzIndex) + }) } - return lines.filter((x) => !cleanInternal || !isInternalLine(x)).join('\n') + return lines.join('\n') } diff --git a/packages/zai/package.json b/packages/zai/package.json index 9b0f544ea43..f188a2d87d4 100644 --- a/packages/zai/package.json +++ b/packages/zai/package.json @@ -29,7 +29,7 @@ "author": "", "license": "ISC", "dependencies": { - "@botpress/cognitive": "0.1.44", + "@botpress/cognitive": "0.1.45", "json5": "^2.2.3", "jsonrepair": "^3.10.0", "lodash-es": "^4.17.21" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae8cbd914f6..b203e5afd87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -470,6 +470,9 @@ importers: '@botpress/sdk': specifier: workspace:* version: link:../../packages/sdk + '@mendable/firecrawl-js': + specifier: ^4.3.8 + version: 4.3.8 axios: specifier: ^1.7.2 version: 1.7.2 @@ -2474,7 +2477,7 @@ importers: specifier: ^1.25.0 version: link:../client '@botpress/cognitive': - specifier: ^0.1.44 + specifier: ^0.1.45 version: link:../cognitive '@bpinternal/thicktoken': specifier: ^1.0.5 @@ -2648,7 +2651,7 @@ importers: packages/zai: dependencies: '@botpress/cognitive': - specifier: 0.1.44 + specifier: 0.1.45 version: link:../cognitive '@bpinternal/thicktoken': specifier: ^1.0.0 @@ -4495,6 +4498,10 @@ packages: resolution: {integrity: sha512-Cgz0xPb+1DUjmrl5whAsmqfAChBko+Wf4/PLQE4RvwfPlcq2agfHr1QFiXEhZ8e+GQwQ3hZQn9iLGXwIXwxUCg==} engines: {node: '>=10.0.0'} + '@mendable/firecrawl-js@4.3.8': + resolution: {integrity: sha512-eVzpav78JQhv6YdQAngp4oVq6AzKtTVXdUj/F7YmPOK4TU3jEpDmwAX5P1L4Ijm/M6h/EM7OLW+rbocgCRgkAw==} + engines: {node: '>=22.0.0'} + '@microsoft/api-extractor-model@7.30.1': resolution: {integrity: sha512-CTS2PlASJHxVY8hqHORVb1HdECWOEMcMnM6/kDkPr0RZapAFSIHhg9D4jxuE8g+OWYHtPc10LCpmde5pylTRlA==} @@ -10575,6 +10582,9 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' + typescript-event-target@1.1.1: + resolution: {integrity: sha512-dFSOFBKV6uwaloBCCUhxlD3Pr/P1a/tJdcmPrTXCHlEFD3faj0mztjcGn6VBAhQ0/Bdy8K3VWrrqwbt/ffsYsg==} + typescript@5.6.3: resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} @@ -13308,6 +13318,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@mendable/firecrawl-js@4.3.8': + dependencies: + axios: 1.12.2 + typescript-event-target: 1.1.1 + zod: 3.24.2 + zod-to-json-schema: 3.24.6(zod@3.24.2) + transitivePeerDependencies: + - debug + '@microsoft/api-extractor-model@7.30.1(@types/node@22.16.4)': dependencies: '@microsoft/tsdoc': 0.15.1 @@ -20911,6 +20930,8 @@ snapshots: transitivePeerDependencies: - supports-color + typescript-event-target@1.1.1: {} + typescript@5.6.3: {} typescript@5.7.2: {}