u
This commit is contained in:
@@ -117,7 +117,7 @@ async function buildSystemPrompt(vfsRoot, googleAuthId) {
|
||||
'6. patch: Create, overwrite, or search-and-replace text in a VFS file. This is the only text write path — it also creates SKILL files.',
|
||||
'7. search_images: Search Google Images and store the candidates in the VFS as AVIF files.',
|
||||
'8. analyze_image: Have a vision model look at up to 9 images (VFS paths or "image/<fullHash>") and return its judgement. This is how you "see" — never claim to have inspected an image yourself.',
|
||||
'9. web_search: Search the web using Google Search. Returns organic results, snippets, and knowledge graph. Supports time filters via `tbs` ("qdr:d" past day, "qdr:w" past week, "qdr:m" past month, "qdr:y" past year).',
|
||||
'9. web_search: Search the web using Google Search. Returns organic results, snippets, and knowledge graph. Supports filtering by timePeriod ("day", "week", "month", "year") — always use "day" or "week" for news and recent events.',
|
||||
'10. url_get: Fetch and scrape the content and markdown of a web page/URL.',
|
||||
'11. pdf_read: Read and convert PDF or text files. Converts PDF to layout-preserved text ("txt") or renders pages into PNG images ("png") saved in the VFS images/ folder.',
|
||||
'12. reset_vfs: Delete files, images, and artifacts stored in the virtual filesystem (VFS) to free up storage or clean up. SKILL files are exempt and survive.',
|
||||
|
||||
@@ -5,30 +5,30 @@ const SERPER_SEARCH_ENDPOINT = 'https://google.serper.dev/search';
|
||||
const SEARCH_TIMEOUT_MS = 15_000;
|
||||
|
||||
/**
|
||||
* Normalizes user/model-supplied time filter (`tbs`) into Google's qdr syntax.
|
||||
* Normalizes user/model-supplied time filter into Google's qdr syntax.
|
||||
* Supported:
|
||||
* - "qdr:d" or "d" / "day" / "24h" -> "qdr:d"
|
||||
* - "qdr:w" or "w" / "week" -> "qdr:w"
|
||||
* - "qdr:m" or "m" / "month" -> "qdr:m"
|
||||
* - "qdr:y" or "y" / "year" -> "qdr:y"
|
||||
* - "qdr:h" or "h" / "hour" -> "qdr:h"
|
||||
* - "day" / "24h" / "d" -> "qdr:d"
|
||||
* - "week" / "w" -> "qdr:w"
|
||||
* - "month" / "m" -> "qdr:m"
|
||||
* - "year" / "y" -> "qdr:y"
|
||||
* - "hour" / "h" -> "qdr:h"
|
||||
*
|
||||
* @param {string|null} tbs
|
||||
* @param {string|null} time
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
function normalizeTbs(tbs) {
|
||||
if (!tbs || typeof tbs !== 'string') return undefined;
|
||||
const trimmed = tbs.trim().toLowerCase();
|
||||
function normalizeTbs(time) {
|
||||
if (!time || typeof time !== 'string') return undefined;
|
||||
const trimmed = time.trim().toLowerCase();
|
||||
if (!trimmed) return undefined;
|
||||
|
||||
if (trimmed === 'day' || trimmed === 'd' || trimmed === '24h' || trimmed === 'today') return 'qdr:d';
|
||||
if (trimmed === 'week' || trimmed === 'w') return 'qdr:w';
|
||||
if (trimmed === 'month' || trimmed === 'm') return 'qdr:m';
|
||||
if (trimmed === 'year' || trimmed === 'y') return 'qdr:y';
|
||||
if (trimmed === 'hour' || trimmed === 'h') return 'qdr:h';
|
||||
if (trimmed.startsWith('qdr:')) return trimmed;
|
||||
if (trimmed === 'd' || trimmed === 'day' || trimmed === '24h') return 'qdr:d';
|
||||
if (trimmed === 'w' || trimmed === 'week') return 'qdr:w';
|
||||
if (trimmed === 'm' || trimmed === 'month') return 'qdr:m';
|
||||
if (trimmed === 'y' || trimmed === 'year') return 'qdr:y';
|
||||
if (trimmed === 'h' || trimmed === 'hour') return 'qdr:h';
|
||||
|
||||
return trimmed;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,8 +91,9 @@ export function createWebSearchTool({ googleAuthId }) {
|
||||
description:
|
||||
'Search the web using Google Search via Serper.dev. ' +
|
||||
'Returns raw search results as-is from Serper. ' +
|
||||
'Supports time filters via `tbs` ("qdr:d" for past day, "qdr:w" for past week, ' +
|
||||
'"qdr:m" for past month, "qdr:y" for past year). Each page returns 10 results.',
|
||||
'Supports filtering fresh content with timePeriod ("day", "week", "month", "year"). ' +
|
||||
'Always use "day" or "week" when searching for news, recent events, or current status. ' +
|
||||
'Each page returns 10 results.',
|
||||
strict: false,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
@@ -103,11 +104,13 @@ export function createWebSearchTool({ googleAuthId }) {
|
||||
type: 'string',
|
||||
description: 'Search query, e.g. "apple inc" or "vite vue3 release".',
|
||||
},
|
||||
tbs: {
|
||||
timePeriod: {
|
||||
type: 'string',
|
||||
enum: ['day', 'week', 'month', 'year'],
|
||||
description:
|
||||
'Time filter for results: "qdr:d" (past 24h / day), "qdr:w" (past week), ' +
|
||||
'"qdr:m" (past month), "qdr:y" (past year). Short forms like "d", "w", "m", "y" are also accepted.',
|
||||
'Filter results by time period: "day" (past 24 hours), "week" (past week), ' +
|
||||
'"month" (past month), or "year" (past year). ' +
|
||||
'Always use "day" or "week" when searching for news, recent events, or current status.',
|
||||
},
|
||||
gl: {
|
||||
type: 'string',
|
||||
@@ -123,7 +126,7 @@ export function createWebSearchTool({ googleAuthId }) {
|
||||
},
|
||||
},
|
||||
},
|
||||
invoke: async ({ query, tbs, gl = 'de', hl = 'de', page = 1 } = {}, { signal } = {}) => {
|
||||
invoke: async ({ query, timePeriod, tbs, gl = 'de', hl = 'de', page = 1 } = {}, { signal } = {}) => {
|
||||
const term = typeof query === 'string' ? query.trim() : '';
|
||||
if (!term) {
|
||||
throw new ToolError('web_search requires a non-empty "query".');
|
||||
@@ -134,7 +137,7 @@ export function createWebSearchTool({ googleAuthId }) {
|
||||
throw new ToolError(`"page" must be a positive integer (received ${page}).`);
|
||||
}
|
||||
|
||||
const normalizedTbs = normalizeTbs(tbs);
|
||||
const normalizedTbs = normalizeTbs(timePeriod || tbs);
|
||||
|
||||
let apiKey = null;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user