feat: implement OpenAI-powered search routing (#97)#122
feat: implement OpenAI-powered search routing (#97)#122Pitrat-wav wants to merge 11 commits intotscircuit:mainfrom
Conversation
routes/api/search.tsx
Outdated
| openai = getOpenAiClient() | ||
| } catch (err) { | ||
| // If not configured, only fail for complex queries | ||
| const isComplex = q && (q.split(" ").length > 1 || /[0-9]/.test(q)) |
There was a problem hiding this comment.
The complex query detection logic incorrectly flags simple LCSC part number queries (like "C123") as complex because they contain numbers. This will cause these simple queries to fail with a 400 error when OPENAI_API_KEY is not configured, even though the executeGeneralSearch function handles them perfectly fine without OpenAI (lines 55-59).
Fix by excluding LCSC format from complex detection:
const isComplex = q && !(/^c\d+$/i.test(q)) && (q.split(" ").length > 1 || /[0-9]/.test(q))| const isComplex = q && (q.split(" ").length > 1 || /[0-9]/.test(q)) | |
| const isComplex = q && !(/^c\d+$/i.test(q)) && (q.split(" ").length > 1 || /[0-9]/.test(q)) |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
| let specQuery = ctx.db | ||
| .selectFrom(routing.table as any) | ||
| .selectAll() | ||
| .limit(limit) | ||
| for (const [k, v] of Object.entries(routing.filters || {})) { | ||
| specQuery = specQuery.where(k as any, "=", v as any) | ||
| } |
There was a problem hiding this comment.
The routing.table value from OpenAI response is used directly in database query without validation. If OpenAI returns an unexpected table name or if the response is manipulated, this could query arbitrary database tables or cause runtime errors.
Should validate against allowed tables:
const allowedTables = ['resistor', 'capacitor', 'diode', 'led', 'voltage_regulator', 'microcontroller'];
if (!allowedTables.includes(routing.table)) {
return executeGeneralSearch(routing.q || q)
}
let specQuery = ctx.db
.selectFrom(routing.table as any)| let specQuery = ctx.db | |
| .selectFrom(routing.table as any) | |
| .selectAll() | |
| .limit(limit) | |
| for (const [k, v] of Object.entries(routing.filters || {})) { | |
| specQuery = specQuery.where(k as any, "=", v as any) | |
| } | |
| const allowedTables = ['resistor', 'capacitor', 'diode', 'led', 'voltage_regulator', 'microcontroller'] | |
| if (!allowedTables.includes(routing.table)) { | |
| return executeGeneralSearch(routing.q || q) | |
| } | |
| let specQuery = ctx.db | |
| .selectFrom(routing.table as any) | |
| .selectAll() | |
| .limit(limit) | |
| for (const [k, v] of Object.entries(routing.filters || {})) { | |
| specQuery = specQuery.where(k as any, "=", v as any) | |
| } |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
Fixes failing tests for queries like 'STM32F401RCT6', '555 Timer', etc. These simple part numbers should not require OpenAI API key. Payment info: Wise or USDC/SOL to GKqwBPH4m6bkZj35j3WVvyJHHdUxddtmETH6ZA8W1aZH (PayPal unavailable in Uzbekistan).
|
|
||
| #MANUAL folder gets created on build, ignore it | ||
| /MANUAL No newline at end of file | ||
| /MANUALbun.lock |
There was a problem hiding this comment.
The file paths are concatenated on a single line. This should be two separate entries:
/MANUAL
bun.lock
Currently this ignores a file called "MANUALbun.lock" instead of ignoring both "/MANUAL" and "bun.lock" separately.
| /MANUALbun.lock | |
| /MANUAL | |
| bun.lock |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
- Add cf-proxy as a workspace in root package.json to ensure dependencies are properly linked - Pin kysely-d1 to exact version 0.4.0 to avoid version mismatches This should resolve 'Cannot find package kysely-d1' errors in CI.
This PR adds an intelligent search router powered by OpenAI.
Changes:
getOpenAiClientutility./api/searchto route natural language queries to specialized component tables (resistor, capacitor, etc.).OPENAI_API_KEYis missing for complex queries.Verified build and formatting pass locally.