diff --git a/README.md b/README.md index 4ca6e506ea..33d1433080 100644 --- a/README.md +++ b/README.md @@ -1051,4 +1051,4 @@ firecrawl alexandria feedback --rating partial \ --rationale "Found summaries but could not retrieve attachments" --json ``` -No job ID is required. Alexandria session feedback has no job-age deadline and does not refund credits. Optional `--provider-feedback` and `--capability-feedback` accept JSON arrays; see `firecrawl alexandria feedback --help` for their fields and issue codes. Existing `feedback` and `search-feedback` commands retain their job-specific behavior. Endpoint feedback opt-out environment variables also apply to this command. +No job ID is required. Alexandria session feedback has no job-age deadline and does not refund credits. Optional `--provider-feedback` and `--capability-feedback` accept JSON arrays; see `firecrawl alexandria feedback --help` for their fields and issue codes. Capability issue codes are `new_capability_request` (requires `requestedFunctionality`), `missing_capability` (the provider exists but lacks this capability), `insufficient_functionality`, `incorrect_result`, `execution_error`, and `other`. Existing `feedback` and `search-feedback` commands retain their job-specific behavior. Endpoint feedback opt-out environment variables also apply to this command. diff --git a/package.json b/package.json index 427f8606e4..d2801d6ea7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firecrawl-cli", - "version": "1.24.0", + "version": "1.24.1", "publishConfig": { "tag": "latest" }, diff --git a/skills/firecrawl-agent/SKILL.md b/skills/firecrawl-agent/SKILL.md index fb288527ac..14225ece46 100644 --- a/skills/firecrawl-agent/SKILL.md +++ b/skills/firecrawl-agent/SKILL.md @@ -60,4 +60,4 @@ firecrawl agent "" --cancel ## Alexandria session feedback -To report an Alexandria session outcome or a provider/capability gap, use `firecrawl alexandria feedback --rating good|partial|bad --url --requested-functionality '' --rationale '' --json`. Use observed results in the rationale. No job ID is needed; this session feedback has no job-age deadline and no credit refund. Optional `--provider-feedback` and `--capability-feedback` JSON arrays describe specific gaps; inspect `firecrawl alexandria feedback --help` for their fields. +To report an Alexandria session outcome or a provider/capability gap, use `firecrawl alexandria feedback --rating good|partial|bad --url --requested-functionality '' --rationale '' --json`. Use observed results in the rationale. No job ID is needed; this session feedback has no job-age deadline and no credit refund. Optional `--provider-feedback` and `--capability-feedback` JSON arrays describe specific gaps; inspect `firecrawl alexandria feedback --help` for their fields. Use the capability issue `missing_capability` when a provider exists but lacks the needed capability, and `new_capability_request` (with `requestedFunctionality`) to ask for one. diff --git a/src/__tests__/alexandria-beta.test.ts b/src/__tests__/alexandria-beta.test.ts index 0bf1b32068..d96a37999f 100644 --- a/src/__tests__/alexandria-beta.test.ts +++ b/src/__tests__/alexandria-beta.test.ts @@ -1202,6 +1202,17 @@ it.each([ '--capability-feedback', [{ name: 'attachments', issue: 'execution_error', why: 'Timeout' }], ], + [ + '--capability-feedback', + [ + { + name: 'attachments', + provider: 'example', + issue: 'unknown_issue', + why: 'Not a real code', + }, + ], + ], ])('rejects malformed %s before posting', async (flag, entries) => { const result = await cli([ ...sessionFeedbackArgs, @@ -1251,3 +1262,27 @@ it('normalizes and sends valid provider and capability feedback', async () => { 'Download attachments' ); }); + +it('sends missing_capability feedback without requestedFunctionality', async () => { + response = { + success: true, + feedbackId: 'feedback-missing-capability', + creditsRefunded: 0, + }; + const capability = [ + { + name: 'attachments', + provider: 'example', + issue: 'missing_capability', + why: 'Provider has no attachment endpoint', + }, + ]; + const result = await cli([ + ...sessionFeedbackArgs, + '--capability-feedback', + JSON.stringify(capability), + ]); + expect(result.code).toBe(0); + expect(requests).toHaveLength(1); + expect(requests[0].body.capabilityFeedback).toEqual(capability); +}); diff --git a/src/__tests__/commands/feedback.test.ts b/src/__tests__/commands/feedback.test.ts index e53915ccf8..45e86f4779 100644 --- a/src/__tests__/commands/feedback.test.ts +++ b/src/__tests__/commands/feedback.test.ts @@ -6,6 +6,7 @@ import { parseFeedbackListArg, parsePageNumbersArg, } from '../../commands/feedback'; +import { parseAlexandriaFeedbackArray } from '../../commands/alexandria-feedback'; import { getClient } from '../../utils/client'; import { initializeConfig } from '../../utils/config'; import { setupTest, teardownTest } from '../utils/mock-client'; @@ -255,3 +256,47 @@ describe('feedback parsing', () => { expect(parsePageNumbersArg('[4,5]')).toEqual([4, 5]); }); }); + +describe('parseAlexandriaFeedbackArray capability issues', () => { + const base = { + name: 'attachments', + provider: 'example', + why: 'Provider has no attachment endpoint', + }; + const parse = (entry: Record) => + parseAlexandriaFeedbackArray(JSON.stringify([entry]), true); + + it('accepts missing_capability without requestedFunctionality', () => { + expect(parse({ ...base, issue: 'missing_capability' })).toEqual([ + { ...base, issue: 'missing_capability' }, + ]); + }); + + it('accepts missing_capability with requestedFunctionality', () => { + expect( + parse({ + ...base, + issue: 'missing_capability', + requestedFunctionality: ' Download attachments ', + }) + ).toEqual([ + { + ...base, + issue: 'missing_capability', + requestedFunctionality: 'Download attachments', + }, + ]); + }); + + it('still requires requestedFunctionality for new_capability_request', () => { + expect(() => parse({ ...base, issue: 'new_capability_request' })).toThrow( + 'requestedFunctionality must contain 1–2000 characters.' + ); + }); + + it('still rejects unknown issue codes', () => { + expect(() => parse({ ...base, issue: 'not_a_real_issue' })).toThrow( + 'unsupported issue code.' + ); + }); +}); diff --git a/src/commands/alexandria-feedback.ts b/src/commands/alexandria-feedback.ts index 480967d8b0..c09e633296 100644 --- a/src/commands/alexandria-feedback.ts +++ b/src/commands/alexandria-feedback.ts @@ -32,6 +32,7 @@ const providerIssues = [ ]; const capabilityIssues = [ 'new_capability_request', + 'missing_capability', 'insufficient_functionality', 'incorrect_result', 'execution_error', @@ -115,7 +116,7 @@ export function createAlexandriaFeedbackCommand(): Command { ) .option( '--capability-feedback ', - 'Array of {name, provider, issue, why, requestedFunctionality?}; issues: new_capability_request (requires requestedFunctionality), insufficient_functionality, incorrect_result, execution_error, other', + 'Array of {name, provider, issue, why, requestedFunctionality?}; issues: new_capability_request (requires requestedFunctionality), missing_capability (provider exists but lacks this capability), insufficient_functionality, incorrect_result, execution_error, other', (value) => parseAlexandriaFeedbackArray(value, true) ) .option('-k, --api-key ', 'Firecrawl API key')