fix(tool-web): share one source projection between search execute and meta
The web_search execute result and searchMetaFromValue each spread the
same {url, title?, snippet?, publishedAt?} projection over a seam source,
which the duplication gate flags as a clone. Extract projectSource, typed
on the seam's WebSearchSource, so both sites carry a byte-identical shape
from one definition.
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
import type { Context } from 'cordis'
|
import type { Context } from 'cordis'
|
||||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||||
import type { GenericCallView, JsonValue, ToolResult, WebSearchResultView, WebSource } from '@deepseek-ai/dsh-tools'
|
import type { GenericCallView, JsonValue, ToolResult, WebSearchResultView, WebSource } from '@deepseek-ai/dsh-tools'
|
||||||
import type { WebSearchResult } from '@deepseek-ai/dsh-web'
|
import type { WebSearchResult, WebSearchSource } from '@deepseek-ai/dsh-web'
|
||||||
import type {} from '@deepseek-ai/dsh-system-prompt'
|
import type {} from '@deepseek-ai/dsh-system-prompt'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,6 +101,28 @@ export interface WebSearchMeta {
|
|||||||
answer?: string
|
answer?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project one seam source into a plain object that omits every absent optional
|
||||||
|
* field. Shared by the canonical `execute` result and its replayable
|
||||||
|
* presentation meta so both carry byte-identical source shapes.
|
||||||
|
*
|
||||||
|
* @param source - one source from the `ctx.web` search outcome.
|
||||||
|
* @returns `{ url }` plus each present optional field.
|
||||||
|
*/
|
||||||
|
function projectSource(source: WebSearchSource): {
|
||||||
|
url: string
|
||||||
|
title?: string
|
||||||
|
snippet?: string
|
||||||
|
publishedAt?: string
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
url: source.url,
|
||||||
|
...source.title !== undefined ? { title: source.title } : {},
|
||||||
|
...source.snippet !== undefined ? { snippet: source.snippet } : {},
|
||||||
|
...source.publishedAt !== undefined ? { publishedAt: source.publishedAt } : {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project a validated `web_search` output value into its replayable
|
* Project a validated `web_search` output value into its replayable
|
||||||
* presentation meta ({@link WebSearchMeta} as opaque JSON).
|
* presentation meta ({@link WebSearchMeta} as opaque JSON).
|
||||||
@@ -110,12 +132,7 @@ export interface WebSearchMeta {
|
|||||||
*/
|
*/
|
||||||
export function searchMetaFromValue(value: WebSearchResult): JsonValue {
|
export function searchMetaFromValue(value: WebSearchResult): JsonValue {
|
||||||
return {
|
return {
|
||||||
sources: value.sources.map(source => ({
|
sources: value.sources.map(projectSource),
|
||||||
url: source.url,
|
|
||||||
...source.title !== undefined ? { title: source.title } : {},
|
|
||||||
...source.snippet !== undefined ? { snippet: source.snippet } : {},
|
|
||||||
...source.publishedAt !== undefined ? { publishedAt: source.publishedAt } : {},
|
|
||||||
})),
|
|
||||||
truncated: value.truncated,
|
truncated: value.truncated,
|
||||||
...value.content !== undefined ? { answer: value.content } : {},
|
...value.content !== undefined ? { answer: value.content } : {},
|
||||||
}
|
}
|
||||||
@@ -238,12 +255,7 @@ export function applyWebSearchTool(ctx: Context, maxResults: number, timeoutMs:
|
|||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
...result.content !== undefined ? { content: result.content } : {},
|
...result.content !== undefined ? { content: result.content } : {},
|
||||||
sources: result.sources.map(source => ({
|
sources: result.sources.map(projectSource),
|
||||||
url: source.url,
|
|
||||||
...source.title !== undefined ? { title: source.title } : {},
|
|
||||||
...source.snippet !== undefined ? { snippet: source.snippet } : {},
|
|
||||||
...source.publishedAt !== undefined ? { publishedAt: source.publishedAt } : {},
|
|
||||||
})),
|
|
||||||
truncated: result.truncated,
|
truncated: result.truncated,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user