From 5896cd2e2a3be091617c47d538b9f25bcaca9150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=82CHES?= Date: Fri, 13 Mar 2026 11:34:07 -0600 Subject: [PATCH] fix: resolve TypeScript type errors in search-the-web extension (#204) (#210) - Add .js extensions to all relative imports for NodeNext module resolution - Cast pi.writeTempFile to (pi as any) since it exists at runtime but not on ExtensionAPI type - Add details: undefined as unknown to return objects missing the required details field - Fix onUpdate calls to include details field required by AgentToolResult Co-authored-by: Claude Opus 4.6 --- .../extensions/search-the-web/format.ts | 2 +- .../extensions/search-the-web/index.ts | 10 ++++----- .../search-the-web/tool-fetch-page.ts | 14 ++++++------ .../search-the-web/tool-llm-context.ts | 22 +++++++++---------- .../extensions/search-the-web/tool-search.ts | 20 ++++++++--------- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/resources/extensions/search-the-web/format.ts b/src/resources/extensions/search-the-web/format.ts index 27a91e2c4..0c4123faa 100644 --- a/src/resources/extensions/search-the-web/format.ts +++ b/src/resources/extensions/search-the-web/format.ts @@ -3,7 +3,7 @@ * and LLM context responses. */ -import { extractDomain } from "./url-utils"; +import { extractDomain } from "./url-utils.js"; export interface SearchResultFormatted { title: string; diff --git a/src/resources/extensions/search-the-web/index.ts b/src/resources/extensions/search-the-web/index.ts index a2c38cf69..af33c3058 100644 --- a/src/resources/extensions/search-the-web/index.ts +++ b/src/resources/extensions/search-the-web/index.ts @@ -45,11 +45,11 @@ */ import type { ExtensionAPI } from "@gsd/pi-coding-agent"; -import { registerSearchTool } from "./tool-search"; -import { registerFetchPageTool } from "./tool-fetch-page"; -import { registerLLMContextTool } from "./tool-llm-context"; -import { registerSearchProviderCommand } from "./command-search-provider.ts"; -import { registerNativeSearchHooks } from "./native-search"; +import { registerSearchTool } from "./tool-search.js"; +import { registerFetchPageTool } from "./tool-fetch-page.js"; +import { registerLLMContextTool } from "./tool-llm-context.js"; +import { registerSearchProviderCommand } from "./command-search-provider.js"; +import { registerNativeSearchHooks } from "./native-search.js"; export default function (pi: ExtensionAPI) { registerSearchTool(pi); diff --git a/src/resources/extensions/search-the-web/tool-fetch-page.ts b/src/resources/extensions/search-the-web/tool-fetch-page.ts index 98b21515e..44169659b 100644 --- a/src/resources/extensions/search-the-web/tool-fetch-page.ts +++ b/src/resources/extensions/search-the-web/tool-fetch-page.ts @@ -13,10 +13,10 @@ import { truncateHead, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES } from "@gsd/pi-codi import { Text } from "@gsd/pi-tui"; import { Type } from "@sinclair/typebox"; -import { LRUTTLCache } from "./cache"; -import { fetchSimple, HttpError } from "./http"; -import { extractDomain } from "./url-utils"; -import { formatPageContent, type FormatPageOptions } from "./format"; +import { LRUTTLCache } from "./cache.js"; +import { fetchSimple, HttpError } from "./http.js"; +import { extractDomain } from "./url-utils.js"; +import { formatPageContent, type FormatPageOptions } from "./format.js"; // ============================================================================= // Cache @@ -336,7 +336,7 @@ export function registerFetchPageTool(pi: ExtensionAPI) { async execute(toolCallId, params, signal, onUpdate, ctx) { if (signal?.aborted) { - return { content: [{ type: "text", text: "Fetch cancelled." }] }; + return { content: [{ type: "text", text: "Fetch cancelled." }], details: undefined as unknown }; } const maxChars = params.maxChars ?? 8000; @@ -392,7 +392,7 @@ export function registerFetchPageTool(pi: ExtensionAPI) { } const domain = extractDomain(url); - onUpdate?.({ content: [{ type: "text", text: `Fetching ${domain}...` }] }); + onUpdate?.({ content: [{ type: "text", text: `Fetching ${domain}...` }], details: undefined as unknown }); // ------------------------------------------------------------------ // Fetch page content @@ -439,7 +439,7 @@ export function registerFetchPageTool(pi: ExtensionAPI) { const finalTruncation = truncateHead(output, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES }); let content = finalTruncation.content; if (finalTruncation.truncated) { - const tempFile = await pi.writeTempFile(output, { prefix: "fetch-page-" }); + const tempFile = await (pi as any).writeTempFile(output, { prefix: "fetch-page-" }); content += `\n\n[Truncated to fit context. Full content: ${tempFile}]`; } diff --git a/src/resources/extensions/search-the-web/tool-llm-context.ts b/src/resources/extensions/search-the-web/tool-llm-context.ts index 5c0f5d3aa..461942340 100644 --- a/src/resources/extensions/search-the-web/tool-llm-context.ts +++ b/src/resources/extensions/search-the-web/tool-llm-context.ts @@ -21,13 +21,13 @@ import { Text } from "@gsd/pi-tui"; import { Type } from "@sinclair/typebox"; import { StringEnum } from "@gsd/pi-ai"; -import { LRUTTLCache } from "./cache"; -import { fetchWithRetryTimed, HttpError, classifyError, type RateLimitInfo } from "./http"; -import { normalizeQuery, extractDomain } from "./url-utils"; -import { formatLLMContext, type LLMContextSnippet, type LLMContextSource } from "./format"; -import type { TavilyResult, TavilySearchResponse } from "./tavily"; -import { publishedDateToAge } from "./tavily"; -import { getTavilyApiKey, resolveSearchProvider } from "./provider"; +import { LRUTTLCache } from "./cache.js"; +import { fetchWithRetryTimed, HttpError, classifyError, type RateLimitInfo } from "./http.js"; +import { normalizeQuery, extractDomain } from "./url-utils.js"; +import { formatLLMContext, type LLMContextSnippet, type LLMContextSource } from "./format.js"; +import type { TavilyResult, TavilySearchResponse } from "./tavily.js"; +import { publishedDateToAge } from "./tavily.js"; +import { getTavilyApiKey, resolveSearchProvider } from "./provider.js"; // ============================================================================= // Types @@ -286,7 +286,7 @@ export function registerLLMContextTool(pi: ExtensionAPI) { async execute(toolCallId, params, signal, onUpdate, ctx) { if (signal?.aborted) { - return { content: [{ type: "text", text: "Search cancelled." }] }; + return { content: [{ type: "text", text: "Search cancelled." }], details: undefined as unknown }; } // ------------------------------------------------------------------ @@ -321,7 +321,7 @@ export function registerLLMContextTool(pi: ExtensionAPI) { const truncation = truncateHead(output, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES }); let content = truncation.content; if (truncation.truncated) { - const tempFile = await pi.writeTempFile(output, { prefix: "llm-context-" }); + const tempFile = await (pi as any).writeTempFile(output, { prefix: "llm-context-" }); content += `\n\n[Truncated. Full content: ${tempFile}]`; } @@ -340,7 +340,7 @@ export function registerLLMContextTool(pi: ExtensionAPI) { return { content: [{ type: "text", text: content }], details }; } - onUpdate?.({ content: [{ type: "text", text: `Searching & reading about "${params.query}"...` }] }); + onUpdate?.({ content: [{ type: "text", text: `Searching & reading about "${params.query}"...` }], details: undefined as unknown }); try { // ------------------------------------------------------------------ @@ -483,7 +483,7 @@ export function registerLLMContextTool(pi: ExtensionAPI) { let content = truncation.content; if (truncation.truncated) { - const tempFile = await pi.writeTempFile(output, { prefix: "llm-context-" }); + const tempFile = await (pi as any).writeTempFile(output, { prefix: "llm-context-" }); content += `\n\n[Truncated. Full content: ${tempFile}]`; } diff --git a/src/resources/extensions/search-the-web/tool-search.ts b/src/resources/extensions/search-the-web/tool-search.ts index c7328e1eb..70677e90a 100644 --- a/src/resources/extensions/search-the-web/tool-search.ts +++ b/src/resources/extensions/search-the-web/tool-search.ts @@ -16,12 +16,12 @@ import { Text } from "@gsd/pi-tui"; import { Type } from "@sinclair/typebox"; import { StringEnum } from "@gsd/pi-ai"; -import { LRUTTLCache } from "./cache"; -import { fetchWithRetryTimed, fetchWithRetry, classifyError, type RateLimitInfo } from "./http"; -import { normalizeQuery, toDedupeKey, detectFreshness } from "./url-utils"; -import { formatSearchResults, type SearchResultFormatted, type FormatSearchOptions } from "./format"; -import { getTavilyApiKey, resolveSearchProvider } from "./provider"; -import { normalizeTavilyResult, mapFreshnessToTavily, type TavilySearchResponse } from "./tavily"; +import { LRUTTLCache } from "./cache.js"; +import { fetchWithRetryTimed, fetchWithRetry, classifyError, type RateLimitInfo } from "./http.js"; +import { normalizeQuery, toDedupeKey, detectFreshness } from "./url-utils.js"; +import { formatSearchResults, type SearchResultFormatted, type FormatSearchOptions } from "./format.js"; +import { getTavilyApiKey, resolveSearchProvider } from "./provider.js"; +import { normalizeTavilyResult, mapFreshnessToTavily, type TavilySearchResponse } from "./tavily.js"; // ============================================================================= // Types @@ -291,7 +291,7 @@ export function registerSearchTool(pi: ExtensionAPI) { async execute(toolCallId, params, signal, onUpdate, ctx) { if (signal?.aborted) { - return { content: [{ type: "text", text: "Search cancelled." }] }; + return { content: [{ type: "text", text: "Search cancelled." }], details: undefined as unknown }; } // ------------------------------------------------------------------ @@ -365,7 +365,7 @@ export function registerSearchTool(pi: ExtensionAPI) { const truncation = truncateHead(output, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES }); let content = truncation.content; if (truncation.truncated) { - const tempFile = await pi.writeTempFile(output, { prefix: "web-search-" }); + const tempFile = await (pi as any).writeTempFile(output, { prefix: "web-search-" }); content += `\n\n[Truncated: ${truncation.outputLines}/${truncation.totalLines} lines (${formatSize(truncation.outputBytes)}/${formatSize(truncation.totalBytes)}). Full results: ${tempFile}]`; } @@ -387,7 +387,7 @@ export function registerSearchTool(pi: ExtensionAPI) { return { content: [{ type: "text", text: content }], details }; } - onUpdate?.({ content: [{ type: "text", text: `Searching for "${params.query}"...` }] }); + onUpdate?.({ content: [{ type: "text", text: `Searching for "${params.query}"...` }], details: undefined as unknown }); try { // ------------------------------------------------------------------ @@ -484,7 +484,7 @@ export function registerSearchTool(pi: ExtensionAPI) { let content = truncation.content; if (truncation.truncated) { - const tempFile = await pi.writeTempFile(output, { prefix: "web-search-" }); + const tempFile = await (pi as any).writeTempFile(output, { prefix: "web-search-" }); content += `\n\n[Truncated: ${truncation.outputLines}/${truncation.totalLines} lines (${formatSize(truncation.outputBytes)}/${formatSize(truncation.totalBytes)}). Full results: ${tempFile}]`; }