@mrclrchtr/supi-web 11.4.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +9 -9
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/package.json +2 -2
- package/src/tool/namespace.ts +12 -0
- package/src/tool/web_docs_fetch/execute.ts +2 -2
- package/src/tool/web_docs_fetch/guidance.ts +1 -1
- package/src/tool/web_docs_fetch/register.ts +2 -0
- package/src/tool/web_docs_fetch/render.ts +1 -1
- package/src/tool/web_docs_fetch/spec.ts +7 -1
- package/src/tool/web_docs_search/execute.ts +2 -2
- package/src/tool/web_docs_search/register.ts +2 -0
- package/src/tool/web_docs_search/render.ts +1 -1
- package/src/tool/web_docs_search/result.ts +1 -1
- package/src/tool/web_docs_search/spec.ts +7 -1
- package/src/tool/web_fetch_md/execute.ts +4 -4
- package/src/tool/web_fetch_md/fetch.ts +2 -2
- package/src/tool/web_fetch_md/input.ts +4 -4
- package/src/tool/web_fetch_md/register.ts +2 -0
- package/src/tool/web_fetch_md/render.ts +2 -2
- package/src/tool/web_fetch_md/spec.ts +6 -0
- package/src/tool/web_search/register.ts +2 -0
- package/src/tool/web_search/spec.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [12.0.0]
|
|
4
|
+
|
|
5
|
+
- **Breaking:** Web tool parameters are camelCase, like every other SuPi tool. `web_fetch_md`: `output_mode` → `outputMode`, `fetch_mode` → `fetchMode`, `abs_links` → `absLinks`, `timeout_ms` → `timeoutMs`. `web_docs_search`: `library_name` → `libraryName`. `web_docs_fetch`: `library_id` → `libraryId`. Values such as `firecrawl_fallback` are unchanged. Update codemode scripts and saved prompts that pass the old names; they are now rejected as unknown fields.
|
|
6
|
+
- Codemode now lists the Web tools under a `web` namespace heading, so scripts can find them with `describeNamespace("web")` or `searchTools(query, { namespace: "web" })`. Every Web tool now declares audited `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` annotations, which permission extensions can read from `pi.getAllTools()`. They are read-only and open-world ([#582](https://github.com/mrclrchtr/supi/issues/582)).
|
|
7
|
+
|
|
3
8
|
## [11.4.0]
|
|
4
9
|
|
|
5
10
|
- Guides agents toward the library documentation tools for library and framework usage questions, while keeping web search available for issues, release notes, and news.
|
package/README.md
CHANGED
|
@@ -63,12 +63,12 @@ Results describe the evidence returned by the provider, not exhaustive coverage
|
|
|
63
63
|
|
|
64
64
|
```javascript
|
|
65
65
|
const libraries = await tools.web_docs_search({
|
|
66
|
-
|
|
66
|
+
libraryName: "react",
|
|
67
67
|
query: "effect cleanup",
|
|
68
68
|
});
|
|
69
69
|
if (libraries.results.length > 0) {
|
|
70
70
|
const docs = await tools.web_docs_fetch({
|
|
71
|
-
|
|
71
|
+
libraryId: libraries.results[0].id,
|
|
72
72
|
query: "effect cleanup",
|
|
73
73
|
raw: true,
|
|
74
74
|
});
|
|
@@ -84,7 +84,7 @@ HTTP fetch failures include the requested URL and response status in the error m
|
|
|
84
84
|
```javascript
|
|
85
85
|
for (const url of urls) {
|
|
86
86
|
try {
|
|
87
|
-
const page = await tools.web_fetch_md({ url,
|
|
87
|
+
const page = await tools.web_fetch_md({ url, outputMode: "file" });
|
|
88
88
|
text({ url, filePath: page.filePath });
|
|
89
89
|
} catch (error) {
|
|
90
90
|
text({ url, error: String(error) });
|
|
@@ -117,7 +117,7 @@ Search results are provider-reported source material. A source date can be a pub
|
|
|
117
117
|
|
|
118
118
|
It follows redirects and, for HTML, removes scripts and styles while preserving headings, links, lists, code blocks, and tables.
|
|
119
119
|
|
|
120
|
-
Native Markdown is returned unchanged, including relative links and code examples. For HTML conversion, `
|
|
120
|
+
Native Markdown is returned unchanged, including relative links and code examples. For HTML conversion, `absLinks` defaults to `true`; set it to `false` to preserve original link and image destinations. Unsafe URL schemes are removed in either HTML mode.
|
|
121
121
|
|
|
122
122
|
### Optional Firecrawl retrieval
|
|
123
123
|
|
|
@@ -125,7 +125,7 @@ Direct fetching remains the default and needs no API key. To allow Firecrawl, op
|
|
|
125
125
|
|
|
126
126
|
Export `FIRECRAWL_API_KEY` before starting Pi. The key stays in the environment, not settings. Enabling without a key saves the preference and shows a warning; direct fetching remains available.
|
|
127
127
|
|
|
128
|
-
The agent can select one `
|
|
128
|
+
The agent can select one `fetchMode`:
|
|
129
129
|
|
|
130
130
|
| Mode | Behavior |
|
|
131
131
|
|---|---|
|
|
@@ -140,19 +140,19 @@ For a public page blocked with HTTP 403:
|
|
|
140
140
|
```javascript
|
|
141
141
|
const page = await tools.web_fetch_md({
|
|
142
142
|
url: "https://example.com/article",
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
fetchMode: "firecrawl_fallback",
|
|
144
|
+
outputMode: "file",
|
|
145
145
|
});
|
|
146
146
|
return page;
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
-
For JS-rendered content, select `
|
|
149
|
+
For JS-rendered content, select `fetchMode: "firecrawl"` instead. The key is read only when Firecrawl is actually needed and is not returned in results. Firecrawl receives the requested URL and may consume credits, including for cached results. The tool requests Markdown only, with no structured-extraction add-ons or client-side retries. Firecrawl manages its own retrieval pipeline.
|
|
150
150
|
|
|
151
151
|
`firecrawl_fallback` runs only after the direct pipeline ends with HTTP 403—not for authentication errors (401), missing pages, rate limits, network failures, or cancellation. Neither mode retries Firecrawl failures through another provider. Both modes reject credential-bearing URLs, local/reserved hosts, and hosts resolving to non-public addresses before sharing them. Do not select Firecrawl for signed URLs or login-protected, private, or paywalled pages. These checks are not a sandbox or proof that a page is publicly accessible.
|
|
152
152
|
|
|
153
153
|
Firecrawl results retain the requested source URL and include `retrieval.provider: "firecrawl"`, plus `cacheState` and `cachedAt` when supplied. Both inline/file responses disclose retrieval provenance. [Firecrawl caching](https://docs.firecrawl.dev/features/scrape#caching-and-freshness) allows cached content up to two days old by default; missing cache metadata does not establish freshness. Empty, unsuccessful, warning-bearing, and recognizable access-block responses are failures, not usable article content. A null or absent warning is accepted. Firecrawl can still return incomplete or noisy content, so inspect it before relying on it.
|
|
154
154
|
|
|
155
|
-
`
|
|
155
|
+
`timeoutMs` applies to each direct HTTP request and to the complete Firecrawl attempt, including DNS validation and response reading; it is not a whole-tool deadline. The provider timeout is clamped to its supported 1–300 second range, while the local deadline still enforces shorter budgets. Cancellation is forwarded to Firecrawl. Native/Firecrawl Markdown remains unchanged, so `absLinks` applies only to local HTML conversion.
|
|
156
156
|
|
|
157
157
|
### Large pages
|
|
158
158
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-web",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Public web pages, web search sources, and focused Context7 docs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@mozilla/readability": "^0.6.0",
|
|
40
40
|
"turndown": "^7.2.0",
|
|
41
41
|
"turndown-plugin-gfm": "^1.0.2",
|
|
42
|
-
"@mrclrchtr/supi-core": "
|
|
42
|
+
"@mrclrchtr/supi-core": "12.0.0"
|
|
43
43
|
},
|
|
44
44
|
"bundledDependencies": [
|
|
45
45
|
"@mrclrchtr/supi-core"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ToolNamespace } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
/** Codemode namespace shared by every `web_*` tool. */
|
|
4
|
+
export const WEB_TOOL_NAMESPACE: ToolNamespace = {
|
|
5
|
+
name: "web",
|
|
6
|
+
description: "Public web search, page fetching, and library documentation lookup.",
|
|
7
|
+
instructions: [
|
|
8
|
+
"For library or framework usage, call web_docs_search for a libraryId, then web_docs_fetch.",
|
|
9
|
+
"Use web_search for current or external sources such as issues, release notes, or news.",
|
|
10
|
+
"Use web_fetch_md to read a known public URL.",
|
|
11
|
+
].join("\n"),
|
|
12
|
+
};
|
|
@@ -13,11 +13,11 @@ export async function runFetch(
|
|
|
13
13
|
_ctx: ExtensionContext,
|
|
14
14
|
): Promise<FetchResult> {
|
|
15
15
|
const input = (params ?? {}) as WebDocsFetchInput;
|
|
16
|
-
const libraryId = input.
|
|
16
|
+
const libraryId = input.libraryId?.trim();
|
|
17
17
|
const query = input.query?.trim();
|
|
18
18
|
const raw = Boolean(input.raw);
|
|
19
19
|
|
|
20
|
-
if (!libraryId) throw new Error("'
|
|
20
|
+
if (!libraryId) throw new Error("'libraryId' parameter is required");
|
|
21
21
|
if (!query) throw new Error("'query' parameter is required");
|
|
22
22
|
|
|
23
23
|
onUpdate?.({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const toolDescription =
|
|
2
|
-
"Fetch focused Context7 docs for a known
|
|
2
|
+
"Fetch focused Context7 docs for a known libraryId. Search first if the ID is unknown. Markdown is the default; raw=true returns JSON snippets.";
|
|
3
3
|
|
|
4
4
|
export const promptSnippet = "fetch focused Context7 documentation";
|
|
5
5
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { WEB_TOOL_NAMESPACE } from "../namespace.ts";
|
|
2
3
|
import { promptGuidelines, promptSnippet, toolDescription } from "./guidance.ts";
|
|
3
4
|
import { renderFetchCall, renderFetchResult } from "./render.ts";
|
|
4
5
|
import { webDocsFetchSpec } from "./spec.ts";
|
|
@@ -7,6 +8,7 @@ import { webDocsFetchSpec } from "./spec.ts";
|
|
|
7
8
|
export function registerWebDocsFetchTool(pi: ExtensionAPI): void {
|
|
8
9
|
pi.registerTool({
|
|
9
10
|
...webDocsFetchSpec,
|
|
11
|
+
namespace: WEB_TOOL_NAMESPACE,
|
|
10
12
|
description: toolDescription,
|
|
11
13
|
promptSnippet,
|
|
12
14
|
promptGuidelines: [...promptGuidelines],
|
|
@@ -6,7 +6,7 @@ import { WEB_DOCS_FETCH_TOOL_NAME, type WebDocsFetchInput } from "./spec.ts";
|
|
|
6
6
|
/** Transcript renderer for web_docs_fetch tool calls. */
|
|
7
7
|
export function renderFetchCall(args: unknown, theme: Theme) {
|
|
8
8
|
const input = (args ?? {}) as WebDocsFetchInput;
|
|
9
|
-
const libraryId = typeof input.
|
|
9
|
+
const libraryId = typeof input.libraryId === "string" ? input.libraryId : "";
|
|
10
10
|
const query = typeof input.query === "string" ? truncatePreview(input.query) : undefined;
|
|
11
11
|
return renderToolCall(WEB_DOCS_FETCH_TOOL_NAME, libraryId, theme, query);
|
|
12
12
|
}
|
|
@@ -8,7 +8,7 @@ export const WEB_DOCS_FETCH_TOOL_LABEL = "Web Docs Fetch";
|
|
|
8
8
|
|
|
9
9
|
export const webDocsFetchParameters = Type.Object(
|
|
10
10
|
{
|
|
11
|
-
|
|
11
|
+
libraryId: Type.String({
|
|
12
12
|
description: "Context7 ID, for example /react/react.",
|
|
13
13
|
}),
|
|
14
14
|
query: Type.String({ description: "Specific docs question" }),
|
|
@@ -28,6 +28,12 @@ export type WebDocsFetchInput = Static<typeof webDocsFetchParameters>;
|
|
|
28
28
|
export const webDocsFetchSpec = {
|
|
29
29
|
name: WEB_DOCS_FETCH_TOOL_NAME,
|
|
30
30
|
label: WEB_DOCS_FETCH_TOOL_LABEL,
|
|
31
|
+
annotations: {
|
|
32
|
+
readOnlyHint: true,
|
|
33
|
+
destructiveHint: false,
|
|
34
|
+
idempotentHint: true,
|
|
35
|
+
openWorldHint: true,
|
|
36
|
+
},
|
|
31
37
|
parameters: webDocsFetchParameters,
|
|
32
38
|
outputSchema: webDocsFetchOutputSchema,
|
|
33
39
|
execute: runFetch,
|
|
@@ -18,10 +18,10 @@ export async function runSearch(
|
|
|
18
18
|
_ctx: ExtensionContext,
|
|
19
19
|
): Promise<SearchResult> {
|
|
20
20
|
const input = (params ?? {}) as WebDocsSearchInput;
|
|
21
|
-
const libraryName = input.
|
|
21
|
+
const libraryName = input.libraryName?.trim();
|
|
22
22
|
const query = input.query?.trim();
|
|
23
23
|
|
|
24
|
-
if (!libraryName) throw new Error("'
|
|
24
|
+
if (!libraryName) throw new Error("'libraryName' parameter is required");
|
|
25
25
|
if (!query) throw new Error("'query' parameter is required");
|
|
26
26
|
|
|
27
27
|
onUpdate?.({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { WEB_TOOL_NAMESPACE } from "../namespace.ts";
|
|
2
3
|
import { promptGuidelines, promptSnippet, toolDescription } from "./guidance.ts";
|
|
3
4
|
import { renderSearchCall, renderSearchResult } from "./render.ts";
|
|
4
5
|
import { webDocsSearchSpec } from "./spec.ts";
|
|
@@ -7,6 +8,7 @@ import { webDocsSearchSpec } from "./spec.ts";
|
|
|
7
8
|
export function registerWebDocsSearchTool(pi: ExtensionAPI): void {
|
|
8
9
|
pi.registerTool({
|
|
9
10
|
...webDocsSearchSpec,
|
|
11
|
+
namespace: WEB_TOOL_NAMESPACE,
|
|
10
12
|
description: toolDescription,
|
|
11
13
|
promptSnippet,
|
|
12
14
|
promptGuidelines: [...promptGuidelines],
|
|
@@ -6,7 +6,7 @@ import { WEB_DOCS_SEARCH_TOOL_NAME, type WebDocsSearchInput } from "./spec.ts";
|
|
|
6
6
|
/** Transcript renderer for web_docs_search tool calls. */
|
|
7
7
|
export function renderSearchCall(args: unknown, theme: Theme) {
|
|
8
8
|
const input = (args ?? {}) as WebDocsSearchInput;
|
|
9
|
-
const libraryName = typeof input.
|
|
9
|
+
const libraryName = typeof input.libraryName === "string" ? input.libraryName : "";
|
|
10
10
|
const query = typeof input.query === "string" ? truncatePreview(input.query) : undefined;
|
|
11
11
|
return renderToolCall(WEB_DOCS_SEARCH_TOOL_NAME, libraryName, theme, query);
|
|
12
12
|
}
|
|
@@ -83,7 +83,7 @@ export function formatSearchResults(
|
|
|
83
83
|
const noun = results.length === 1 ? "library" : "libraries";
|
|
84
84
|
const hiddenNote =
|
|
85
85
|
hiddenCount > 0
|
|
86
|
-
? [`_${hiddenCount} more omitted; refine \`
|
|
86
|
+
? [`_${hiddenCount} more omitted; refine \`libraryName\` or \`query\` if needed._`, ""]
|
|
87
87
|
: [];
|
|
88
88
|
|
|
89
89
|
return [
|
|
@@ -8,7 +8,7 @@ export const WEB_DOCS_SEARCH_TOOL_LABEL = "Web Docs Search";
|
|
|
8
8
|
|
|
9
9
|
export const webDocsSearchParameters = Type.Object(
|
|
10
10
|
{
|
|
11
|
-
|
|
11
|
+
libraryName: Type.String({
|
|
12
12
|
description: "Library name (e.g. react, next.js, fastapi)",
|
|
13
13
|
}),
|
|
14
14
|
query: Type.String({
|
|
@@ -24,6 +24,12 @@ export type WebDocsSearchInput = Static<typeof webDocsSearchParameters>;
|
|
|
24
24
|
export const webDocsSearchSpec = {
|
|
25
25
|
name: WEB_DOCS_SEARCH_TOOL_NAME,
|
|
26
26
|
label: WEB_DOCS_SEARCH_TOOL_LABEL,
|
|
27
|
+
annotations: {
|
|
28
|
+
readOnlyHint: true,
|
|
29
|
+
destructiveHint: false,
|
|
30
|
+
idempotentHint: true,
|
|
31
|
+
openWorldHint: true,
|
|
32
|
+
},
|
|
27
33
|
parameters: webDocsSearchParameters,
|
|
28
34
|
outputSchema: webDocsSearchOutputSchema,
|
|
29
35
|
execute: runSearch,
|
|
@@ -41,9 +41,9 @@ async function fetchAsMarkdown(
|
|
|
41
41
|
throw new Error(`URL must be http(s): ${url}`);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const outputMode = input.
|
|
45
|
-
const absLinks = input.
|
|
46
|
-
const timeoutMs = typeof input.
|
|
44
|
+
const outputMode = input.outputMode ?? "auto";
|
|
45
|
+
const absLinks = input.absLinks ?? true;
|
|
46
|
+
const timeoutMs = typeof input.timeoutMs === "number" ? input.timeoutMs : 30_000;
|
|
47
47
|
|
|
48
48
|
onUpdate?.({
|
|
49
49
|
content: [{ type: "text", text: `Fetching ${url}...` }],
|
|
@@ -53,7 +53,7 @@ async function fetchAsMarkdown(
|
|
|
53
53
|
const result = await fetchPage(url, {
|
|
54
54
|
timeoutMs,
|
|
55
55
|
signal,
|
|
56
|
-
fetchMode: input.
|
|
56
|
+
fetchMode: input.fetchMode,
|
|
57
57
|
firecrawlEnabled: loadWebConfig(configCwd).firecrawlEnabled,
|
|
58
58
|
});
|
|
59
59
|
const markdown = await resolveMarkdown(result, absLinks);
|
|
@@ -71,7 +71,7 @@ export async function fetchPage(
|
|
|
71
71
|
const mode = options.fetchMode ?? "direct";
|
|
72
72
|
if (!WEB_FETCH_MODES.includes(mode)) {
|
|
73
73
|
throw new FetchError(
|
|
74
|
-
'Unsupported
|
|
74
|
+
'Unsupported fetchMode; select "direct", "firecrawl_fallback", or "firecrawl"',
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
77
|
if (mode !== "direct" && !options.firecrawlEnabled) {
|
|
@@ -89,7 +89,7 @@ export async function fetchPage(
|
|
|
89
89
|
? ""
|
|
90
90
|
: "requires Firecrawl enabled in /supi-settings and FIRECRAWL_API_KEY; ";
|
|
91
91
|
throw new FetchError(
|
|
92
|
-
`${error.message}. For a public page, retry with
|
|
92
|
+
`${error.message}. For a public page, retry with fetchMode: "firecrawl_fallback" (${setupHint}shares the URL and may consume credits).`,
|
|
93
93
|
{ status: 403, cause: error },
|
|
94
94
|
);
|
|
95
95
|
}
|
|
@@ -26,8 +26,8 @@ const OutputModeEnum = Type.Enum(WEB_FETCH_OUTPUT_MODES, {
|
|
|
26
26
|
export const webFetchMdParameters = Type.Object(
|
|
27
27
|
{
|
|
28
28
|
url: Type.String({ description: "Public http(s) URL" }),
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
outputMode: Type.Optional(OutputModeEnum),
|
|
30
|
+
fetchMode: Type.Optional(
|
|
31
31
|
Type.Enum(WEB_FETCH_MODES, {
|
|
32
32
|
type: "string",
|
|
33
33
|
default: "direct",
|
|
@@ -35,13 +35,13 @@ export const webFetchMdParameters = Type.Object(
|
|
|
35
35
|
"direct fetches locally; firecrawl_fallback uses Firecrawl only after HTTP 403; firecrawl skips direct fetching for JS-heavy or poorly extracted pages. Firecrawl requires opt-in via /supi-settings and FIRECRAWL_API_KEY, shares the URL and may consume credits. Never use it for signed, login-protected, private, or paywalled URLs.",
|
|
36
36
|
}),
|
|
37
37
|
),
|
|
38
|
-
|
|
38
|
+
absLinks: Type.Optional(
|
|
39
39
|
Type.Boolean({
|
|
40
40
|
description: "Absolutize HTML links/images; false preserves original destinations.",
|
|
41
41
|
default: true,
|
|
42
42
|
}),
|
|
43
43
|
),
|
|
44
|
-
|
|
44
|
+
timeoutMs: Type.Optional(
|
|
45
45
|
Type.Integer({
|
|
46
46
|
description: "Timeout per direct request and for the complete Firecrawl attempt (ms)",
|
|
47
47
|
default: 30_000,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { WEB_TOOL_NAMESPACE } from "../namespace.ts";
|
|
2
3
|
import { createWebFetchExecute } from "./execute.ts";
|
|
3
4
|
import { getWebFetchPromptSurface } from "./guidance.ts";
|
|
4
5
|
import { renderWebFetchCall, renderWebFetchResult } from "./render.ts";
|
|
@@ -12,6 +13,7 @@ export function registerWebFetchMdTool(pi: ExtensionAPI, configCwd?: string): vo
|
|
|
12
13
|
const surface = getWebFetchPromptSurface();
|
|
13
14
|
pi.registerTool({
|
|
14
15
|
...webFetchMdSpec,
|
|
16
|
+
namespace: WEB_TOOL_NAMESPACE,
|
|
15
17
|
...(configCwd ? { execute: createWebFetchExecute(configCwd) } : {}),
|
|
16
18
|
description: surface.description,
|
|
17
19
|
promptSnippet: surface.promptSnippet,
|
|
@@ -7,8 +7,8 @@ import { WEB_FETCH_MD_TOOL_NAME, type WebFetchMdInput } from "./spec.ts";
|
|
|
7
7
|
export function renderWebFetchCall(args: unknown, theme: Theme) {
|
|
8
8
|
const input = (args ?? {}) as WebFetchMdInput;
|
|
9
9
|
const url = typeof input.url === "string" ? input.url : "";
|
|
10
|
-
const outputMode = typeof input.
|
|
11
|
-
const annotation = [outputMode, input.
|
|
10
|
+
const outputMode = typeof input.outputMode === "string" ? input.outputMode : undefined;
|
|
11
|
+
const annotation = [outputMode, input.fetchMode].filter(Boolean).join(", ");
|
|
12
12
|
return renderToolCall(WEB_FETCH_MD_TOOL_NAME, url, theme, annotation || undefined);
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -17,6 +17,12 @@ export const WEB_FETCH_MD_TOOL_LABEL = "Web Fetch";
|
|
|
17
17
|
export const webFetchMdSpec = {
|
|
18
18
|
name: WEB_FETCH_MD_TOOL_NAME,
|
|
19
19
|
label: WEB_FETCH_MD_TOOL_LABEL,
|
|
20
|
+
annotations: {
|
|
21
|
+
readOnlyHint: true,
|
|
22
|
+
destructiveHint: false,
|
|
23
|
+
idempotentHint: true,
|
|
24
|
+
openWorldHint: true,
|
|
25
|
+
},
|
|
20
26
|
parameters: webFetchMdParameters,
|
|
21
27
|
outputSchema: webFetchMdOutputSchema,
|
|
22
28
|
execute: runWebFetch,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { WEB_TOOL_NAMESPACE } from "../namespace.ts";
|
|
2
3
|
import { promptGuidelines, promptSnippet, toolDescription } from "./guidance.ts";
|
|
3
4
|
import { renderWebSearchCall, renderWebSearchResult } from "./render.ts";
|
|
4
5
|
import { webSearchSpec } from "./spec.ts";
|
|
@@ -7,6 +8,7 @@ import { webSearchSpec } from "./spec.ts";
|
|
|
7
8
|
export function registerWebSearchTool(pi: ExtensionAPI): void {
|
|
8
9
|
pi.registerTool({
|
|
9
10
|
...webSearchSpec,
|
|
11
|
+
namespace: WEB_TOOL_NAMESPACE,
|
|
10
12
|
description: toolDescription,
|
|
11
13
|
promptSnippet,
|
|
12
14
|
promptGuidelines: [...promptGuidelines],
|
|
@@ -14,6 +14,12 @@ export const WEB_SEARCH_TOOL_LABEL = "Web Search";
|
|
|
14
14
|
export const webSearchSpec = {
|
|
15
15
|
name: WEB_SEARCH_TOOL_NAME,
|
|
16
16
|
label: WEB_SEARCH_TOOL_LABEL,
|
|
17
|
+
annotations: {
|
|
18
|
+
readOnlyHint: true,
|
|
19
|
+
destructiveHint: false,
|
|
20
|
+
idempotentHint: true,
|
|
21
|
+
openWorldHint: true,
|
|
22
|
+
},
|
|
17
23
|
parameters: webSearchParameters,
|
|
18
24
|
outputSchema: webSearchOutputSchema,
|
|
19
25
|
execute: runWebSearch,
|