Merge origin/master into worktree/web-plugin-config
Three seams: the tsconfig path map gained a mapping on each side and keeps both; the event-producer matrix is generated, so it was regenerated rather than hand-merged row by row.
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/web/tool-web/README.md
|
||||
README.md: 643da4e2f083c2efabd39a462290559ddbd291c8
|
||||
README.md: 6a7ca42773f4a62b75d6077c5cdd892b0ccfdbee
|
||||
README.zh.md: 7b52f2b08f393a584258dea1a216d9124ec8760a
|
||||
@@ -134,5 +134,5 @@ Append-only; newly visible content follows the reusable request prefix and does
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **HTML→markdown conversion degrades on inputs GFM cannot safely represent** — [turndown](https://github.com/mixmark-io/turndown) (with GFM tables/strikethrough) converts at most `fetchMaxOutputChars` source characters through a real DOM. A conservative 512-level lexical guard passes deeply or ambiguously nested bodies through as raw HTML, conversion exceptions do the same, and table `colspan` is ignored because GFM has no spanning-cell representation; these bounds avoid blocking the event loop or expanding output from an untrusted numeric attribute ([archived dependency decision](../../../.agents/notes/archived/simplification/2026-07-26-turndown-for-tool-web-html-markdown.md)).
|
||||
- **The model-facing surface is minimal by design, with promotions deferred** — `max_results` stays a config bound (not a model argument), and `web_fetch` takes only `url` (no `format`/`prompt`/LLM-summarization mode); both are named later steps in [the seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md).
|
||||
- **The model-facing API is minimal by design, with promotions deferred** — `max_results` stays a config bound (not a model argument), and `web_fetch` takes only `url` (no `format`/`prompt`/LLM-summarization mode); both are named later steps in [the seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md).
|
||||
- **No web-specific permission policy** — both tools execute without requesting `ctx.approval`; a deployment that needs confirmation must add a `tools/pre-execute` policy, and the package does not define persistent URL/domain grants.
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/web/web-search-deepseek/README.md
|
||||
README.md: 1e90f947b4a58288722307aaed50c4889cfe7cb4
|
||||
README.md: 25162a3e82a05bb17f31a69bc65f6552e42906ad
|
||||
README.zh.md: 21962bcd390f253f899000be7273a79485821018
|
||||
@@ -38,7 +38,7 @@ The entry above is the base layer of the `web-search-deepseek` Settings section:
|
||||
|
||||
## Mapping
|
||||
|
||||
DeepSeek returns no provider-generated answer surface this provider trusts as `content`, so `content` is omitted. `sources[]` comes from `web_search_result` items inside `web_search_tool_result` blocks: `url` ← `url`, `title` ← `title`, and `publishedAt` ← `page_age`. Snippets live separately as URL-keyed `cited_text` entries in a text block's `citations[]`; the provider joins them, leaving `snippet` absent when no excerpt exists.
|
||||
DeepSeek returns no provider-generated answer content this provider trusts as `content`, so `content` is omitted. `sources[]` comes from `web_search_result` items inside `web_search_tool_result` blocks: `url` ← `url`, `title` ← `title`, and `publishedAt` ← `page_age`. Snippets live separately as URL-keyed `cited_text` entries in a text block's `citations[]`; the provider joins them, leaving `snippet` absent when no excerpt exists.
|
||||
|
||||
Results are deduplicated by URL because one request may surface the same page across searches. DeepSeek exposes `maxUses`, not a result-count knob, so the seam enforces `maxResults` by truncating `sources[]` and setting `truncated`.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import type {
|
||||
export const DEEPSEEK_PROVIDER_ID = 'deepseek-official'
|
||||
|
||||
/**
|
||||
* Default endpoint: DeepSeek's Anthropic-compatible surface, `/v1` included
|
||||
* Default endpoint: DeepSeek's Anthropic-compatible API, `/v1` included
|
||||
* (`/messages` is appended). This is NOT the chat-completions base
|
||||
* (`https://api.deepseek.com`) `@deepseek-ai/dsh-llm-deepseek` uses, so this
|
||||
* provider does NOT reuse `$DEEPSEEK_BASE_URL` — only the API key is shared.
|
||||
@@ -111,7 +111,7 @@ export interface DeepSeekSearchProviderOptions {
|
||||
|
||||
/**
|
||||
* Build a `url → cited_text` map from every `text` block's `citations[]`. This
|
||||
* is the snippet surface: Anthropic `web_search_result` items carry
|
||||
* is the snippet source: Anthropic `web_search_result` items carry
|
||||
* `url`/`title`/`page_age` but typically NO inline snippet — the excerpt lives
|
||||
* in a separate `text` block's citation, keyed by `url` (first occurrence wins).
|
||||
*
|
||||
|
||||
@@ -14,13 +14,13 @@ export interface WebSearchResultItem {
|
||||
page_age?: string | null
|
||||
}
|
||||
|
||||
/** A `web_search_tool_result` content block: the citeable result surface. */
|
||||
/** A `web_search_tool_result` content block: the citeable result shape. */
|
||||
export interface WebSearchToolResultBlock {
|
||||
type: 'web_search_tool_result'
|
||||
content?: WebSearchResultItem[]
|
||||
}
|
||||
|
||||
/** One citation location inside a `text` block (the snippet surface). */
|
||||
/** One citation location inside a `text` block (the snippet source). */
|
||||
export interface CitationLocation {
|
||||
type?: string
|
||||
url?: string | null
|
||||
|
||||
@@ -153,7 +153,7 @@ export class PerplexitySearchProvider implements WebSearchProvider {
|
||||
}
|
||||
|
||||
// These two predicates are intentionally local: exporting generic internals
|
||||
// from the public web seam would cost more API surface than these pure checks.
|
||||
// from the public web seam would add more API than these pure checks.
|
||||
/* jscpd:ignore-start */
|
||||
/** True for a fetch/`AbortSignal` abort, surfaced as `WEB_ABORTED`. */
|
||||
function isAbortError(error: unknown): boolean {
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface PerplexityRequest {
|
||||
messages: { role: 'user'; content: string }[]
|
||||
}
|
||||
|
||||
/** One structured search result (the preferred citation surface). */
|
||||
/** One structured search result (the preferred citation shape). */
|
||||
export interface PerplexitySearchResult {
|
||||
url: string
|
||||
title?: string | null
|
||||
@@ -22,7 +22,7 @@ export interface PerplexitySearchResult {
|
||||
/** Perplexity's response envelope. */
|
||||
export interface PerplexityResponse {
|
||||
choices?: { message?: { content?: string | null } }[]
|
||||
/** Structured citation surface (preferred). */
|
||||
/** Structured citation data (preferred). */
|
||||
search_results?: PerplexitySearchResult[]
|
||||
/** URL-only citation fallback. */
|
||||
citations?: string[]
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/web/web/README.md
|
||||
README.md: 2acb5022a83c08c33a26be626a93b7355c07a0ed
|
||||
README.md: 237c7e28416a1f920042d2713a2b2e67dc882c42
|
||||
README.zh.md: b77b0a897082dba01e10be3f7b0ca3b3f0260a9f
|
||||
@@ -39,7 +39,7 @@ Selection never depends on registration, config, or HMR order. A capability has
|
||||
| no id, no usable provider | `WEB_PROVIDER_UNAVAILABLE` |
|
||||
| no id, multiple usable providers | `WEB_PROVIDER_AMBIGUOUS` |
|
||||
|
||||
The failure branches throw `WebError`, whose structured code (plus message detail — the missing id, the ambiguous candidate set) is the surface callers route on. A provider's own `available()` is a cheap local check (credential presence, parseable config) that feeds this execution-time selection and **must not make network calls**; `dsh-tool-web` never calls it — the tool executes through `ctx.web.search()`/`fetch()` and routes on the thrown codes, so provider selection has one owner.
|
||||
The failure branches throw `WebError`, whose structured code (plus message detail — the missing id, the ambiguous candidate set) is the direct callers route on. A provider's own `available()` is a cheap local check (credential presence, parseable config) that feeds this execution-time selection and **must not make network calls**; `dsh-tool-web` never calls it — the tool executes through `ctx.web.search()`/`fetch()` and routes on the thrown codes, so provider selection has one owner.
|
||||
|
||||
## Vocabulary
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface WebSearchRequest {
|
||||
* Normalized search outcome. `content` is optional provider-generated answer
|
||||
* text or summary (Exa and DeepSeek return none; Perplexity returns a
|
||||
* generated answer).
|
||||
* `sources[]` is the portable citation surface. `truncated` is set by the seam
|
||||
* `sources[]` is the portable citation shape. `truncated` is set by the seam
|
||||
* when it cut `sources[]` down to `maxResults`.
|
||||
*/
|
||||
export interface WebSearchResult {
|
||||
|
||||
Reference in New Issue
Block a user