diff --git a/README.md b/README.md index 4f2a8f43ce..f7d2924215 100644 --- a/README.md +++ b/README.md @@ -695,23 +695,32 @@ firecrawl agent --wait #### Agent Options -| Option | Description | -| --------------------------- | -------------------------------------------------------------------------------------- | -| `--urls ` | Comma-separated URLs to focus extraction on | -| `--model ` | `spark-2` (default). `spark-1-mini` and `spark-1-pro` are deprecated and run `spark-2` | -| `--effort ` | Reasoning effort: `low`, `medium`, or `high` | -| `--schema ` | JSON schema for structured output (inline JSON string) | -| `--schema-file ` | Path to JSON schema file for structured output | -| `--max-credits ` | Maximum credits to spend (job fails if exceeded) | -| `--webhook ` | Webhook URL or configuration | -| `--status` | Check status of existing agent job | -| `--cancel` | Cancel an active agent job by job ID | -| `--wait` | Wait for agent to complete before returning results | -| `--poll-interval ` | Polling interval in seconds when waiting (default: 5) | -| `--timeout ` | Timeout in seconds when waiting (default: no timeout) | -| `-o, --output ` | Save output to file | -| `--json` | Output as JSON format | -| `--pretty` | Pretty print JSON output | +| Option | Description | +| ------------------------------ | --------------------------------------------------------------------------------------------------------- | +| `--urls ` | Comma-separated URLs to focus extraction on | +| `--model ` | `spark-2` (default). `spark-1-mini` and `spark-1-pro` are deprecated and run `spark-2` | +| `--effort ` | Reasoning effort: `low`, `medium`, or `high` | +| `--schema ` | JSON schema for structured output (inline JSON string) | +| `--schema-file ` | Path to JSON schema file for structured output | +| `--max-credits ` | Maximum credits to spend (job fails if exceeded) | +| `--webhook ` | Webhook URL or configuration | +| `--alexandria` | Let the agent call Alexandria providers (implied by the flags below); `--no-alexandria` keeps it off them | +| `--toolkits ` | Comma-separated provider slugs the agent may use (up to 5; default: the whole catalog) | +| `--max-calls ` | Most provider calls the agent may make this turn (1-30) | +| `--require-approval` | Stop for approval before any paid provider call (needs `--mode chat`) | +| `--approve ` | Approve the previous turn's pending approval (needs `--thread`) | +| `--call-ids ` | With `--approve`: comma-separated call IDs to approve (default: all) | +| `--always` | With `--approve`: stop asking for the rest of the thread | +| `--decline ` | Decline the previous turn's pending approval (needs `--thread`) | +| `--on-terms-required ` | When a provider needs data terms the team has not accepted: `skip` it (default) or `ask` | +| `--status` | Check status of existing agent job | +| `--cancel` | Cancel an active agent job by job ID | +| `--wait` | Wait for agent to complete before returning results | +| `--poll-interval ` | Polling interval in seconds when waiting (default: 5) | +| `--timeout ` | Timeout in seconds when waiting (default: no timeout) | +| `-o, --output ` | Save output to file | +| `--json` | Output as JSON format | +| `--pretty` | Pretty print JSON output | #### Examples @@ -735,6 +744,21 @@ firecrawl agent abc123-def456-... --json firecrawl agent abc123-def456-... --wait --poll-interval 10 ``` +#### Alexandria providers + +A run uses Alexandria providers only when it starts with an Alexandria flag. A follow-up turn (`--thread`) keeps the previous turn's setting for every Alexandria flag it omits. + +```bash +# Let the agent use two providers +firecrawl agent "Find the head of sales at example.com" --toolkits apollo,crunchbase --wait + +# Ask before any paid provider call, then answer the approval on the next turn +firecrawl agent "Find the head of sales at example.com" --mode chat --require-approval --wait +firecrawl agent "Go ahead" --thread --mode chat --approve --wait +``` + +A run that stops for approval prints its approval ID and the exact `--approve` / `--decline` follow-up commands. With `--json`, read `pendingApproval` and `exchange` from the output. + --- ### `interact` - Interact with scraped pages diff --git a/package.json b/package.json index 26cecd52a3..5c7213efeb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firecrawl-cli", - "version": "1.26.1", + "version": "1.26.2", "publishConfig": { "tag": "latest" }, @@ -85,7 +85,7 @@ "dependencies": { "@inquirer/prompts": "^8.2.1", "commander": "^14.0.2", - "firecrawl": "4.40.0", + "firecrawl": "4.44.0", "yaml": "^2.9.0", "zod-to-json-schema": "3.24.6" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb1484dcf1..6d3c93ba5a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^14.0.2 version: 14.0.2 firecrawl: - specifier: 4.40.0 - version: 4.40.0 + specifier: 4.44.0 + version: 4.44.0 yaml: specifier: ^2.9.0 version: 2.9.0 @@ -530,8 +530,8 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axios@1.18.0: - resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} + axios@1.20.0: + resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -667,8 +667,8 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - firecrawl@4.40.0: - resolution: {integrity: sha512-YPNQvDyytR5cU4ETQwODI/D9ABs0bri70HAk43zCa07neP/c0DPQtea403iUvATzGy0wvn+bQjxqkJBxD7VTjw==} + firecrawl@4.44.0: + resolution: {integrity: sha512-cpjl8pqYUYYCTtl0cXAoLgWCYotIvjKDrh31nx/HdB/1OcrfNswXRrbrnDCAkM1Ij1BUrd22mUHkBboIGiv3cg==} engines: {node: '>=22.0.0'} follow-redirects@1.16.0: @@ -680,8 +680,8 @@ packages: debug: optional: true - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} fsevents@2.3.3: @@ -720,8 +720,8 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} https-proxy-agent@5.0.1: @@ -1417,10 +1417,10 @@ snapshots: asynckit@0.4.0: {} - axios@1.18.0: + axios@1.20.0: dependencies: follow-redirects: 1.16.0 - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: @@ -1500,7 +1500,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 esbuild@0.27.2: optionalDependencies: @@ -1569,9 +1569,9 @@ snapshots: dependencies: to-regex-range: 5.0.1 - firecrawl@4.40.0: + firecrawl@4.44.0: dependencies: - axios: 1.18.0 + axios: 1.20.0 typescript-event-target: 1.1.2 zod: 3.25.76 zod-to-json-schema: 3.24.6(zod@3.25.76) @@ -1581,12 +1581,12 @@ snapshots: follow-redirects@1.16.0: {} - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.2 + hasown: 2.0.4 mime-types: 2.1.35 fsevents@2.3.3: @@ -1606,7 +1606,7 @@ snapshots: get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-proto@1.0.1: @@ -1624,7 +1624,7 @@ snapshots: dependencies: has-symbols: 1.1.0 - hasown@2.0.2: + hasown@2.0.4: dependencies: function-bind: 1.1.2 diff --git a/skills/firecrawl-agent/SKILL.md b/skills/firecrawl-agent/SKILL.md index 14e99628f6..fffc42f0bd 100644 --- a/skills/firecrawl-agent/SKILL.md +++ b/skills/firecrawl-agent/SKILL.md @@ -29,6 +29,16 @@ Run `firecrawl agent --help` for the full option list. **Done when:** the output file contains valid JSON answering the request — or a job ID was intentionally returned for later polling. +## Alexandria providers + +A run uses connected Alexandria data providers only when it starts with an Alexandria flag: `--alexandria`, `--toolkits ` (up to 5), `--max-calls `, `--require-approval`, or `--on-terms-required skip|ask`. Follow-ups on its thread keep those settings. + +```bash +firecrawl agent "find the head of sales at " --toolkits apollo,crunchbase --wait --json -o .firecrawl/contacts.json +``` + +With `--require-approval` (needs `--mode chat`), a run can end on a `pendingApproval` instead of making a paid call. Ask the user, then answer it on the same thread with `--thread --mode chat --approve ` (or `--decline `). A `terms` approval only continues after an organization admin has accepted the provider's terms in the Firecrawl dashboard; approving does not accept them. + ## Job IDs Omitting `--wait` returns a job ID. A UUID positional argument is auto-detected as a status check: diff --git a/src/__tests__/alexandria-beta.test.ts b/src/__tests__/alexandria-beta.test.ts index bc0d7142ce..abb375c056 100644 --- a/src/__tests__/alexandria-beta.test.ts +++ b/src/__tests__/alexandria-beta.test.ts @@ -1069,6 +1069,207 @@ it('rejects a malformed --thread before calling the API', async () => { expect(requests).toHaveLength(0); }); +const APPROVAL_ID = '3f2a1b0c-9d8e-4f7a-8b6c-5d4e3f2a1b0c'; + +it('maps the Alexandria flags onto the exchange object', async () => { + response = { success: true, id: RUN_ID, threadId: THREAD_ID, threadTurn: 2 }; + const approve = await cli([ + 'agent', + 'Go ahead.', + '--thread', + THREAD_ID, + '--mode', + 'chat', + '--alexandria', + '--toolkits', + 'apollo, crunchbase', + '--max-calls', + '8', + '--require-approval', + '--approve', + APPROVAL_ID, + '--call-ids', + 'call-1,call-2', + '--always', + '--on-terms-required', + 'ask', + ]); + expect(approve.code).toBe(0); + expect(requests[0].body.exchange).toEqual({ + enabled: true, + toolkits: ['apollo', 'crunchbase'], + maxCalls: 8, + requireApproval: true, + approve: { + approvalId: APPROVAL_ID, + callIds: ['call-1', 'call-2'], + always: true, + }, + onTermsRequired: 'ask', + }); + + const decline = await cli([ + 'agent', + 'Never mind.', + '--thread', + THREAD_ID, + '--decline', + APPROVAL_ID, + '--no-alexandria', + ]); + expect(decline.code).toBe(0); + expect(requests[1].body.exchange).toEqual({ + enabled: false, + decline: { approvalId: APPROVAL_ID }, + }); +}); + +it('sends no exchange without an Alexandria flag', async () => { + response = { success: true, id: RUN_ID, threadId: THREAD_ID, threadTurn: 2 }; + const result = await cli([ + 'agent', + 'And the heading?', + '--thread', + THREAD_ID, + '--mode', + 'chat', + ]); + expect(result.code).toBe(0); + expect(requests[0].body).not.toHaveProperty('exchange'); +}); + +it('rejects approval flags the API cannot honor before calling it', async () => { + const both = await cli([ + 'agent', + 'Go ahead.', + '--thread', + THREAD_ID, + '--approve', + APPROVAL_ID, + '--decline', + APPROVAL_ID, + ]); + expect(both.code).toBe(1); + expect(both.stderr).toContain('use --approve or --decline, not both'); + + const noThread = await cli(['agent', 'Go ahead.', '--decline', APPROVAL_ID]); + expect(noThread.code).toBe(1); + expect(noThread.stderr).toContain('pass that thread with --thread'); + + const noChat = await cli(['agent', 'Find contacts.', '--require-approval']); + expect(noChat.code).toBe(1); + expect(noChat.stderr).toContain('--require-approval needs --mode chat'); + expect(requests).toHaveLength(0); +}); + +it('shows a pending approval and how to answer it', async () => { + const approvalStatus = { + success: true, + status: 'completed', + expiresAt: '2026-09-17T00:00:00.000Z', + creditsUsed: 4, + threadId: THREAD_ID, + threadTurn: 1, + mode: 'chat', + message: 'I need your approval for one paid lookup.', + pendingApproval: { + id: APPROVAL_ID, + kind: 'calls', + reason: 'Look up the company in a paid provider.', + calls: [ + { + id: 'call-1', + provider: 'apollo', + capability: 'organizations/enrich', + input: { domain: 'example.com' }, + creditsEstimate: 3, + }, + ], + resolution: null, + }, + exchange: { + enabled: true, + toolkits: ['apollo'], + requireApproval: true, + paidCalls: 0, + creditsUsed: 0, + skippedProviders: [ + { + provider: 'crunchbase', + name: 'Crunchbase', + reason: 'terms_required', + version: '1', + termsUrl: 'https://example.com/terms/crunchbase', + }, + ], + }, + }; + runThenPoll(approvalStatus); + const args = [ + 'agent', + 'Find the company size.', + '--mode', + 'chat', + '--toolkits', + 'apollo', + '--require-approval', + '--wait', + '--poll-interval', + '0.01', + ]; + const readable = await cli(args); + expect(readable.code).toBe(0); + expect(requests[0].body.exchange).toEqual({ + toolkits: ['apollo'], + requireApproval: true, + }); + expect(readable.stdout).toContain('Alexandria: 0 paid calls, 0 credits'); + expect(readable.stdout).toContain( + ' - Crunchbase: https://example.com/terms/crunchbase' + ); + expect(readable.stdout).toContain( + `Pending approval ${APPROVAL_ID}: Look up the company in a paid provider.` + ); + expect(readable.stdout).toContain( + ' - call-1: apollo/organizations/enrich (~3 credits)' + ); + for (const answer of ['--approve', '--decline']) { + expect(readable.stdout).toContain( + `firecrawl agent "" --thread ${THREAD_ID} --mode chat ${answer} ${APPROVAL_ID}` + ); + } + + const json = await cli([...args, '--json']); + expect(JSON.parse(json.stdout)).toMatchObject({ + pendingApproval: approvalStatus.pendingApproval, + exchange: approvalStatus.exchange, + }); + + response = { + ...approvalStatus, + pendingApproval: { + id: APPROVAL_ID, + kind: 'terms', + reason: 'Crunchbase needs its data terms accepted.', + calls: [], + terms: [ + { + provider: 'crunchbase', + name: 'Crunchbase', + version: '1', + digest: null, + url: 'https://example.com/terms/crunchbase', + }, + ], + resolution: null, + }, + }; + responseFor = undefined; + const terms = await cli(['agent', RUN_ID]); + expect(terms.stdout).toContain('accept them in the Firecrawl dashboard'); + expect(terms.stdout).toContain(`--approve ${APPROVAL_ID}`); +}); + it('surfaces chat replies and thread position on status', async () => { response = { success: true, diff --git a/src/commands/agent.ts b/src/commands/agent.ts index 139dabb7f0..81f4aca5af 100644 --- a/src/commands/agent.ts +++ b/src/commands/agent.ts @@ -13,10 +13,13 @@ import type { AgentThreadOptions, } from '../types/agent'; import type { + AgentExchangeOptions, + AgentExchangeSummary, AgentMode, AgentStatusResponse, AgentThread, AgentWebhookConfig, + PendingApproval, } from 'firecrawl'; import { getClient } from '../utils/client'; import { isJobId } from '../utils/job'; @@ -131,6 +134,8 @@ function toStatusData( ...(status.mode !== undefined && { mode: status.mode }), ...(status.message !== undefined && { message: status.message }), ...(status.suggestions?.length && { suggestions: status.suggestions }), + ...(status.pendingApproval && { pendingApproval: status.pendingApproval }), + ...(status.exchange && { exchange: status.exchange }), ...readIncompleteFields(status), }; } @@ -299,6 +304,7 @@ export async function executeAgent( pollInterval?: number; timeout?: number; webhook?: string | AgentWebhookConfig; + exchange?: AgentExchangeOptions; integration?: string; } = { prompt, @@ -329,6 +335,9 @@ export async function executeAgent( if (options.webhook) { agentParams.webhook = options.webhook; } + if (options.exchange) { + agentParams.exchange = options.exchange; + } // If wait mode, use polling with spinner if (wait) { @@ -483,6 +492,62 @@ function creditLimitNextSteps(threadId?: string): string[] { return lines; } +/** + * What Alexandria did in the run: paid calls, their credits, and providers + * left out because their data terms are not accepted. + */ +function exchangeSummaryLines(exchange: AgentExchangeSummary): string[] { + const calls = `${exchange.paidCalls} paid call${exchange.paidCalls === 1 ? '' : 's'}`; + const credits = + typeof exchange.creditsUsed === 'number' + ? `, ${exchange.creditsUsed} credits` + : ''; + const lines = [`Alexandria: ${calls}${credits}`]; + if (exchange.skippedProviders?.length) { + lines.push('Skipped until their data terms are accepted:'); + for (const provider of exchange.skippedProviders) { + lines.push(` - ${provider.name}: ${provider.termsUrl}`); + } + } + return lines; +} + +/** + * What a turn that ended on a pending approval waits for, and the follow-up + * commands that answer it. + */ +function pendingApprovalLines( + approval: PendingApproval, + threadId: string +): string[] { + const lines = [`Pending approval ${approval.id}: ${approval.reason}`]; + if (approval.kind === 'terms') { + lines.push( + 'Approving does not accept terms; accept them in the Firecrawl dashboard first:' + ); + for (const gate of approval.terms) { + lines.push(` - ${gate.name}: ${gate.url}`); + } + } else { + for (const call of approval.calls) { + const estimate = + typeof call.creditsEstimate === 'number' + ? ` (~${call.creditsEstimate} credits)` + : ''; + lines.push( + ` - ${call.id}: ${call.provider}/${call.capability}${estimate}` + ); + } + } + const followUp = `firecrawl agent "" --thread ${threadId} --mode chat`; + lines.push( + 'To answer it:', + ` ${followUp} --approve ${approval.id}`, + ` ${followUp} --decline ${approval.id}` + ); + return lines; +} + /** * Short credit-limit notice for stderr, used when the result itself goes to * JSON or to a file and so is not shown on the terminal. @@ -537,6 +602,10 @@ function formatAgentStatus(data: AgentStatusResult['data']): string { lines.push(`Credits Used: ${data.creditsUsed}`); } + if (data.exchange) { + lines.push(...exchangeSummaryLines(data.exchange)); + } + if (data.expiresAt) { const expiresDate = new Date(data.expiresAt); lines.push( @@ -576,6 +645,11 @@ function formatAgentStatus(data: AgentStatusResult['data']): string { } } + if (data.pendingApproval && data.threadId) { + lines.push(''); + lines.push(...pendingApprovalLines(data.pendingApproval, data.threadId)); + } + if (creditLimited) { lines.push(''); lines.push(...creditLimitNextSteps(data.threadId)); diff --git a/src/index.ts b/src/index.ts index 343bdcd552..1c8c0835c5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,7 +81,7 @@ import packageJson from '../package.json'; import type { SearchSource, SearchCategory } from './types/search'; import type { ScrapeFormat } from './types/scrape'; import type { RelatedPapersOptions } from './types/research'; -import type { AgentWebhookConfig } from 'firecrawl'; +import type { AgentExchangeOptions, AgentWebhookConfig } from 'firecrawl'; import { createCreateCommand } from './commands/create'; import { createListCommand, createAlexandriaCommand } from './commands/list'; @@ -1698,6 +1698,47 @@ function createAgentCommand(): Command { 'high', ]) ) + // Alexandria providers: each flag maps onto one field of `exchange`. + .option( + '--alexandria', + 'Let the agent call Alexandria providers (implied by the flags below)' + ) + .option('--no-alexandria', 'Keep the agent off Alexandria providers') + .option( + '--toolkits ', + 'Comma-separated provider slugs the agent may use (up to 5; default: the whole catalog)' + ) + .option( + '--max-calls ', + 'Most provider calls the agent may make this turn (1-30)', + parseInt + ) + .option( + '--require-approval', + 'Stop for approval before any paid provider call (needs --mode chat)' + ) + .option( + '--approve ', + "Approve the previous turn's pending approval (needs --thread)" + ) + .option( + '--call-ids ', + 'With --approve: comma-separated call IDs to approve (default: all)' + ) + .option( + '--always', + 'With --approve: stop asking for the rest of the thread' + ) + .option( + '--decline ', + "Decline the previous turn's pending approval (needs --thread)" + ) + .addOption( + new Option( + '--on-terms-required ', + 'When a provider needs data terms the team has not accepted: skip it (default) or ask' + ).choices(['skip', 'ask']) + ) .action(async (promptOrJobId, options) => { // Auto-detect if it's a job ID (UUID format) const isStatusCheck = options.status || isJobId(promptOrJobId); @@ -1720,6 +1761,24 @@ function createAgentCommand(): Command { ); process.exit(1); } + if (options.approve && options.decline) { + console.error( + 'Error: use --approve or --decline, not both: each answers the pending approval one way.' + ); + process.exit(1); + } + if ((options.approve || options.decline) && !options.thread) { + console.error( + "Error: --approve and --decline answer a thread's pending approval; pass that thread with --thread." + ); + process.exit(1); + } + if (options.requireApproval && options.mode !== 'chat') { + console.error( + 'Error: --require-approval needs --mode chat on the same request, including follow-ups.' + ); + process.exit(1); + } // Parse URLs let urls: string[] | undefined; @@ -1767,6 +1826,20 @@ function createAgentCommand(): Command { process.exit(1); } + const exchange: AgentExchangeOptions = { + enabled: options.alexandria, + toolkits: parseCommaList(options.toolkits), + maxCalls: options.maxCalls, + requireApproval: options.requireApproval, + approve: options.approve && { + approvalId: options.approve, + callIds: parseCommaList(options.callIds), + always: options.always, + }, + decline: options.decline && { approvalId: options.decline }, + onTermsRequired: options.onTermsRequired, + }; + const agentOptions = { prompt: promptOrJobId, urls, @@ -1787,6 +1860,9 @@ function createAgentCommand(): Command { json: options.json, pretty: options.pretty, webhook, + exchange: Object.values(exchange).some((value) => value !== undefined) + ? exchange + : undefined, }; await handleAgentCommand(agentOptions); diff --git a/src/types/agent.ts b/src/types/agent.ts index d10969ded6..a391976e92 100644 --- a/src/types/agent.ts +++ b/src/types/agent.ts @@ -2,7 +2,14 @@ * Types and interfaces for the agent command */ -import type { AgentMode, AgentSuggestion, AgentWebhookConfig } from 'firecrawl'; +import type { + AgentExchangeOptions, + AgentExchangeSummary, + AgentMode, + AgentSuggestion, + AgentWebhookConfig, + PendingApproval, +} from 'firecrawl'; export type AgentModel = 'spark-1-pro' | 'spark-1-mini' | 'spark-2'; @@ -47,6 +54,8 @@ export interface AgentOptions { schemaFile?: string; /** Webhook URL or webhook config */ webhook?: string | AgentWebhookConfig; + /** Alexandria provider settings, sent only when an Alexandria flag is given */ + exchange?: AgentExchangeOptions; /** Cancel active agent job by ID */ cancel?: boolean; /** Maximum credits to spend (job fails if exceeded) */ @@ -95,6 +104,8 @@ export interface AgentStatusResult { mode?: AgentMode; message?: string; suggestions?: AgentSuggestion[]; + pendingApproval?: PendingApproval; + exchange?: AgentExchangeSummary; }; error?: string; }