From f55990c25e050899e105ec2b1977d218628eced2 Mon Sep 17 00:00:00 2001 From: seb Date: Mon, 5 Oct 2026 14:54:23 +0200 Subject: [PATCH] u --- docs/api/routes/serper/images.md | 2 +- src/api/routes/serper.js | 6 ++---- src/config/env.js | 1 - src/tools/analyze-image.js | 5 ++++- src/tools/search-images.js | 13 ++++++++++--- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/api/routes/serper/images.md b/docs/api/routes/serper/images.md index a60c1c5..753c064 100644 --- a/docs/api/routes/serper/images.md +++ b/docs/api/routes/serper/images.md @@ -5,7 +5,7 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). Search images via Serper.dev and stream WebP thumbnails (SSE) Queries Google Image search via `https://google.serper.dev/images` using the -company setting `keys.serper` (or server `SERPER_API_KEY`), and streams the +company setting `keys.serper`, and streams the results via Server-Sent Events (`text/event-stream`). 1. First emits an `images` event with the full search result list (including `imageUrl`). diff --git a/src/api/routes/serper.js b/src/api/routes/serper.js index 108c621..933fa80 100644 --- a/src/api/routes/serper.js +++ b/src/api/routes/serper.js @@ -1,6 +1,5 @@ import sharp from 'sharp'; import * as dbCompanySetting from '../../db/companysetting.js'; -import env from '../../config/env.js'; import { crawlAndProcessImage } from '../../services/imageCrop.js'; const CONCURRENCY = 6; @@ -98,7 +97,7 @@ export function register(app, basePath = '') { * summary: Search images via Serper.dev and stream WebP thumbnails (SSE) * description: | * Queries Google Image search via `https://google.serper.dev/images` using the - * company setting `keys.serper` (or server `SERPER_API_KEY`), and streams the + * company setting `keys.serper`, and streams the * results via Server-Sent Events (`text/event-stream`). * * 1. First emits an `images` event with the full search result list (including `imageUrl`). @@ -204,10 +203,9 @@ export function register(app, basePath = '') { let apiKey = null; try { const setting = await dbCompanySetting.getByKey(req.user.id, 'keys.serper', { maskWriteonly: false }); - apiKey = setting?.value || env.serperApiKey; + apiKey = setting?.value?.trim() || null; } catch (err) { console.warn('Serper images: failed to read company setting keys.serper:', err?.message || err); - apiKey = env.serperApiKey; } if (!apiKey) { diff --git a/src/config/env.js b/src/config/env.js index 4fb3839..259dae7 100644 --- a/src/config/env.js +++ b/src/config/env.js @@ -29,7 +29,6 @@ export default { openrouterFreeKey: process.env.OPENROUTER_FREE_KEY, openrouterFreeModel: process.env.OPENROUTER_FREE_MODEL || 'openrouter/free', openrouterPaidModel: process.env.OPENROUTER_PAID_MODEL || 'openai/gpt-6-luna:floor', - serperApiKey: process.env.SERPER_API_KEY, sqlite: { filename: process.env.SQLITE_PATH || process.env.SQLITE_FILENAME || resolve(__dirname, '../../data/dash.db'), }, diff --git a/src/tools/analyze-image.js b/src/tools/analyze-image.js index 9a336c7..b23d7e3 100644 --- a/src/tools/analyze-image.js +++ b/src/tools/analyze-image.js @@ -381,7 +381,10 @@ export function createAnalyzeImageTool({ googleAuthId, model }) { role: 'user', content: [ { type: 'text', text }, - { type: 'image_url', imageUrl: { url: `data:image/webp;base64,${webp.toString('base64')}` } }, + { + type: 'image_url', + image_url: { url: `data:image/webp;base64,${webp.toString('base64')}` }, + }, ], }, ], diff --git a/src/tools/search-images.js b/src/tools/search-images.js index fe6f95e..f246e50 100644 --- a/src/tools/search-images.js +++ b/src/tools/search-images.js @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import sharp from 'sharp'; import { defineTool, ToolError } from 'libllmorbiter'; -import env from '../config/env.js'; +import * as dbCompanySetting from '../db/companysetting.js'; import { prepareVfs, syncVfsToDb } from './vfs.js'; const SERPER_ENDPOINT = 'https://google.serper.dev/images'; @@ -175,10 +175,17 @@ export function createSearchImagesTool({ googleAuthId }) { } const wanted = Math.min(count, MAX_COUNT); - const apiKey = env.serperApiKey?.trim(); + let apiKey = null; + try { + const setting = await dbCompanySetting.getByKey(googleAuthId, 'keys.serper', { maskWriteonly: false }); + apiKey = setting?.value?.trim() || null; + } catch (err) { + console.warn('search_images: failed to read company setting keys.serper:', err?.message || err); + } + if (!apiKey) { throw new ToolError( - 'search_images is unavailable: SERPER_API_KEY is not configured on the server. ' + + 'search_images is unavailable: Serper API key not configured (companysetting: keys.serper). ' + 'Use a direct image URL with javascript_execute instead.' ); }