Both research tickets and the config surface are settled. Decide how the plugin maps a fastCRW response to opencode results and how it reports failures: parsing both data[] and data.results shapes, snippet/description to content, the time field, empty results, success:false and each error_code (e.g. 429, 503 search_disabled), non-JSON bodies, network errors, abort via signal, and what error messages the user sees. Fallback to built-ins is off (fastCRW is the only provider).
Map: #1
## Question
Both research tickets and the config surface are settled. Decide how the plugin maps a fastCRW response to opencode results and how it reports failures: parsing both `data[]` and `data.results` shapes, `snippet`/`description` to `content`, the `time` field, empty results, `success:false` and each `error_code` (e.g. 429, 503 `search_disabled`), non-JSON bodies, network errors, abort via `signal`, and what error messages the user sees. Fallback to built-ins is off (fastCRW is the only provider).
Empty/malformed: empty list returns [], not an error. Entries without a string url are dropped; missing title falls back to url. No warnings logged.
API errors: throw Error("fastCRW <status> <error_code>: <error>"); HTTP 200 with success:false handled the same (status 200). Fixed hints only for 401 ("check apiKey or CRW_API_KEY") and 503 search_disabled ("the server has no search backend configured"). The token never appears in any message.
Non-JSON: throw fastCRW <status>: non-JSON response plus the first 200 chars of the body.
Network errors: throw fastCRW: cannot reach <baseURL> with the original error as cause.
Abort: an abort via opencode's signal is rethrown untouched.
Timeout/retries: fixed internal 30 s timeout combined with opencode's signal via AbortSignal.any; not configurable. No retries; a 429 keeps its status in the message so opencode's cooldown logic can see it (verify in the runtime checks).
Long queries: sent as-is; the server's 400 invalid_request flows through the error path.
Resolved with the user (all recommendations accepted).
- **Parsing:** accept `data` as an array or `data.results` as an array; any other shape throws "unexpected response shape".
- **Mapping:** `{ url, title, content: snippet || description || "", time: {} }`. `time` always `{}` (inner shape unverified); `publishedDate` not mapped.
- **Empty/malformed:** empty list returns `[]`, not an error. Entries without a string `url` are dropped; missing `title` falls back to `url`. No warnings logged.
- **API errors:** throw `Error("fastCRW <status> <error_code>: <error>")`; HTTP 200 with `success:false` handled the same (status 200). Fixed hints only for 401 ("check apiKey or CRW_API_KEY") and 503 `search_disabled` ("the server has no search backend configured"). The token never appears in any message.
- **Non-JSON:** throw `fastCRW <status>: non-JSON response` plus the first 200 chars of the body.
- **Network errors:** throw `fastCRW: cannot reach <baseURL>` with the original error as `cause`.
- **Abort:** an abort via opencode's `signal` is rethrown untouched.
- **Timeout/retries:** fixed internal 30 s timeout combined with opencode's `signal` via `AbortSignal.any`; not configurable. No retries; a 429 keeps its status in the message so opencode's cooldown logic can see it (verify in the runtime checks).
- **Long queries:** sent as-is; the server's 400 `invalid_request` flows through the error path.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Map: #1
Question
Both research tickets and the config surface are settled. Decide how the plugin maps a fastCRW response to opencode results and how it reports failures: parsing both
data[]anddata.resultsshapes,snippet/descriptiontocontent, thetimefield, empty results,success:falseand eacherror_code(e.g. 429, 503search_disabled), non-JSON bodies, network errors, abort viasignal, and what error messages the user sees. Fallback to built-ins is off (fastCRW is the only provider).Resolved with the user (all recommendations accepted).
dataas an array ordata.resultsas an array; any other shape throws "unexpected response shape".{ url, title, content: snippet || description || "", time: {} }.timealways{}(inner shape unverified);publishedDatenot mapped.[], not an error. Entries without a stringurlare dropped; missingtitlefalls back tourl. No warnings logged.Error("fastCRW <status> <error_code>: <error>"); HTTP 200 withsuccess:falsehandled the same (status 200). Fixed hints only for 401 ("check apiKey or CRW_API_KEY") and 503search_disabled("the server has no search backend configured"). The token never appears in any message.fastCRW <status>: non-JSON responseplus the first 200 chars of the body.fastCRW: cannot reach <baseURL>with the original error ascause.signalis rethrown untouched.signalviaAbortSignal.any; not configurable. No retries; a 429 keeps its status in the message so opencode's cooldown logic can see it (verify in the runtime checks).invalid_requestflows through the error path.