@humain/terminal 0.2.3 → 0.3.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 +2 -0
- package/dist/bundle/chunks/{chunk-U75GS4NL.js → chunk-CBTAWCW5.js} +1 -1
- package/dist/bundle/chunks/{chunk-D6HHRSB5.js → chunk-S43N4JYF.js} +14 -29
- package/dist/bundle/chunks/{chunk-LYOOYM65.js → chunk-WKLAQTQ4.js} +100 -124
- package/dist/bundle/chunks/{compat-22OQ5DBK.js → compat-L5WILLPV.js} +1 -1
- package/dist/bundle/chunks/{extract-CTIFQZDJ.js → extract-2YP6VMY4.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/anysearch.js +4 -14
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/bocha.js +3 -24
- package/dist/humain/web-access/vendor/bocha.js.map +1 -1
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brave.js +3 -24
- package/dist/humain/web-access/vendor/brave.js.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.js +5 -34
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/content-find.js +186 -51
- package/dist/humain/web-access/vendor/content-find.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.js +4 -1
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-run.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-run.js +3 -1
- package/dist/humain/web-access/vendor/curator-run.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.js +2 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
- package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts +2 -0
- package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/domain-filter-normalization.js +19 -0
- package/dist/humain/web-access/vendor/domain-filter-normalization.js.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.js +3 -24
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/extract.js +3 -1
- package/dist/humain/web-access/vendor/extract.js.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.js +5 -32
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.d.ts +5 -2
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.js +85 -37
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
- package/dist/humain/web-access/vendor/index.d.ts +3 -3
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/index.js +135 -157
- package/dist/humain/web-access/vendor/index.js.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.js +4 -14
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/kagi.js +4 -12
- package/dist/humain/web-access/vendor/kagi.js.map +1 -1
- package/dist/humain/web-access/vendor/kimi-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/kimi-search.js +5 -32
- package/dist/humain/web-access/vendor/kimi-search.js.map +1 -1
- package/dist/humain/web-access/vendor/mistral-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/mistral-search.js +1 -18
- package/dist/humain/web-access/vendor/mistral-search.js.map +1 -1
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ollama.js +2 -6
- package/dist/humain/web-access/vendor/ollama.js.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts +3 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.js +181 -38
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/opencode-session-headers.d.ts +10 -0
- package/dist/humain/web-access/vendor/opencode-session-headers.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/opencode-session-headers.js +23 -0
- package/dist/humain/web-access/vendor/opencode-session-headers.js.map +1 -0
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/page-query.js +10 -2
- package/dist/humain/web-access/vendor/page-query.js.map +1 -1
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/parallel.js +1 -18
- package/dist/humain/web-access/vendor/parallel.js.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +2 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.js +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/querit.js +5 -32
- package/dist/humain/web-access/vendor/querit.js.map +1 -1
- package/dist/humain/web-access/vendor/search-answer-formatting.d.ts +8 -0
- package/dist/humain/web-access/vendor/search-answer-formatting.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/search-answer-formatting.js +6 -0
- package/dist/humain/web-access/vendor/search-answer-formatting.js.map +1 -0
- package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts +2 -0
- package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/search-result-count-normalization.js +6 -0
- package/dist/humain/web-access/vendor/search-result-count-normalization.js.map +1 -0
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/search1api.js +5 -32
- package/dist/humain/web-access/vendor/search1api.js.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.js +5 -32
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searxng.js +3 -24
- package/dist/humain/web-access/vendor/searxng.js.map +1 -1
- package/dist/humain/web-access/vendor/serpapi.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpapi.js +5 -30
- package/dist/humain/web-access/vendor/serpapi.js.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.js +3 -24
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.js +3 -24
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
- package/dist/humain/web-access/vendor/serper.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serper.js +5 -30
- package/dist/humain/web-access/vendor/serper.js.map +1 -1
- package/dist/humain/web-access/vendor/serply.d.ts +4 -0
- package/dist/humain/web-access/vendor/serply.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serply.js +191 -0
- package/dist/humain/web-access/vendor/serply.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/source-check.js +11 -47
- package/dist/humain/web-access/vendor/source-check.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.js +6 -2
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tavily.js +3 -24
- package/dist/humain/web-access/vendor/tavily.js.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.js +5 -32
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/utils.js +2 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -1
- package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/valyu.js +5 -30
- package/dist/humain/web-access/vendor/valyu.js.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.js +1 -18
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/xcrawl.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/xcrawl.js +5 -34
- package/dist/humain/web-access/vendor/xcrawl.js.map +1 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
- package/src/humain/web-access/UPSTREAM.md +33 -1
- package/src/humain/web-access/upstream.json +6 -5
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
2
|
-
import{ANTHROPIC_API_KEY_ENV,ANTHROPIC_AUTH_TOKEN_ENV,ANTHROPIC_OAUTH_TOKEN_ENV,anthropicMessagesApi,azureOpenAIResponsesApi,bedrockConverseStreamApi,complete,completeSimple,findEnvKeys,generateImages,generateImagesOpenRouter,getApiProvider,getApiProviders,getEnvApiKey,getImageModel,getImageModels,getImageProviders,getImagesApiProvider,getModel,getModels,getProviders,googleGenerativeAIApi,googleVertexApi,mistralConversationsApi,openAICodexResponsesApi,openAICompletionsApi,openAIResponsesApi,piMessagesApi,registerApiProvider,registerBuiltInApiProviders,registerBuiltInImagesApiProviders,registerFauxProvider,registerImagesApiProvider,resetApiProviders,setBedrockProviderModule,stream,streamAnthropic,streamAzureOpenAIResponses,streamGoogle,streamGoogleVertex,streamMistral,streamOpenAICodexResponses,streamOpenAICompletions,streamOpenAIResponses,streamSimple,streamSimpleAnthropic,streamSimpleAzureOpenAIResponses,streamSimpleGoogle,streamSimpleGoogleVertex,streamSimpleMistral,streamSimpleOpenAICodexResponses,streamSimpleOpenAICompletions,streamSimpleOpenAIResponses,unregisterApiProviders}from"./chunk-
|
|
2
|
+
import{ANTHROPIC_API_KEY_ENV,ANTHROPIC_AUTH_TOKEN_ENV,ANTHROPIC_OAUTH_TOKEN_ENV,anthropicMessagesApi,azureOpenAIResponsesApi,bedrockConverseStreamApi,complete,completeSimple,findEnvKeys,generateImages,generateImagesOpenRouter,getApiProvider,getApiProviders,getEnvApiKey,getImageModel,getImageModels,getImageProviders,getImagesApiProvider,getModel,getModels,getProviders,googleGenerativeAIApi,googleVertexApi,mistralConversationsApi,openAICodexResponsesApi,openAICompletionsApi,openAIResponsesApi,piMessagesApi,registerApiProvider,registerBuiltInApiProviders,registerBuiltInImagesApiProviders,registerFauxProvider,registerImagesApiProvider,resetApiProviders,setBedrockProviderModule,stream,streamAnthropic,streamAzureOpenAIResponses,streamGoogle,streamGoogleVertex,streamMistral,streamOpenAICodexResponses,streamOpenAICompletions,streamOpenAIResponses,streamSimple,streamSimpleAnthropic,streamSimpleAzureOpenAIResponses,streamSimpleGoogle,streamSimpleGoogleVertex,streamSimpleMistral,streamSimpleOpenAICodexResponses,streamSimpleOpenAICompletions,streamSimpleOpenAIResponses,unregisterApiProviders}from"./chunk-CBTAWCW5.js";import{AssistantMessageFrameEncoder,StringEnum,contentText,createFauxCore,createImagesModels,createImagesProvider,envApiKeyAuth,fauxAssistantMessage,fauxProvider,fauxText,fauxThinking,fauxToolCall,getAssistantRetryDelayMs,getOverflowPatterns,isContextOverflow,isRecoverableLength,isRetryableAssistantError,lazyOAuth,reduceAssistantMessageFrames,retryAssistantCall,typebox_exports,validateToolArguments,validateToolCall}from"./chunk-7T6XCLJF.js";import{cleanupSessionResources,registerSessionResourceCleanup,uuidv7}from"./chunk-USJZMAIR.js";import"./chunk-7DDKXS2Q.js";import{parseJsonWithRepair,parseStreamingJson,repairJson}from"./chunk-D7XAASZM.js";import{InMemoryCredentialStore,InMemoryModelsStore,ModelsError,calculateCost,clampThinkingLevel,createModels,createProvider,defaultProviderAuthContext,getSupportedThinkingLevels,hasApi,lazyApi,lazyStream,modelsAreEqual}from"./chunk-E6KP6V7F.js";import{AssistantMessageEventStream,EventStream,appendAssistantMessageDiagnostic,createAssistantMessageDiagnostic,createAssistantMessageEventStream,extractDiagnosticError,formatThrownValue}from"./chunk-72KO4OMP.js";import"./chunk-JXWJOIH4.js";export{ANTHROPIC_API_KEY_ENV,ANTHROPIC_AUTH_TOKEN_ENV,ANTHROPIC_OAUTH_TOKEN_ENV,AssistantMessageEventStream,AssistantMessageFrameEncoder,EventStream,InMemoryCredentialStore,InMemoryModelsStore,ModelsError,StringEnum,typebox_exports as Type,anthropicMessagesApi,appendAssistantMessageDiagnostic,azureOpenAIResponsesApi,bedrockConverseStreamApi,calculateCost,clampThinkingLevel,cleanupSessionResources,complete,completeSimple,contentText,createAssistantMessageDiagnostic,createAssistantMessageEventStream,createFauxCore,createImagesModels,createImagesProvider,createModels,createProvider,defaultProviderAuthContext,envApiKeyAuth,extractDiagnosticError,fauxAssistantMessage,fauxProvider,fauxText,fauxThinking,fauxToolCall,findEnvKeys,formatThrownValue,generateImages,generateImagesOpenRouter,getApiProvider,getApiProviders,getAssistantRetryDelayMs,getEnvApiKey,getImageModel,getImageModels,getImageProviders,getImagesApiProvider,getModel,getModels,getOverflowPatterns,getProviders,getSupportedThinkingLevels,googleGenerativeAIApi,googleVertexApi,hasApi,isContextOverflow,isRecoverableLength,isRetryableAssistantError,lazyApi,lazyOAuth,lazyStream,mistralConversationsApi,modelsAreEqual,openAICodexResponsesApi,openAICompletionsApi,openAIResponsesApi,parseJsonWithRepair,parseStreamingJson,piMessagesApi,reduceAssistantMessageFrames,registerApiProvider,registerBuiltInApiProviders,registerBuiltInImagesApiProviders,registerFauxProvider,registerImagesApiProvider,registerSessionResourceCleanup,repairJson,resetApiProviders,retryAssistantCall,setBedrockProviderModule,stream,streamAnthropic,streamAzureOpenAIResponses,streamGoogle,streamGoogleVertex,streamMistral,streamOpenAICodexResponses,streamOpenAICompletions,streamOpenAIResponses,streamSimple,streamSimpleAnthropic,streamSimpleAzureOpenAIResponses,streamSimpleGoogle,streamSimpleGoogleVertex,streamSimpleMistral,streamSimpleOpenAICodexResponses,streamSimpleOpenAICompletions,streamSimpleOpenAIResponses,unregisterApiProviders,uuidv7,validateToolArguments,validateToolCall};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
2
|
-
import{CredentialResolutionError,DEFAULT_MODEL,activityMonitor,assertAuthFetchUrl,authFetchRedirectGuard,checkGhAvailable,extractGitHub,extractWithFirecrawl,extractWithKagi,extractWithOllama,extractWithParallel,extractWithParallelMcp,extractWithQuerit,extractWithSearch1API,extractWithTinyFish,fetchGeminiApi,fetchRemoteUrl,formatSeconds,getApiKey,getBrowserCookiesForHosts,getLastBrowserCookieDiagnostic,getUploadBase,getVersionedApiBase,getWebSearchConfigPath,hasCredentialSource,isFirecrawlAvailable,isGatewayConfigured,isGeminiAdcAvailable,isGeminiApiAvailable,isGeminiApiAvailableWithVideo,isGeminiWebAvailable,isKagiExtractAvailable,isOllamaFetchAvailable,isParallelAvailable,isPerplexityAvailable,isQueritAvailable,isSearch1APIAvailable,isTimeoutError,isTinyFishAvailable,loadFetchContentDomainPolicy,loadSsrfConfig,mapFfmpegError,pLimit,queryGeminiApiWithInlineData,queryGeminiApiWithVideo,queryWithCookies,readExecError,redactCredential,redactGeminiApiResponse,resolveCredential,searchWithPerplexity,showGhHint,trimErrorText,validateRemoteUrl}from"./chunk-
|
|
2
|
+
import{CredentialResolutionError,DEFAULT_MODEL,activityMonitor,assertAuthFetchUrl,authFetchRedirectGuard,checkGhAvailable,extractGitHub,extractWithFirecrawl,extractWithKagi,extractWithOllama,extractWithParallel,extractWithParallelMcp,extractWithQuerit,extractWithSearch1API,extractWithTinyFish,fetchGeminiApi,fetchRemoteUrl,formatSeconds,getApiKey,getBrowserCookiesForHosts,getLastBrowserCookieDiagnostic,getUploadBase,getVersionedApiBase,getWebSearchConfigPath,hasCredentialSource,isFirecrawlAvailable,isGatewayConfigured,isGeminiAdcAvailable,isGeminiApiAvailable,isGeminiApiAvailableWithVideo,isGeminiWebAvailable,isKagiExtractAvailable,isOllamaFetchAvailable,isParallelAvailable,isPerplexityAvailable,isQueritAvailable,isSearch1APIAvailable,isTimeoutError,isTinyFishAvailable,loadFetchContentDomainPolicy,loadSsrfConfig,mapFfmpegError,pLimit,queryGeminiApiWithInlineData,queryGeminiApiWithVideo,queryWithCookies,readExecError,redactCredential,redactGeminiApiResponse,resolveCredential,searchWithPerplexity,showGhHint,trimErrorText,validateRemoteUrl}from"./chunk-S43N4JYF.js";import"./chunk-LI2YVPWP.js";import"./chunk-JXWJOIH4.js";import{existsSync as existsSync9,readFileSync as readFileSync9}from"node:fs";function extractRSCContent(html){if(!html.includes("self.__next_f.push"))return null;let chunkMap=new Map,scriptRegex=/<script>self\.__next_f\.push\(\[1,"([\s\S]*?)"\]\)<\/script>/g;for(let match of html.matchAll(scriptRegex)){let content2;try{content2=JSON.parse('"'+match[1]+'"')}catch{continue}for(let line of content2.split(`
|
|
3
3
|
`)){if(!line.trim())continue;let colonIdx=line.indexOf(":");if(colonIdx<=0||colonIdx>4)continue;let id=line.slice(0,colonIdx);if(!/^[0-9a-f]+$/i.test(id))continue;let payload=line.slice(colonIdx+1);if(!payload)continue;let existing=chunkMap.get(id);(!existing||payload.length>existing.length)&&chunkMap.set(id,payload)}}if(chunkMap.size===0)return null;let title=html.match(/<title[^>]*>([^<]+)<\/title>/)?.[1]?.split("|")[0]?.trim()||"",parsedCache=new Map;function getParsedChunk(id){if(parsedCache.has(id))return parsedCache.get(id);let chunk=chunkMap.get(id);if(!chunk||!chunk.startsWith("["))return parsedCache.set(id,null),null;try{let parsed=JSON.parse(chunk);return parsedCache.set(id,parsed),parsed}catch{return parsedCache.set(id,null),null}}let visitedRefs=new Set;function extractNode(node,ctx={inTable:!1,inCode:!1}){if(node==null)return"";if(typeof node=="string"){let refMatch=node.match(/^\$L([0-9a-f]+)$/i);if(refMatch){let refId=refMatch[1];if(visitedRefs.has(refId))return"";visitedRefs.add(refId);let refNode=getParsedChunk(refId),result=refNode?extractNode(refNode,ctx):"";return visitedRefs.delete(refId),result}return!ctx.inCode&&(node==="$undefined"||node==="$"||/^\$[A-Z]/.test(node))?"":node.trim()?node:""}if(typeof node=="number")return String(node);if(typeof node=="boolean"||!Array.isArray(node))return"";if(node[0]==="$"&&typeof node[1]=="string"){let tag=node[1],props=node[3]||{};if(["script","style","svg","path","circle","link","meta","template","button","input","nav","footer","aside"].includes(tag))return"";if(tag.startsWith("$L")){let refId=tag.slice(2);if(visitedRefs.has(refId))return"";if(props.baseId&&props.children)return`## ${String(props.children)}
|
|
4
4
|
|
|
5
5
|
`;visitedRefs.add(refId);let refNode=getParsedChunk(refId),result="";return refNode?result=extractNode(refNode,ctx):props.children&&(result=extractNode(props.children,ctx)),visitedRefs.delete(refId),result}let children=props.children,content2=children?extractNode(children,ctx):"";switch(tag){case"h1":return`# ${content2.trim()}
|
|
@@ -45,7 +45,7 @@ Requirements:
|
|
|
45
45
|
- If text is unreadable, mark it as [unreadable] rather than guessing.
|
|
46
46
|
- Return only Markdown, without an enclosing code fence or commentary.`}function stripEnclosingMarkdownFence(value){let trimmed=value.trim();return(trimmed.match(/^```(?:markdown|md)?[ \t]*\n([\s\S]*?)\n```$/i)?.[1]??trimmed).trim()}function validatePageMarkers(markdown,maxPages,exactPageCount){let markers=[...markdown.matchAll(PAGE_MARKER_PATTERN)].map(match=>Number(match[1]));if(markers.length===0)throw new Error("Gemini PDF extraction returned no page markers");if(exactPageCount&&markers.length!==maxPages)throw new Error(`Gemini PDF extraction returned ${markers.length} page markers; expected ${maxPages}`);if(markers.length>maxPages)throw new Error(`Gemini PDF extraction returned ${markers.length} page markers; expected at most ${maxPages}`);for(let index=0;index<markers.length;index+=1){let expected=index+1;if(markers[index]!==expected)throw new Error(`Gemini PDF extraction page markers are out of sequence at page ${expected}`)}}function removeDuplicateInitialTitle(markdown,title){let match=markdown.match(/^(<!-- Page 1 -->\s*\n+)#\s+(.+?)\s*\n+/);return!match||normalizeTitle(match[2])!==normalizeTitle(title)?markdown:`${match[1]}${markdown.slice(match[0].length)}`.trim()}function normalizeTitle(value){return value.normalize("NFKC").toLocaleLowerCase().replace(/[`*_~]/g,"").replace(/[\p{P}\p{S}\s]+/gu,"")}var PDF_PROVIDER_VALUES=new Set(["auto","gemini","datalab","unpdf"]),DEFAULT_PDF_MAX_SIZE_MB=20,MAX_PDF_MAX_SIZE_MB=50,MAX_DATALAB_TIMEOUT_MS=3e5,DEFAULT_MAX_PAGES=100,DEFAULT_OUTPUT_DIR=join(tmpdir(),"pi-web-pdf"),CONFIG_PATH2=getWebSearchConfigPath(),PAGE_MARKER_PATTERN2=/^<!-- Page (\d+) -->$/gm;function loadPDFConfig(){if(!existsSync2(CONFIG_PATH2))return{enabled:!0,maxSizeMB:DEFAULT_PDF_MAX_SIZE_MB,maxPages:DEFAULT_MAX_PAGES,provider:"auto",datalabMode:normalizeDatalabMode(process.env.DATALAB_MODE),datalabTimeoutMs:DEFAULT_DATALAB_TIMEOUT_MS};let rawText=readFileSync2(CONFIG_PATH2,"utf-8"),raw;try{raw=JSON.parse(rawText)}catch(err){let message=err instanceof Error?err.message:String(err);throw new Error(`Failed to parse ${CONFIG_PATH2}: ${message}`)}let root=raw&&typeof raw=="object"?raw:{},pdf=root.pdf&&typeof root.pdf=="object"?root.pdf:{},enabled=pdf.enabled!==!1,configured=pdf.maxSizeMB,normalized=typeof configured=="number"&&Number.isFinite(configured)&&configured>0?Math.min(configured,MAX_PDF_MAX_SIZE_MB):DEFAULT_PDF_MAX_SIZE_MB,configuredMaxPages=pdf.maxPages,maxPages=typeof configuredMaxPages=="number"&&Number.isFinite(configuredMaxPages)&&configuredMaxPages>0?Math.max(1,Math.floor(configuredMaxPages)):DEFAULT_MAX_PAGES,provider=typeof pdf.provider=="string"&&PDF_PROVIDER_VALUES.has(pdf.provider)?pdf.provider:"auto",datalabMode=typeof pdf.datalabMode=="string"&&DATALAB_MODE_VALUES.has(pdf.datalabMode)?pdf.datalabMode:normalizeDatalabMode(process.env.DATALAB_MODE),configuredTimeout=pdf.datalabTimeoutMs,datalabTimeoutMs=typeof configuredTimeout=="number"&&Number.isFinite(configuredTimeout)&&configuredTimeout>0?Math.min(configuredTimeout,MAX_DATALAB_TIMEOUT_MS):DEFAULT_DATALAB_TIMEOUT_MS;return{enabled,maxSizeMB:normalized,maxPages,provider,datalabMode,datalabTimeoutMs}}async function getUnpdf(){if(typeof Promise.try!="function"){let{default:promiseTry}=await import("./promise-J5TGSM32.js");promiseTry.shim()}let[unpdf,pdfjs]=await Promise.all([import("./dist-BXEVYJIO.js"),import("./pdfjs-UKQT3OWY.js")]),{VerbosityLevel}=pdfjs;return{getDocumentProxy:unpdf.getDocumentProxy,VerbosityLevel}}async function extractPDFToMarkdown(buffer,url,options={}){let{maxPages,outputDir=DEFAULT_OUTPUT_DIR,filename,signal,geminiTimeoutMs}=options,pdfConfig=loadPDFConfig(),safeMaxPages=maxPages===void 0?pdfConfig.maxPages:Number.isFinite(maxPages)?Math.max(1,Math.floor(maxPages)):DEFAULT_MAX_PAGES,urlTitle=extractTitleFromURL(url),provider=pdfConfig.provider;if(provider==="auto"||provider==="datalab")try{if(isDatalabApiAvailable()){let result=await extractPDFViaDatalab(buffer,{maxPages:safeMaxPages,title:urlTitle,mode:pdfConfig.datalabMode,timeoutMs:pdfConfig.datalabTimeoutMs,...signal?{signal}:{}});return writeMarkdownResult({markdownBody:result.markdown,title:urlTitle,pages:result.pages,outputDir,filename,url})}}catch(err){if(shouldRethrowExtractionError(err,signal))throw err}if(provider==="auto"||provider==="gemini")try{if(isGeminiApiAvailable()){let markdownBody=await extractPDFViaGemini(buffer,{maxPages:safeMaxPages,title:urlTitle,...signal?{signal}:{},...geminiTimeoutMs!==void 0?{timeoutMs:geminiTimeoutMs}:{}});return writeMarkdownResult({markdownBody,title:urlTitle,pages:countPageMarkers2(markdownBody),outputDir,filename,url})}}catch(err){if(shouldRethrowExtractionError(err,signal))throw err}let{getDocumentProxy,VerbosityLevel}=await getUnpdf(),pdf=await getDocumentProxy(new Uint8Array(buffer),{verbosity:VerbosityLevel.ERRORS}),metadata=await pdf.getMetadata(),metadataInfo=metadata.info&&typeof metadata.info=="object"?metadata.info:null,metaTitle=typeof metadataInfo?.Title=="string"?metadataInfo.Title:void 0,metaAuthor=typeof metadataInfo?.Author=="string"?metadataInfo.Author:void 0,title=metaTitle?.trim()||urlTitle,pagesToExtract=Math.min(pdf.numPages,safeMaxPages),truncated=pdf.numPages>safeMaxPages,pages=[];for(let i=1;i<=pagesToExtract;i++){let pageText=(await(await pdf.getPage(i)).getTextContent()).items.map(item=>item.str||"").join(" ").replace(/\s+/g," ").trim();pageText&&pages.push({pageNum:i,text:pageText})}let bodyLines=[];for(let i=0;i<pages.length;i++)i>0&&(bodyLines.push(""),bodyLines.push(`<!-- Page ${pages[i].pageNum} -->`),bodyLines.push("")),bodyLines.push(pages[i].text);return writeMarkdownResult({markdownBody:bodyLines.join(`
|
|
47
47
|
`),title,pages:pdf.numPages,outputDir,filename,url,metaAuthor,truncated,pagesToExtract})}async function writeMarkdownResult(options){let lines=[];lines.push(`# ${options.title}`),lines.push(""),lines.push(`> Source: ${options.url}`),lines.push(`> Pages: ${options.pages}${options.truncated?` (extracted first ${options.pagesToExtract})`:""}`),options.metaAuthor&&lines.push(`> Author: ${options.metaAuthor}`),lines.push(""),lines.push("---"),lines.push(""),options.markdownBody&&lines.push(options.markdownBody),options.truncated&&(lines.push(""),lines.push("---"),lines.push(""),lines.push(`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`));let content=lines.join(`
|
|
48
|
-
`),outputFilename=options.filename||sanitizeFilename(options.title)+".md",outputPath=join(options.outputDir,outputFilename);return await mkdir(options.outputDir,{recursive:!0}),await writeFile(outputPath,content,"utf-8"),{title:options.title,pages:options.pages,chars:content.length,outputPath}}function countPageMarkers2(markdown){return[...markdown.matchAll(PAGE_MARKER_PATTERN2)].length}function shouldRethrowExtractionError(err,signal){return signal?.aborted||err instanceof CredentialResolutionError?!0:(err instanceof Error?err.message:String(err)).startsWith("Failed to parse ")}function extractTitleFromURL(url){try{let urlObj=new URL(url),pathname=urlObj.pathname,filename=basename(pathname,".pdf");if(urlObj.hostname.includes("arxiv.org")){let match=pathname.match(/\/(?:pdf|abs)\/(\d+\.\d+)/);match&&(filename=`arxiv-${match[1]}`)}return filename=filename.replace(/[_-]+/g," ").replace(/\s+/g," ").trim(),filename||"document"}catch{return"document"}}function sanitizeFilename(name){return name.toLowerCase().replace(/[^a-z0-9\s-]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-").slice(0,100).replace(/^-|-$/g,"")||"document"}function isPDF(url,contentType){if(contentType?.includes("application/pdf"))return!0;try{return new URL(url).pathname.toLowerCase().endsWith(".pdf")}catch{return!1}}import{execFile}from"node:child_process";import{existsSync as existsSync3,readFileSync as readFileSync3}from"node:fs";var CONFIG_PATH3=getWebSearchConfigPath(),GH_TIMEOUT_MS=1e4,GH_TOTAL_TIMEOUT_MS=2e4,MAX_DOC_CHARS=15e4,BODY_INLINE_CHARS=4e3,COMMENT_INLINE_CHARS=700,MAX_INLINE_COMMENTS=15,MAX_INLINE_REVIEWS=10,MAX_INLINE_CHECKS=15,MAX_INLINE_FILES=50,MAX_INLINE_COMMITS=20,MAX_INLINE_REVIEW_THREADS=30,REST_HEADERS={Accept:"application/vnd.github+json","User-Agent":"pi-web-access"},PR_SUBPATHS=new Set(["files","commits","checks","conversation"]),PR_FIELDS=["title","number","state","isDraft","author","baseRefName","headRefName","headRepositoryOwner","createdAt","mergedAt","closedAt","labels","milestone","additions","deletions","changedFiles","files","commits","reviews","statusCheckRollup","comments","body","closingIssuesReferences","url"],PR_CORE_FIELDS=["title","number","state","isDraft","author","baseRefName","headRefName","headRepositoryOwner","createdAt","mergedAt","closedAt","labels","milestone","additions","deletions","changedFiles","files","commits","reviews","comments","body","url"],ISSUE_FIELDS=["title","number","state","stateReason","author","createdAt","closedAt","labels","assignees","milestone","comments","body","closedByPullRequestsReferences","url"],ISSUE_CORE_FIELDS=["title","number","state","author","createdAt","closedAt","labels","assignees","milestone","comments","body","url"],cachedConfig2=null;function loadConfig2(){if(cachedConfig2)return cachedConfig2;let defaults2={enabled:!0};if(!existsSync3(CONFIG_PATH3))return cachedConfig2=defaults2,cachedConfig2;let parsed;try{parsed=JSON.parse(readFileSync3(CONFIG_PATH3,"utf-8"))}catch(err){let message=err instanceof Error?err.message:String(err);throw new Error(`Failed to parse ${CONFIG_PATH3}: ${message}`)}let value=(parsed&&typeof parsed=="object"&&!Array.isArray(parsed)?parsed:{}).githubPrIssue;if(value!==void 0&&(typeof value!="object"||value===null||Array.isArray(value)))throw new Error(`githubPrIssue in ${CONFIG_PATH3} must be an object`);return cachedConfig2={enabled:typeof value?.enabled=="boolean"?value.enabled:!0},cachedConfig2}function validOwner(owner){return/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/.test(owner)&&!owner.includes("--")}function validRepo(repo){return/^[A-Za-z0-9._-]{1,100}$/.test(repo)&&repo!=="."&&repo!==".."}function errorMessage(err){return err instanceof Error?err.message:String(err)}function isAbortError(err){return errorMessage(err).toLowerCase().includes("abort")}function parseGitHubIssuePrUrl(url){let parsed;try{parsed=new URL(url)}catch{return null}let host=parsed.hostname.toLowerCase();if(host!=="github.com"&&host!=="www.github.com")return null;let segments=[];for(let segment of parsed.pathname.split("/").filter(Boolean))try{segments.push(decodeURIComponent(segment))}catch{return null}if(segments.length<4)return null;let owner=segments[0],repo=segments[1].replace(/\.git$/,"");if(!validOwner(owner)||!validRepo(repo))return null;let route=segments[2].toLowerCase();if(route!=="pull"&&route!=="issues"||!/^\d+$/.test(segments[3]))return null;let subpath=segments[4]?.toLowerCase();if(route==="pull"&&subpath&&!PR_SUBPATHS.has(subpath)||route==="issues"&&subpath)return null;let number=Number.parseInt(segments[3],10);if(!Number.isSafeInteger(number)||number<=0)return null;let fragment=parsed.hash.slice(1),anchor=(route==="pull"?/^(?:issuecomment-\d+|discussion_r\d+)$/i:/^issuecomment-\d+$/i).test(fragment)?fragment:void 0;return{owner,repo,kind:route==="pull"?"pull":"issue",number,...anchor?{anchor}:{}}}function runGh(args,timeoutMs=GH_TIMEOUT_MS,signal){return new Promise(resolve2=>{execFile("gh",args,{timeout:timeoutMs,maxBuffer:10*1024*1024,...signal?{signal}:{},env:{...process.env,GH_PROMPT_DISABLED:"1",GIT_TERMINAL_PROMPT:"0"}},(err,stdout,stderr)=>{let nodeErr=err;resolve2({ok:!err,stdout,stderr,code:typeof nodeErr?.code=="number"?nodeErr.code:null,...err?{error:nodeErr?.message??String(err)}:{}})})})}function remainingGhTimeout(deadlineMs){return Math.max(1,Math.min(GH_TIMEOUT_MS,deadlineMs-Date.now()))}function unknownJsonField(result){return/unknown (?:json )?field|UnknownField|Unknown JSON field/i.test(`${result.stderr}
|
|
48
|
+
`),outputFilename=options.filename||sanitizeFilename(options.title)+".md",outputPath=join(options.outputDir,outputFilename);return await mkdir(options.outputDir,{recursive:!0}),await writeFile(outputPath,content,"utf-8"),{title:options.title,content,pages:options.pages,chars:content.length,outputPath}}function countPageMarkers2(markdown){return[...markdown.matchAll(PAGE_MARKER_PATTERN2)].length}function shouldRethrowExtractionError(err,signal){return signal?.aborted||err instanceof CredentialResolutionError?!0:(err instanceof Error?err.message:String(err)).startsWith("Failed to parse ")}function extractTitleFromURL(url){try{let urlObj=new URL(url),pathname=urlObj.pathname,filename=basename(pathname,".pdf");if(urlObj.hostname.includes("arxiv.org")){let match=pathname.match(/\/(?:pdf|abs)\/(\d+\.\d+)/);match&&(filename=`arxiv-${match[1]}`)}return filename=filename.replace(/[_-]+/g," ").replace(/\s+/g," ").trim(),filename||"document"}catch{return"document"}}function sanitizeFilename(name){return name.toLowerCase().replace(/[^a-z0-9\s-]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-").slice(0,100).replace(/^-|-$/g,"")||"document"}function isPDF(url,contentType){if(contentType?.includes("application/pdf"))return!0;try{return new URL(url).pathname.toLowerCase().endsWith(".pdf")}catch{return!1}}import{execFile}from"node:child_process";import{existsSync as existsSync3,readFileSync as readFileSync3}from"node:fs";var CONFIG_PATH3=getWebSearchConfigPath(),GH_TIMEOUT_MS=1e4,GH_TOTAL_TIMEOUT_MS=2e4,MAX_DOC_CHARS=15e4,BODY_INLINE_CHARS=4e3,COMMENT_INLINE_CHARS=700,MAX_INLINE_COMMENTS=15,MAX_INLINE_REVIEWS=10,MAX_INLINE_CHECKS=15,MAX_INLINE_FILES=50,MAX_INLINE_COMMITS=20,MAX_INLINE_REVIEW_THREADS=30,REST_HEADERS={Accept:"application/vnd.github+json","User-Agent":"pi-web-access"},PR_SUBPATHS=new Set(["files","commits","checks","conversation"]),PR_FIELDS=["title","number","state","isDraft","author","baseRefName","headRefName","headRepositoryOwner","createdAt","mergedAt","closedAt","labels","milestone","additions","deletions","changedFiles","files","commits","reviews","statusCheckRollup","comments","body","closingIssuesReferences","url"],PR_CORE_FIELDS=["title","number","state","isDraft","author","baseRefName","headRefName","headRepositoryOwner","createdAt","mergedAt","closedAt","labels","milestone","additions","deletions","changedFiles","files","commits","reviews","comments","body","url"],ISSUE_FIELDS=["title","number","state","stateReason","author","createdAt","closedAt","labels","assignees","milestone","comments","body","closedByPullRequestsReferences","url"],ISSUE_CORE_FIELDS=["title","number","state","author","createdAt","closedAt","labels","assignees","milestone","comments","body","url"],cachedConfig2=null;function loadConfig2(){if(cachedConfig2)return cachedConfig2;let defaults2={enabled:!0};if(!existsSync3(CONFIG_PATH3))return cachedConfig2=defaults2,cachedConfig2;let parsed;try{parsed=JSON.parse(readFileSync3(CONFIG_PATH3,"utf-8"))}catch(err){let message=err instanceof Error?err.message:String(err);throw new Error(`Failed to parse ${CONFIG_PATH3}: ${message}`)}let value=(parsed&&typeof parsed=="object"&&!Array.isArray(parsed)?parsed:{}).githubPrIssue;if(value!==void 0&&(typeof value!="object"||value===null||Array.isArray(value)))throw new Error(`githubPrIssue in ${CONFIG_PATH3} must be an object`);return cachedConfig2={enabled:typeof value?.enabled=="boolean"?value.enabled:!0},cachedConfig2}function validOwner(owner){return/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/.test(owner)&&!owner.includes("--")}function validRepo(repo){return/^[A-Za-z0-9._-]{1,100}$/.test(repo)&&repo!=="."&&repo!==".."}function errorMessage(err){return err instanceof Error?err.message:String(err)}function isAbortError(err){return errorMessage(err).toLowerCase().includes("abort")}function parseGitHubIssuePrUrl(url){let parsed;try{parsed=new URL(url)}catch{return null}let host=parsed.hostname.toLowerCase();if(host!=="github.com"&&host!=="www.github.com")return null;let segments=[];for(let segment of parsed.pathname.split("/").filter(Boolean))try{segments.push(decodeURIComponent(segment))}catch{return null}if(segments.length<4)return null;let owner=segments[0],repo=segments[1].replace(/\.git$/,"");if(!validOwner(owner)||!validRepo(repo))return null;let route=segments[2].toLowerCase();if(route!=="pull"&&route!=="issues"||!/^\d+$/.test(segments[3]))return null;let subpath=segments[4]?.toLowerCase();if(route==="pull"&&subpath&&!PR_SUBPATHS.has(subpath)||route==="issues"&&subpath)return null;let number=Number.parseInt(segments[3],10);if(!Number.isSafeInteger(number)||number<=0)return null;let fragment=parsed.hash.slice(1),anchor=(route==="pull"?/^(?:issuecomment-\d+|discussion_r\d+)$/i:/^issuecomment-\d+$/i).test(fragment)?fragment:void 0;return{owner,repo,kind:route==="pull"?"pull":"issue",number,...anchor?{anchor}:{}}}function runGh(args,timeoutMs=GH_TIMEOUT_MS,signal){return new Promise(resolve2=>{execFile("gh",args,{timeout:timeoutMs,maxBuffer:10*1024*1024,...signal?{signal}:{},env:{...process.env,GH_PROMPT_DISABLED:"1",GIT_TERMINAL_PROMPT:"0"}},(err,stdout,stderr)=>{let nodeErr=err;resolve2({ok:!err,stdout,stderr,code:typeof nodeErr?.code=="number"?nodeErr.code:null,...err?{error:nodeErr?.message??String(err)}:{}})})})}function remainingGhTimeout(deadlineMs){return Math.max(1,Math.min(GH_TIMEOUT_MS,deadlineMs-Date.now()))}function unknownJsonField(result){return/unknown (?:json )?field|UnknownField|Unknown JSON field/i.test(`${result.stderr}
|
|
49
49
|
${result.error??""}`)}async function ghView(info,deadlineMs,signal){let repoArg=`${info.owner}/${info.repo}`,command=info.kind==="pull"?"pr":"issue",fields=info.kind==="pull"?PR_FIELDS:ISSUE_FIELDS,coreFields=info.kind==="pull"?PR_CORE_FIELDS:ISSUE_CORE_FIELDS,result=await runGh([command,"view",String(info.number),"--repo",repoArg,"--json",fields.join(",")],remainingGhTimeout(deadlineMs),signal),notes=[],linkedReferencesUnavailable=!1;if(!result.ok&&unknownJsonField(result)&&(result=await runGh([command,"view",String(info.number),"--repo",repoArg,"--json",coreFields.join(",")],remainingGhTimeout(deadlineMs),signal),notes.push("Some GitHub fields were unavailable from this gh version; retried with the core field set."),linkedReferencesUnavailable=!0),!result.ok)return null;try{let parsed=JSON.parse(result.stdout);if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return null;let view=parsed;return linkedReferencesUnavailable&&(view.linkedReferencesUnavailable=!0),{view,notes}}catch{return null}}async function ghReviewThreads(info,deadlineMs,signal){if(info.kind!=="pull")return{comments:[]};let comments=[],bounded=!1,pageFailed=!1;for(let page=1;page<=3;page++){let result=await runGh(["api",`repos/${info.owner}/${info.repo}/pulls/${info.number}/comments?per_page=100&page=${page}`],remainingGhTimeout(deadlineMs),signal);if(!result.ok){pageFailed=!0;break}let pageItems;try{pageItems=JSON.parse(result.stdout)}catch{pageFailed=!0;break}if(!Array.isArray(pageItems)||pageItems.length===0||(comments.push(...pageItems.filter(item=>!!item&&typeof item=="object"&&!Array.isArray(item))),pageItems.length<100))break;page===3&&(bounded=!0)}let discussionId=anchorId(info.anchor,"discussion_r");if(discussionId&&!hasCommentId(comments,discussionId)){let result=await runGh(["api",`repos/${info.owner}/${info.repo}/pulls/comments/${discussionId}`],remainingGhTimeout(deadlineMs),signal);if(result.ok)try{let comment=JSON.parse(result.stdout);if(comment&&typeof comment=="object"&&!Array.isArray(comment)&&belongsToPull(comment,discussionId,info))comments.push(comment);else return{comments,bounded:bounded||pageFailed&&comments.length>0,unavailable:pageFailed&&comments.length===0,anchorUnavailable:!0}}catch{return{comments,bounded:bounded||pageFailed&&comments.length>0,unavailable:pageFailed&&comments.length===0,note:"Anchored review thread comment unavailable from gh."}}else return{comments,bounded:bounded||pageFailed&&comments.length>0,unavailable:pageFailed&&comments.length===0,anchorUnavailable:!0}}return{comments,bounded:bounded||pageFailed&&comments.length>0,unavailable:pageFailed&&comments.length===0}}function isRateLimited(response){return response.status===403&&response.headers.get("x-ratelimit-remaining")==="0"}function anchorId(anchor,prefix){return anchor?.match(prefix==="issuecomment"?/^issuecomment-(\d+)$/i:/^discussion_r(\d+)$/i)?.[1]??null}function hasCommentId(comments,id){return comments.some(comment=>commentId(comment)===id)}function belongsToIssue(comment,id,info){return commentId(comment)===id&&associationMatches(comment.issue_url,info,"issues")}function belongsToPull(comment,id,info){return commentId(comment)===id&&associationMatches(comment.pull_request_url,info,"pulls")}function associationMatches(value,info,route){if(typeof value!="string")return!1;try{let parsed=new URL(value);return parsed.protocol!=="https:"||parsed.hostname.toLowerCase()!=="api.github.com"?!1:parsed.pathname.toLowerCase()===`/repos/${info.owner}/${info.repo}/${route}/${info.number}`.toLowerCase()}catch{return!1}}function rateLimitResult(url,info,response){let reset=response.headers.get("x-ratelimit-reset"),resetNote=reset?` Rate limit resets at Unix time ${reset}.`:"";return{url,title:`${info.owner}/${info.repo}#${info.number}`,content:`GitHub API rate limit reached for ${info.owner}/${info.repo} ${info.kind} #${info.number}.${resetNote}
|
|
50
50
|
|
|
51
51
|
Authenticate the gh CLI and retry:
|
|
@@ -101,7 +101,7 @@ ${section}`:section}function addDeclaredLink(links,candidate){if(!candidate.url|
|
|
|
101
101
|
`)}function abortedResult(url){return{url,title:"",content:"",error:"Aborted"}}var turndownInstance;async function loadTurndown(){let{default:TurndownService}=await import("./turndown.cjs-HRMZVRUL.js");return new TurndownService({headingStyle:"atx",codeBlockStyle:"fenced"})}function getTurndown(){return turndownInstance??=loadTurndown(),turndownInstance}var fetchLimit=pLimit(CONCURRENT_LIMIT);function resolveFetchTimeoutMs(options){return options?.timeoutMs??loadFetchTimeoutMs()}var JINA_READER_BASE="https://r.jina.ai/";async function extractWithJinaReader(url,timeoutMs,signal,lookup){let jinaUrl=JINA_READER_BASE+url,activityId=activityMonitor.logStart({type:"api",query:`jina: ${url}`});try{let ssrf=loadSsrfConfig(),domainPolicy=loadFetchContentDomainPolicy();await validateRemoteUrl(url,{allowRanges:ssrf.allowRanges,trustEnvProxy:ssrf.trustEnvProxy,domainPolicy,...lookup?{lookup}:{}});let res=await fetch(jinaUrl,{headers:{Accept:"text/markdown","X-No-Cache":"true"},signal:AbortSignal.any([AbortSignal.timeout(timeoutMs),...signal?[signal]:[]])});if(!res.ok)return activityMonitor.logComplete(activityId,res.status),null;let content=await res.text();activityMonitor.logComplete(activityId,res.status);let contentStart=content.indexOf("Markdown Content:");if(contentStart<0)return null;let markdownPart=content.slice(contentStart+17).trim();if(markdownPart.length<100||markdownPart.startsWith("Loading...")||markdownPart.startsWith("Please enable JavaScript"))return null;let title=extractHeadingTitle(markdownPart)??(new URL(url).pathname.split("/").pop()||url);return{url,title,content:markdownPart,error:null}}catch(err){let message=err instanceof Error?err.message:String(err);return message.toLowerCase().includes("abort")?activityMonitor.logComplete(activityId,0):activityMonitor.logError(activityId,message),null}}function parseTimestamp(ts){let num=Number(ts);if(!isNaN(num)&&num>=0)return Math.floor(num);let parts=ts.split(":").map(Number);return parts.some(p=>isNaN(p)||p<0)?null:parts.length===3?Math.floor(parts[0]*3600+parts[1]*60+parts[2]):parts.length===2?Math.floor(parts[0]*60+parts[1]):null}function parseTimestampSpec(ts){let dashIdx=ts.indexOf("-",1);if(dashIdx>0){let start=parseTimestamp(ts.slice(0,dashIdx)),end=parseTimestamp(ts.slice(dashIdx+1));if(start!==null&&end!==null&&end>start)return{type:"range",start,end}}let seconds=parseTimestamp(ts);return seconds!==null?{type:"single",seconds}:null}var DEFAULT_RANGE_FRAMES=6,MIN_FRAME_INTERVAL=5;function computeRangeTimestamps(start,end,maxFrames=DEFAULT_RANGE_FRAMES){if(maxFrames<=1)return[start];let idealInterval=(end-start)/(maxFrames-1);if(idealInterval<MIN_FRAME_INTERVAL){let timestamps=[];for(let t=start;t<=end&×tamps.length<maxFrames;t+=MIN_FRAME_INTERVAL)timestamps.push(t);return timestamps}return Array.from({length:maxFrames},(_,i)=>Math.round(start+i*idealInterval))}function buildFrameResult(url,label,requestedCount,frames,error,duration){if(frames.length===0){let msg=error??"Frame extraction failed";return{url,title:`Frames ${label} (0/${requestedCount})`,content:msg,error:msg}}return{url,title:`Frames ${label} (${frames.length}/${requestedCount})`,content:`${frames.length} frames extracted from ${label}`,error:null,frames,...duration!==void 0?{duration}:{}}}async function extractLocalFrames(filePath,timestamps){let results=await Promise.all(timestamps.map(async t=>{let frame=await extractVideoFrame(filePath,t);return"error"in frame?{error:frame.error}:{...frame,timestamp:formatSeconds(t)}})),frames=results.filter(f=>"data"in f),firstError=results.find(f=>"error"in f);return{frames,error:frames.length===0&&firstError?firstError.error:null}}function safeVideoInfo(url){try{let info=isVideoFile(url);return info?{status:"video",info}:{status:"not-video"}}catch(err){return{status:"invalid",error:errorMessage5(err)}}}async function extractContent(url,signal,options){if(signal?.aborted)return{url,title:"",content:"",error:"Aborted"};let remoteUrl=null;try{let parsed=new URL(url);(parsed.protocol==="http:"||parsed.protocol==="https:")&&(remoteUrl=parsed)}catch{}if(remoteUrl)try{let ssrf=loadSsrfConfig(),domainPolicy=loadFetchContentDomainPolicy();await validateRemoteUrl(remoteUrl,{allowRanges:ssrf.allowRanges,trustEnvProxy:ssrf.trustEnvProxy,domainPolicy,...options?.lookup?{lookup:options.lookup}:{}})}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}if(options?.authFetchProfile||options?.mode==="raw")try{return await extractViaHttp(url,resolveFetchTimeoutMs(options),signal,options)}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}if(options?.frames||options?.timestamp){let disabled=imageGateError();if(disabled)return{url,title:"",content:"",error:disabled}}if(options?.frames&&!options.timestamp){let frameCount=options.frames,ytInfo2=isYouTubeURL(url);if(ytInfo2.isYouTube&&ytInfo2.videoId){let streamInfo=await getYouTubeStreamInfo(ytInfo2.videoId);if("error"in streamInfo)return{url,title:"Frames",content:streamInfo.error,error:streamInfo.error};if(streamInfo.duration===null){let error="Cannot determine video duration. Use a timestamp range instead.";return{url,title:"Frames",content:error,error}}let dur=Math.floor(streamInfo.duration),timestamps=computeRangeTimestamps(0,dur,frameCount),result=await extractYouTubeFrames(ytInfo2.videoId,timestamps,streamInfo),label=`${formatSeconds(0)}-${formatSeconds(dur)}`;return buildFrameResult(url,label,timestamps.length,result.frames,result.error,streamInfo.duration)}let localVideo2=safeVideoInfo(url);if(localVideo2.status==="invalid")return{url,title:"",content:"",error:localVideo2.error};if(localVideo2.status==="video"){let durationResult=await getLocalVideoDuration(localVideo2.info.absolutePath);if(typeof durationResult!="number")return{url,title:"Frames",content:durationResult.error,error:durationResult.error};let dur=Math.floor(durationResult),timestamps=computeRangeTimestamps(0,dur,frameCount),result=await extractLocalFrames(localVideo2.info.absolutePath,timestamps),label=`${formatSeconds(0)}-${formatSeconds(dur)}`;return buildFrameResult(url,label,timestamps.length,result.frames,result.error,durationResult)}return{url,title:"",content:"",error:"Frame extraction only works with YouTube and local video files"}}if(options?.timestamp){let spec=parseTimestampSpec(options.timestamp);if(!spec)return{url,title:"",content:"",error:`Invalid timestamp format: "${options.timestamp}". Use "H:MM:SS", "MM:SS", "85", or "start-end".`};let frameCount=options.frames,ytInfo2=isYouTubeURL(url);if(ytInfo2.isYouTube&&ytInfo2.videoId){let streamInfo=await getYouTubeStreamInfo(ytInfo2.videoId);if("error"in streamInfo){if(spec.type==="range"){let label=`${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;return{url,title:`Frames ${label}`,content:streamInfo.error,error:streamInfo.error}}if(frameCount){let end=spec.seconds+(frameCount-1)*MIN_FRAME_INTERVAL,label=`${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;return{url,title:`Frames ${label}`,content:streamInfo.error,error:streamInfo.error}}return{url,title:`Frame at ${options.timestamp}`,content:streamInfo.error,error:streamInfo.error}}if(spec.type==="range"){let label=`${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;if(streamInfo.duration!==null&&spec.end>streamInfo.duration){let error=`Timestamp ${formatSeconds(spec.end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;return{url,title:`Frames ${label}`,content:error,error}}let timestamps=frameCount?computeRangeTimestamps(spec.start,spec.end,frameCount):computeRangeTimestamps(spec.start,spec.end),result=await extractYouTubeFrames(ytInfo2.videoId,timestamps,streamInfo);return buildFrameResult(url,label,timestamps.length,result.frames,result.error,result.duration??void 0)}if(frameCount){let end=spec.seconds+(frameCount-1)*MIN_FRAME_INTERVAL,label=`${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;if(streamInfo.duration!==null&&end>streamInfo.duration){let error=`Timestamp ${formatSeconds(end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;return{url,title:`Frames ${label}`,content:error,error}}let timestamps=computeRangeTimestamps(spec.seconds,end,frameCount),result=await extractYouTubeFrames(ytInfo2.videoId,timestamps,streamInfo);return buildFrameResult(url,label,timestamps.length,result.frames,result.error,result.duration??void 0)}if(streamInfo.duration!==null&&spec.seconds>streamInfo.duration){let error=`Timestamp ${formatSeconds(spec.seconds)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;return{url,title:`Frame at ${options.timestamp}`,content:error,error}}let frame=await extractYouTubeFrame(ytInfo2.videoId,spec.seconds,streamInfo);return"error"in frame?{url,title:`Frame at ${options.timestamp}`,content:frame.error,error:frame.error}:{url,title:`Frame at ${options.timestamp}`,content:`Video frame at ${options.timestamp}`,error:null,thumbnail:frame}}let localVideo2=safeVideoInfo(url);if(localVideo2.status==="invalid")return{url,title:"",content:"",error:localVideo2.error};if(localVideo2.status==="video"){if(spec.type==="range"){let timestamps=frameCount?computeRangeTimestamps(spec.start,spec.end,frameCount):computeRangeTimestamps(spec.start,spec.end),result=await extractLocalFrames(localVideo2.info.absolutePath,timestamps),label=`${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;return buildFrameResult(url,label,timestamps.length,result.frames,result.error)}if(frameCount){let end=spec.seconds+(frameCount-1)*MIN_FRAME_INTERVAL,timestamps=computeRangeTimestamps(spec.seconds,end,frameCount),result=await extractLocalFrames(localVideo2.info.absolutePath,timestamps),label=`${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;return buildFrameResult(url,label,timestamps.length,result.frames,result.error)}let frame=await extractVideoFrame(localVideo2.info.absolutePath,spec.seconds);return"error"in frame?{url,title:`Frame at ${options.timestamp}`,content:frame.error,error:frame.error}:{url,title:`Frame at ${options.timestamp}`,content:`Video frame at ${options.timestamp}`,error:null,thumbnail:frame}}return{url,title:"",content:"",error:"Timestamp extraction only works with YouTube and local video files"}}let localVideo=safeVideoInfo(url);if(localVideo.status==="invalid")return{url,title:"",content:"",error:localVideo.error};if(localVideo.status==="video")try{let result=await extractVideo(localVideo.info,signal,options);return signal?.aborted?abortedResult(url):result??{url,title:"",content:"",error:`Video analysis requires Gemini access. Either:
|
|
102
102
|
1. Sign into gemini.google.com in Chrome (free, uses cookies)
|
|
103
103
|
2. Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`}}catch(err){return isAbortError3(err)?abortedResult(url):{url,title:"",content:"",error:errorMessage5(err)}}try{remoteUrl||new URL(url)}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}try{let ghIssuePrResult=await extractGitHubIssuePr(url,signal,options);if(ghIssuePrResult)return ghIssuePrResult;if(signal?.aborted)return abortedResult(url)}catch(err){let message=errorMessage5(err);if(isAbortError3(err))return abortedResult(url);if(isConfigParseError(err))return{url,title:"",content:"",error:message}}try{let ghResult=await extractGitHub(url,signal,options?.forceClone);if(ghResult)return ghResult;if(signal?.aborted)return abortedResult(url)}catch(err){let message=errorMessage5(err);if(isAbortError3(err))return abortedResult(url);if(isConfigParseError(err))return{url,title:"",content:"",error:message}}let ytInfo=isYouTubeURL(url),youtubeEnabled=!1;try{youtubeEnabled=isYouTubeEnabled()}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}if(ytInfo.isYouTube&&youtubeEnabled){try{let ytResult=await extractYouTube(url,signal,options?.prompt,options?.model);if(ytResult)return ytResult;if(signal?.aborted)return abortedResult(url)}catch(err){let message=errorMessage5(err);return isAbortError3(err)?abortedResult(url):{url,title:"",content:"",error:message}}return{url,title:"",content:"",error:"Could not extract YouTube video content. Sign into Google in a supported Chromium browser for automatic access, or set GEMINI_API_KEY."}}if(signal?.aborted)return abortedResult(url);let fetchTimeoutMs;try{fetchTimeoutMs=resolveFetchTimeoutMs(options)}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}let fetchRouting;try{fetchRouting=loadFetchRouting()}catch(err){return{url,title:"",content:"",error:errorMessage5(err)}}let providerOrder=remoteUrl&&!fetchRouting.allowRemoteHostedProviders?fetchRouting.providers.filter(provider=>!REMOTE_HOSTED_FETCH_PROVIDERS.has(provider)):fetchRouting.providers;if(providerOrder.length===0)return{url,title:"",content:"",error:"Remote hosted fetch providers are disabled unless fetchRouting.allowRemoteHostedProviders is true"};let httpResult=null,declaredLinks=[],withDeclaredLinks=result=>({...result,content:appendDeclaredWebLinks(result.content,declaredLinks)}),parseErrorResult=message=>httpResult?{...httpResult,error:message}:{url,title:"",content:"",error:message},runHttpProvider=async()=>{let{declaredLinks:discoveredLinks=[],...result}=await extractViaHttp(url,fetchTimeoutMs,signal,options);return httpResult=result,declaredLinks=discoveredLinks,signal?.aborted?abortedResult(url):!httpResult.error||NON_RECOVERABLE_ERRORS.some(prefix=>httpResult.error.startsWith(prefix))||isRedirectPolicyError(httpResult.error)||isConfigParseError(httpResult.error)?httpResult:null},firecrawlError=null,crawl4aiError=null,tinyfishError=null,search1apiError=null,queritError=null,kagiError=null,ollamaError=null,parallelError=null,parallelMcpError=null,brightdataError=null;if(remoteUrl&&providerOrder[0]!=="http"){let httpGateResult=await runHttpProvider();if(httpGateResult)return httpGateResult}for(let provider of providerOrder){if(signal?.aborted)return abortedResult(url);if(provider==="http"){let result=await runHttpProvider();if(result)return result;continue}if(provider==="firecrawl"){try{if(isFirecrawlAvailable()){let ssrf=loadSsrfConfig(),firecrawlResult=await extractWithFirecrawl(url,signal,{timeoutMs:options?.timeoutMs,...options?.lookup?{lookup:options.lookup}:{},ssrf});if(firecrawlResult)return withDeclaredLinks(firecrawlResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(firecrawlError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(firecrawlError)}continue}if(provider==="crawl4ai"){try{if(isCrawl4aiAvailable()){let ssrf=loadSsrfConfig(),crawl4aiResult=await extractWithCrawl4ai(url,signal,{timeoutMs:options?.timeoutMs,...options?.lookup?{lookup:options.lookup}:{},ssrf});if(crawl4aiResult)return withDeclaredLinks(crawl4aiResult)}}catch(err){if(signal?.aborted||isAbortException2(err))return abortedResult(url);if(crawl4aiError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(crawl4aiError)}continue}if(provider==="jina"){let jinaResult=await extractWithJinaReader(url,fetchTimeoutMs,signal,options?.lookup);if(jinaResult)return withDeclaredLinks(jinaResult);continue}if(provider==="tinyfish"){try{if(isTinyFishAvailable()){let tinyfishResult=await extractWithTinyFish(url,signal,options);if(tinyfishResult)return withDeclaredLinks(tinyfishResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(tinyfishError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(tinyfishError)}continue}if(provider==="search1api"){try{if(isSearch1APIAvailable()){let search1apiResult=await extractWithSearch1API(url,signal,options);if(search1apiResult)return withDeclaredLinks(search1apiResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(search1apiError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(search1apiError)}continue}if(provider==="querit"){try{if(isQueritAvailable()){let queritResult=await extractWithQuerit(url,signal,options);if(queritResult)return withDeclaredLinks(queritResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(queritError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(queritError)}continue}if(provider==="kagi"){try{if(isKagiExtractAvailable()){let ssrf=loadSsrfConfig(),kagiResult=await extractWithKagi(url,signal,{timeoutMs:options?.timeoutMs,...options?.lookup?{lookup:options.lookup}:{},ssrf});if(kagiResult)return withDeclaredLinks(kagiResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(kagiError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(kagiError)}continue}if(provider==="ollama"){try{if(isOllamaFetchAvailable()){let ssrf=loadSsrfConfig(),ollamaResult=await extractWithOllama(url,signal,{timeoutMs:options?.timeoutMs,...options?.lookup?{lookup:options.lookup}:{},ssrf});if(ollamaResult)return withDeclaredLinks(ollamaResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(ollamaError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(ollamaError)}continue}if(provider==="parallel"){try{if(isParallelAvailable()){let parallelResult=await extractWithParallel(url,signal,options);if(parallelResult)return withDeclaredLinks(parallelResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(parallelError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(parallelError)}continue}if(provider==="parallel-mcp"){try{let parallelMcpResult=await extractWithParallelMcp(url,signal,options);if(parallelMcpResult)return withDeclaredLinks(parallelMcpResult)}catch(err){if(isAbortError3(err))return abortedResult(url);if(parallelMcpError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(parallelMcpError)}continue}if(provider==="brightdata"){try{if(isBrightDataUnlockerAvailable()){let ssrf=loadSsrfConfig(),brightdataResult=await extractWithBrightDataUnlocker(url,signal,{timeoutMs:options?.timeoutMs,...options?.lookup?{lookup:options.lookup}:{},ssrf});if(brightdataResult)return withDeclaredLinks(brightdataResult)}}catch(err){if(isAbortError3(err))return abortedResult(url);if(brightdataError=errorMessage5(err),isConfigParseError(err))return parseErrorResult(brightdataError)}continue}if(provider==="gemini"){let geminiResult=null;try{geminiResult=await extractWithUrlContext(url,signal)??await extractWithGeminiWeb(url,signal)}catch(err){if(isAbortError3(err))return abortedResult(url);if(err instanceof CredentialResolutionError||isConfigParseError(err))return parseErrorResult(errorMessage5(err))}if(geminiResult)return withDeclaredLinks(geminiResult)}}if(signal?.aborted)return abortedResult(url);let finalHttpResult=httpResult;if(finalHttpResult&&declaredLinks.length>0)return{...finalHttpResult,error:null};if(finalHttpResult?.status===404||finalHttpResult?.status===410)return{...finalHttpResult,error:notFoundGuidance(finalHttpResult,options?.toolNames)};let searchToolName=options?.toolNames?.webSearch,guidance=[finalHttpResult?.error??"No fetch_content provider returned content",...firecrawlError?[`Firecrawl fallback failed: ${firecrawlError}`]:[],...crawl4aiError?[`Crawl4AI fallback failed: ${crawl4aiError}`]:[],...tinyfishError?[`TinyFish fallback failed: ${tinyfishError}`]:[],...search1apiError?[`Search1API fallback failed: ${search1apiError}`]:[],...queritError?[`Querit fallback failed: ${queritError}`]:[],...kagiError?[`Kagi fallback failed: ${kagiError}`]:[],...ollamaError?[`Ollama fallback failed: ${ollamaError}`]:[],...parallelError?[`Parallel fallback failed: ${parallelError}`]:[],...parallelMcpError?[`Parallel MCP fallback failed: ${parallelMcpError}`]:[],...brightdataError?[`Bright Data fallback failed: ${brightdataError}`]:[],"","Fallback options:",` \u2022 Set firecrawlBaseUrl in ${WEB_SEARCH_CONFIG_PATH} to a self-hosted Firecrawl instance`,` \u2022 Set crawl4aiBaseUrl in ${WEB_SEARCH_CONFIG_PATH} to a self-hosted Crawl4AI instance`,` \u2022 Set tinyfishApiKey in ${WEB_SEARCH_CONFIG_PATH} or TINYFISH_API_KEY`,` \u2022 Set search1apiApiKey in ${WEB_SEARCH_CONFIG_PATH} or SEARCH1API_KEY`,` \u2022 Set queritApiKey in ${WEB_SEARCH_CONFIG_PATH} or QUERIT_API_KEY`,` \u2022 Set kagiApiKey in ${WEB_SEARCH_CONFIG_PATH} or KAGI_API_KEY`,` \u2022 Set ollamaApiKey in ${WEB_SEARCH_CONFIG_PATH} or OLLAMA_API_KEY`,` \u2022 Set parallelApiKey in ${WEB_SEARCH_CONFIG_PATH} or PARALLEL_API_KEY`,` \u2022 Set brightdataApiKey and brightdataUnlockerZone in ${WEB_SEARCH_CONFIG_PATH} or BRIGHTDATA_API_KEY and BRIGHTDATA_UNLOCKER_ZONE`,` \u2022 Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`," \u2022 Sign into gemini.google.com in Chrome",...searchToolName?[` \u2022 Use ${searchToolName} to find content about this topic`]:[]].join(`
|
|
104
|
-
`);return{...finalHttpResult??{url,title:"",content:"",error:null},error:guidance}}function isLikelyJSRendered(html){let bodyMatch=html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(!bodyMatch)return!1;let textContent=bodyMatch[1].replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim(),scriptCount=(html.match(/<script/gi)||[]).length;return textContent.length<500&&scriptCount>3}async function readPDFResponseBuffer(response,maxSizeMB){let maxBytes=maxSizeMB*1024*1024;return readResponseBufferWithLimit(response,maxBytes,()=>pdfSizeLimitError(maxSizeMB))}async function readTextResponseWithLimit(response,maxBytes){let buffer=await readResponseBufferWithLimit(response,maxBytes,()=>responseSizeLimitError(maxBytes)),charset=response.headers.get("content-type")?.match(/charset\s*=\s*["']?([^;"'\s]+)/i)?.[1];try{return new TextDecoder(charset||"utf-8").decode(buffer)}catch{return new TextDecoder("utf-8").decode(buffer)}}function isTextContentType(contentType){let mimeType=contentType.split(";",1)[0]?.trim().toLowerCase()??"";return mimeType.startsWith("text/")||mimeType==="application/json"||mimeType==="application/ld+json"||mimeType==="application/xml"||mimeType==="application/xhtml+xml"||mimeType==="application/javascript"||mimeType==="application/x-javascript"||mimeType.endsWith("+json")||mimeType.endsWith("+xml")}async function readResponseBufferWithLimit(response,maxBytes,buildError){let reader=response.body?.getReader();if(!reader){let buffer=await response.arrayBuffer();if(buffer.byteLength>maxBytes)throw buildError();return buffer}let chunks=[],totalBytes=0;try{for(;;){let{done,value}=await reader.read();if(done)break;if(value){if(totalBytes+=value.byteLength,totalBytes>maxBytes)throw await reader.cancel(),buildError();chunks.push(value)}}}finally{reader.releaseLock()}let combined=new Uint8Array(totalBytes),offset=0;for(let chunk of chunks)combined.set(chunk,offset),offset+=chunk.byteLength;return combined.buffer}function pdfSizeLimitError(maxSizeMB){return new Error(`PDF exceeds configured pdf.maxSizeMB limit (${maxSizeMB} MB)`)}function responseSizeLimitError(maxBytes){return new Error(`Response too large (${Math.round(maxBytes/1024/1024)}MB)`)}async function extractViaHttp(url,timeoutMs,signal,options){let activityId=activityMonitor.logStart({type:"fetch",url}),controller=new AbortController,startedAt=Date.now(),timeoutId=setTimeout(()=>controller.abort(),timeoutMs),onAbort=()=>controller.abort();signal?.addEventListener("abort",onAbort);try{let ssrf=loadSsrfConfig(),domainPolicy=loadFetchContentDomainPolicy(),authProfile=options?.authFetchProfile,trustEnvProxy=options?.proxy===void 0&&ssrf.trustEnvProxy,requestInit={signal:controller.signal,__proxy:options?.proxy,headers:{"User-Agent":"OpenAI File Downloader, XaiImageApiFetch/1.0",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9","Cache-Control":"no-cache","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1"}},response=authProfile?await fetchAuthenticatedRemoteUrl(url,requestInit,{ssrf:{...ssrf,trustEnvProxy},domainPolicy,...options?.lookup?{lookup:options.lookup}:{}},authProfile):await fetchRemoteUrl(url,requestInit,{allowRanges:ssrf.allowRanges,trustEnvProxy,domainPolicy,...options?.lookup?{lookup:options.lookup}:{}});if(!response.ok&&options?.mode!=="raw")return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:`HTTP ${response.status}: ${response.statusText}`,status:response.status};let contentLengthHeader=response.headers.get("content-length"),contentType=response.headers.get("content-type")||"",mimeType=contentType.split(";",1)[0]?.trim().toLowerCase()??"",isPDFContent=isPDF(url,contentType),pdfConfig=isPDFContent?loadPDFConfig():null;if(isPDFContent&&pdfConfig&&!pdfConfig.enabled)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:"PDF extraction is disabled by pdf.enabled",mimeType,status:response.status};let maxResponseSize=(pdfConfig?.maxSizeMB??5)*1024*1024;if(contentLengthHeader){let contentLength=Number.parseInt(contentLengthHeader,10);if(Number.isFinite(contentLength)&&contentLength>maxResponseSize)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:pdfConfig?pdfSizeLimitError(pdfConfig.maxSizeMB).message:`Response too large (${Math.round(contentLength/1024/1024)}MB)`}}if(options?.mode==="raw"){if(!isTextContentType(contentType))return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:`Unsupported content type in raw mode: ${mimeType||"missing"}`,mimeType,status:response.status};let text2=await readTextResponseWithLimit(response,maxResponseSize);return activityMonitor.logComplete(activityId,response.status),{url,title:extractTextTitle(text2,url),content:text2,error:null,mimeType,status:response.status}}if(SUPPORTED_IMAGE_TYPES.has(mimeType)){let disabled=imageGateError();if(disabled)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:disabled,mimeType,status:response.status};try{let buffer=await readResponseBufferWithLimit(response,maxResponseSize,()=>responseSizeLimitError(maxResponseSize)),{resizeImage}=await import("./host-WP3MVKS2.js"),resized=await resizeImage(new Uint8Array(buffer),mimeType,{maxWidth:2e3,maxHeight:2e3});if(activityMonitor.logComplete(activityId,response.status),!resized)return{url,title:"",content:"",error:`Could not decode image: ${mimeType}`,mimeType,status:response.status};let title=new URL(response.url||url).pathname.split("/").pop()||url;return{url,title,content:`Image fetched (${resized.width}\xD7${resized.height}, ${resized.mimeType})`,error:null,thumbnail:{data:resized.data,mimeType:resized.mimeType},mimeType:resized.mimeType,status:response.status}}catch(err){let message=errorMessage5(err);return activityMonitor.logError(activityId,message),{url,title:"",content:"",error:message,mimeType,status:response.status}}}if(isPDFContent&&pdfConfig)try{let buffer=await readPDFResponseBuffer(response,pdfConfig.maxSizeMB);if(signal?.aborted)return abortedResult(url);let result=await extractPDFToMarkdown(buffer,url,{signal});return activityMonitor.logComplete(activityId,response.status),{url,title:result.title,content:`PDF extracted and saved to: ${result.outputPath}
|
|
104
|
+
`);return{...finalHttpResult??{url,title:"",content:"",error:null},error:guidance}}function isLikelyJSRendered(html){let bodyMatch=html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(!bodyMatch)return!1;let textContent=bodyMatch[1].replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim(),scriptCount=(html.match(/<script/gi)||[]).length;return textContent.length<500&&scriptCount>3}async function readPDFResponseBuffer(response,maxSizeMB){let maxBytes=maxSizeMB*1024*1024;return readResponseBufferWithLimit(response,maxBytes,()=>pdfSizeLimitError(maxSizeMB))}async function readTextResponseWithLimit(response,maxBytes){let buffer=await readResponseBufferWithLimit(response,maxBytes,()=>responseSizeLimitError(maxBytes)),charset=response.headers.get("content-type")?.match(/charset\s*=\s*["']?([^;"'\s]+)/i)?.[1];try{return new TextDecoder(charset||"utf-8").decode(buffer)}catch{return new TextDecoder("utf-8").decode(buffer)}}function isTextContentType(contentType){let mimeType=contentType.split(";",1)[0]?.trim().toLowerCase()??"";return mimeType.startsWith("text/")||mimeType==="application/json"||mimeType==="application/ld+json"||mimeType==="application/xml"||mimeType==="application/xhtml+xml"||mimeType==="application/javascript"||mimeType==="application/x-javascript"||mimeType.endsWith("+json")||mimeType.endsWith("+xml")}async function readResponseBufferWithLimit(response,maxBytes,buildError){let reader=response.body?.getReader();if(!reader){let buffer=await response.arrayBuffer();if(buffer.byteLength>maxBytes)throw buildError();return buffer}let chunks=[],totalBytes=0;try{for(;;){let{done,value}=await reader.read();if(done)break;if(value){if(totalBytes+=value.byteLength,totalBytes>maxBytes)throw await reader.cancel(),buildError();chunks.push(value)}}}finally{reader.releaseLock()}let combined=new Uint8Array(totalBytes),offset=0;for(let chunk of chunks)combined.set(chunk,offset),offset+=chunk.byteLength;return combined.buffer}function pdfSizeLimitError(maxSizeMB){return new Error(`PDF exceeds configured pdf.maxSizeMB limit (${maxSizeMB} MB)`)}function responseSizeLimitError(maxBytes){return new Error(`Response too large (${Math.round(maxBytes/1024/1024)}MB)`)}async function extractViaHttp(url,timeoutMs,signal,options){let activityId=activityMonitor.logStart({type:"fetch",url}),controller=new AbortController,startedAt=Date.now(),timeoutId=setTimeout(()=>controller.abort(),timeoutMs),onAbort=()=>controller.abort();signal?.addEventListener("abort",onAbort);try{let ssrf=loadSsrfConfig(),domainPolicy=loadFetchContentDomainPolicy(),authProfile=options?.authFetchProfile,trustEnvProxy=options?.proxy===void 0&&ssrf.trustEnvProxy,requestInit={signal:controller.signal,__proxy:options?.proxy,headers:{"User-Agent":"OpenAI File Downloader, XaiImageApiFetch/1.0",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9","Cache-Control":"no-cache","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1"}},response=authProfile?await fetchAuthenticatedRemoteUrl(url,requestInit,{ssrf:{...ssrf,trustEnvProxy},domainPolicy,...options?.lookup?{lookup:options.lookup}:{}},authProfile):await fetchRemoteUrl(url,requestInit,{allowRanges:ssrf.allowRanges,trustEnvProxy,domainPolicy,...options?.lookup?{lookup:options.lookup}:{}});if(!response.ok&&options?.mode!=="raw")return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:`HTTP ${response.status}: ${response.statusText}`,status:response.status};let contentLengthHeader=response.headers.get("content-length"),contentType=response.headers.get("content-type")||"",mimeType=contentType.split(";",1)[0]?.trim().toLowerCase()??"",isPDFContent=isPDF(url,contentType),pdfConfig=isPDFContent?loadPDFConfig():null;if(isPDFContent&&pdfConfig&&!pdfConfig.enabled)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:"PDF extraction is disabled by pdf.enabled",mimeType,status:response.status};let maxResponseSize=(pdfConfig?.maxSizeMB??5)*1024*1024;if(contentLengthHeader){let contentLength=Number.parseInt(contentLengthHeader,10);if(Number.isFinite(contentLength)&&contentLength>maxResponseSize)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:pdfConfig?pdfSizeLimitError(pdfConfig.maxSizeMB).message:`Response too large (${Math.round(contentLength/1024/1024)}MB)`}}if(options?.mode==="raw"){if(!isTextContentType(contentType))return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:`Unsupported content type in raw mode: ${mimeType||"missing"}`,mimeType,status:response.status};let text2=await readTextResponseWithLimit(response,maxResponseSize);return activityMonitor.logComplete(activityId,response.status),{url,title:extractTextTitle(text2,url),content:text2,error:null,mimeType,status:response.status}}if(SUPPORTED_IMAGE_TYPES.has(mimeType)){let disabled=imageGateError();if(disabled)return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:disabled,mimeType,status:response.status};try{let buffer=await readResponseBufferWithLimit(response,maxResponseSize,()=>responseSizeLimitError(maxResponseSize)),{resizeImage}=await import("./host-WP3MVKS2.js"),resized=await resizeImage(new Uint8Array(buffer),mimeType,{maxWidth:2e3,maxHeight:2e3});if(activityMonitor.logComplete(activityId,response.status),!resized)return{url,title:"",content:"",error:`Could not decode image: ${mimeType}`,mimeType,status:response.status};let title=new URL(response.url||url).pathname.split("/").pop()||url;return{url,title,content:`Image fetched (${resized.width}\xD7${resized.height}, ${resized.mimeType})`,error:null,thumbnail:{data:resized.data,mimeType:resized.mimeType},mimeType:resized.mimeType,status:response.status}}catch(err){let message=errorMessage5(err);return activityMonitor.logError(activityId,message),{url,title:"",content:"",error:message,mimeType,status:response.status}}}if(isPDFContent&&pdfConfig)try{let buffer=await readPDFResponseBuffer(response,pdfConfig.maxSizeMB);if(signal?.aborted)return abortedResult(url);let result=await extractPDFToMarkdown(buffer,url,{signal});return activityMonitor.logComplete(activityId,response.status),{url,title:result.title,content:options?.mode==="answer"?result.content:`PDF extracted and saved to: ${result.outputPath}
|
|
105
105
|
|
|
106
106
|
Pages: ${result.pages}
|
|
107
107
|
Characters: ${result.chars}`,error:null}}catch(err){let message=err instanceof Error?err.message:String(err);return activityMonitor.logError(activityId,message),message.startsWith("PDF exceeds configured pdf.maxSizeMB limit")?{url,title:"",content:"",error:message}:err instanceof CredentialResolutionError||isConfigParseError(err)?{url,title:"",content:"",error:message}:{url,title:"",content:"",error:`PDF extraction failed: ${message}`}}if(contentType.includes("application/octet-stream")||contentType.includes("image/")||contentType.includes("audio/")||contentType.includes("video/")||contentType.includes("application/zip"))return activityMonitor.logComplete(activityId,response.status),{url,title:"",content:"",error:`Unsupported content type: ${contentType.split(";")[0]}`};let text=await readTextResponseWithLimit(response,maxResponseSize);if(!(contentType.includes("text/html")||contentType.includes("application/xhtml+xml"))){activityMonitor.logComplete(activityId,response.status);let title=extractTextTitle(text,url);return{url,title,content:text,error:null}}let{parseHTML}=await import("./esm-E7UVEYTO.js"),{document}=parseHTML(text),documentTitle=document.title?.trim()??"",declaredLinks=discoverDeclaredWebLinks(document,response.headers.get("link"),response.url||url),{Readability}=await import("./readability-LAGF34IB.js"),article=new Readability(document).parse();if(!article){let rscResult=extractRSCContent(text);if(rscResult&&rscResult.content.length>=MIN_USEFUL_CONTENT)return activityMonitor.logComplete(activityId,response.status),{url,title:rscResult.title,content:appendDeclaredWebLinks(rscResult.content,declaredLinks),error:null,declaredLinks};controller.signal.throwIfAborted();let defuddleResult=await extractWithDefuddle(text,response.url||url);if(controller.signal.throwIfAborted(),defuddleResult&&defuddleResult.content.length>=MIN_USEFUL_CONTENT)return activityMonitor.logComplete(activityId,response.status),{url,title:documentTitle||defuddleResult.title,content:appendDeclaredWebLinks(defuddleResult.content,declaredLinks),error:null,declaredLinks};activityMonitor.logComplete(activityId,response.status);let errorMsg=isLikelyJSRendered(text)?"Page appears to be JavaScript-rendered (content loads dynamically)":"Could not extract readable content from HTML structure";return{url,title:documentTitle,content:appendDeclaredWebLinks("",declaredLinks),error:errorMsg,declaredLinks}}if(typeof article.content!="string")throw new Error("Readability returned invalid article content");let markdown=(await getTurndown()).turndown(article.content);if(activityMonitor.logComplete(activityId,response.status),markdown.length<MIN_USEFUL_CONTENT){let rscResult=extractRSCContent(text);if(rscResult&&rscResult.content.length>=MIN_USEFUL_CONTENT)return{url,title:rscResult.title,content:appendDeclaredWebLinks(rscResult.content,declaredLinks),error:null,declaredLinks};controller.signal.throwIfAborted();let defuddleResult=await extractWithDefuddle(text,response.url||url);return controller.signal.throwIfAborted(),defuddleResult&&defuddleResult.content.length>=MIN_USEFUL_CONTENT?{url,title:article.title||documentTitle||defuddleResult.title,content:appendDeclaredWebLinks(defuddleResult.content,declaredLinks),error:null,declaredLinks}:{url,title:article.title||documentTitle,content:appendDeclaredWebLinks(markdown,declaredLinks),error:isLikelyJSRendered(text)?"Page appears to be JavaScript-rendered (content loads dynamically)":"Extracted content appears incomplete",declaredLinks}}return{url,title:article.title||documentTitle,content:appendDeclaredWebLinks(markdown,declaredLinks),error:null,declaredLinks}}catch(err){let message=err instanceof Error?err.message:String(err);return message.toLowerCase().includes("abort")?activityMonitor.logComplete(activityId,0):activityMonitor.logError(activityId,message),{url,title:"",content:"",error:message}}finally{if(clearTimeout(timeoutId),signal?.removeEventListener("abort",onAbort),signal?.aborted)return abortedResult(url);if(controller.signal.aborted||Date.now()-startedAt>=timeoutMs)return{url,title:"",content:"",error:"The operation was aborted."}}}function extractHeadingTitle(text){let match=text.match(/^#{1,2}\s+(.+)/m);return match&&match[1].replace(/\*+/g,"").trim()||null}function extractTextTitle(text,url){return extractHeadingTitle(text)??(new URL(url).pathname.split("/").pop()||url)}async function fetchAllContent(urls,signal,options){let results=await Promise.all(urls.map(url=>fetchLimit(()=>extractContent(url,signal,options))));return options?.mode==="raw"?results:results.map((result,index)=>{if(!result.content)return result;let sanitized=sanitizeInlineDataUris(result.content,`urls[${index}].content`);return sanitized.omissions.length>0?{...result,content:sanitized.text}:result})}export{extractContent,extractHeadingTitle,fetchAllContent,loadSsrfAllowRanges,loadSsrfConfig,readPDFResponseBuffer,resolveFetchTimeoutMs};
|
package/dist/bundle/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
3
|
-
import{configureHttpDispatcher,main}from"./chunks/chunk-
|
|
3
|
+
import{configureHttpDispatcher,main}from"./chunks/chunk-WKLAQTQ4.js";import"./chunks/chunk-S43N4JYF.js";import{APP_NAME,ENV_PREFIX}from"./chunks/chunk-LI2YVPWP.js";import"./chunks/chunk-CBTAWCW5.js";import"./chunks/chunk-SGTGQNNP.js";import"./chunks/chunk-ECWELYBH.js";import"./chunks/chunk-74NVHVNZ.js";import"./chunks/chunk-PL7O7J4J.js";import"./chunks/chunk-7T6XCLJF.js";import"./chunks/chunk-USJZMAIR.js";import"./chunks/chunk-7DDKXS2Q.js";import"./chunks/chunk-D7XAASZM.js";import"./chunks/chunk-E6KP6V7F.js";import"./chunks/chunk-72KO4OMP.js";import"./chunks/chunk-JXWJOIH4.js";function setupCli(){process.title=APP_NAME,process.env.PI_CODING_AGENT="true",process.env[`${ENV_PREFIX}_CODING_AGENT`]="true",process.env.AI_AGENT="pi",process.emitWarning=(()=>{}),configureHttpDispatcher()}setupCli();main(process.argv.slice(2));
|
package/dist/bundle/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
2
|
-
import{AgentExecInputError,AgentSession,AgentSessionRuntime,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BorderedLoader,BranchSummaryMessageComponent,CURRENT_SESSION_VERSION,CompactionSummaryMessageComponent,CredentialSynchronizationError,CustomEditor,CustomMessageComponent,DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,DefaultPackageManager,DefaultResourceLoader,DynamicBorder,ExtensionEditorComponent,ExtensionInputComponent,ExtensionRunner,ExtensionSelectorComponent,FooterComponent,HUMAIN_AGENT_EXECUTION_FAILURE_CODES,HUMAIN_AGENT_EXECUTION_SCHEMA_VERSION,HumainAgentArtifactSchema,HumainAgentExecutionClaimSchema,HumainAgentExecutionControlsSchema,HumainAgentExecutionOutcomeSchema,HumainAgentExecutionRequestSchema,HumainAgentExecutionResponseSchema,HumainAgentRouteRefSchema,HumainAgentUsageSchema,InteractiveMode,LoginDialogComponent,ModelRegistry,ModelRuntime,ModelSelectorComponent,OAuthSelectorComponent,ProjectTrustStore,RpcClient,SessionManager,SessionSelectorComponent,SettingsManager,SettingsSelectorComponent,ShowImagesSelectorComponent,SkillInvocationMessageComponent,Theme,ThemeSelectorComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,buildContextEntries,buildSessionContext,calculateContextTokens,collectEntriesForBranchSummary,compact,convertToLlm,convertToPng,copyToClipboard,createAgentSession,createAgentSessionFromServices,createAgentSessionRuntime,createAgentSessionServices,createBashTool,createBashToolDefinition,createCodingTools,createEditTool,createEditToolDefinition,createEventBus,createExtensionRuntime,createFindTool,createFindToolDefinition,createGrepTool,createGrepToolDefinition,createLocalBashOperations,createLocalPowerShellOperations,createLsTool,createLsToolDefinition,createPiAgentExecutionHost,createPowerShellTool,createPowerShellToolDefinition,createReadOnlyTools,createReadTool,createReadToolDefinition,createSyntheticSourceInfo,createWriteTool,createWriteToolDefinition,defineTool,detectSupportedImageMimeTypeFromFile,discoverAndLoadExtensions,estimateTokens,executeHumainAgentRequest,findCutPoint,findTurnStartIndex,formatSize,formatSkillsForPrompt,generateBranchSummary,generateDiffString,generateSummary,generateSummaryWithUsage,generateUnifiedPatch,getLanguageFromPath,getLastAssistantUsage,getLatestCompactionEntry,getMarkdownTheme,getPowerShellConfig,getSelectListTheme,getSettingsListTheme,getShellConfig,hasTrustRequiringProjectResources,highlightCode,initTheme,isBashToolResult,isEditToolResult,isFindToolResult,isGrepToolResult,isLsToolResult,isPowerShellToolResult,isReadToolResult,isToolCallEventType,isWriteToolResult,keyHint,keyText,loadProjectContextFiles,loadSkills,loadSkillsFromDir,main,migrateSessionEntries,parseArgs,parseFrontmatter,parseHumainAgentExecutionRequest,parseHumainAgentExecutionResponse,parseSessionEntries,parseSkillBlock,prepareBranchEntries,rawKeyHint,readStoredCredential,renderDiff,resolveCliModel,resolveModelScopeWithDiagnostics,runAgentExecMode,runPrintMode,runRpcMode,serializeConversation,sessionEntryToContextMessages,shouldCompact,stripFrontmatter,truncateHead,truncateLine,truncateTail,truncateToVisualLines,withFileMutationQueue,wrapRegisteredTool,wrapRegisteredTools}from"./chunks/chunk-
|
|
2
|
+
import{AgentExecInputError,AgentSession,AgentSessionRuntime,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BorderedLoader,BranchSummaryMessageComponent,CURRENT_SESSION_VERSION,CompactionSummaryMessageComponent,CredentialSynchronizationError,CustomEditor,CustomMessageComponent,DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,DefaultPackageManager,DefaultResourceLoader,DynamicBorder,ExtensionEditorComponent,ExtensionInputComponent,ExtensionRunner,ExtensionSelectorComponent,FooterComponent,HUMAIN_AGENT_EXECUTION_FAILURE_CODES,HUMAIN_AGENT_EXECUTION_SCHEMA_VERSION,HumainAgentArtifactSchema,HumainAgentExecutionClaimSchema,HumainAgentExecutionControlsSchema,HumainAgentExecutionOutcomeSchema,HumainAgentExecutionRequestSchema,HumainAgentExecutionResponseSchema,HumainAgentRouteRefSchema,HumainAgentUsageSchema,InteractiveMode,LoginDialogComponent,ModelRegistry,ModelRuntime,ModelSelectorComponent,OAuthSelectorComponent,ProjectTrustStore,RpcClient,SessionManager,SessionSelectorComponent,SettingsManager,SettingsSelectorComponent,ShowImagesSelectorComponent,SkillInvocationMessageComponent,Theme,ThemeSelectorComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,buildContextEntries,buildSessionContext,calculateContextTokens,collectEntriesForBranchSummary,compact,convertToLlm,convertToPng,copyToClipboard,createAgentSession,createAgentSessionFromServices,createAgentSessionRuntime,createAgentSessionServices,createBashTool,createBashToolDefinition,createCodingTools,createEditTool,createEditToolDefinition,createEventBus,createExtensionRuntime,createFindTool,createFindToolDefinition,createGrepTool,createGrepToolDefinition,createLocalBashOperations,createLocalPowerShellOperations,createLsTool,createLsToolDefinition,createPiAgentExecutionHost,createPowerShellTool,createPowerShellToolDefinition,createReadOnlyTools,createReadTool,createReadToolDefinition,createSyntheticSourceInfo,createWriteTool,createWriteToolDefinition,defineTool,detectSupportedImageMimeTypeFromFile,discoverAndLoadExtensions,estimateTokens,executeHumainAgentRequest,findCutPoint,findTurnStartIndex,formatSize,formatSkillsForPrompt,generateBranchSummary,generateDiffString,generateSummary,generateSummaryWithUsage,generateUnifiedPatch,getLanguageFromPath,getLastAssistantUsage,getLatestCompactionEntry,getMarkdownTheme,getPowerShellConfig,getSelectListTheme,getSettingsListTheme,getShellConfig,hasTrustRequiringProjectResources,highlightCode,initTheme,isBashToolResult,isEditToolResult,isFindToolResult,isGrepToolResult,isLsToolResult,isPowerShellToolResult,isReadToolResult,isToolCallEventType,isWriteToolResult,keyHint,keyText,loadProjectContextFiles,loadSkills,loadSkillsFromDir,main,migrateSessionEntries,parseArgs,parseFrontmatter,parseHumainAgentExecutionRequest,parseHumainAgentExecutionResponse,parseSessionEntries,parseSkillBlock,prepareBranchEntries,rawKeyHint,readStoredCredential,renderDiff,resolveCliModel,resolveModelScopeWithDiagnostics,runAgentExecMode,runPrintMode,runRpcMode,serializeConversation,sessionEntryToContextMessages,shouldCompact,stripFrontmatter,truncateHead,truncateLine,truncateTail,truncateToVisualLines,withFileMutationQueue,wrapRegisteredTool,wrapRegisteredTools}from"./chunks/chunk-WKLAQTQ4.js";import"./chunks/chunk-S43N4JYF.js";import{CONFIG_DIR_NAME,UPSTREAM_PI_VERSION,VERSION,formatDimensionNote,getAgentDir,getDocsPath,getExamplesPath,getPackageDir,getReadmePath,resizeImage}from"./chunks/chunk-LI2YVPWP.js";import"./chunks/chunk-CBTAWCW5.js";import"./chunks/chunk-SGTGQNNP.js";import"./chunks/chunk-ECWELYBH.js";import"./chunks/chunk-74NVHVNZ.js";import"./chunks/chunk-PL7O7J4J.js";import"./chunks/chunk-7T6XCLJF.js";import"./chunks/chunk-USJZMAIR.js";import"./chunks/chunk-7DDKXS2Q.js";import"./chunks/chunk-D7XAASZM.js";import"./chunks/chunk-E6KP6V7F.js";import"./chunks/chunk-72KO4OMP.js";import"./chunks/chunk-JXWJOIH4.js";export{AgentExecInputError,AgentSession,AgentSessionRuntime,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BorderedLoader,BranchSummaryMessageComponent,CONFIG_DIR_NAME,CURRENT_SESSION_VERSION,CompactionSummaryMessageComponent,CredentialSynchronizationError,CustomEditor,CustomMessageComponent,DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,DefaultPackageManager,DefaultResourceLoader,DynamicBorder,ExtensionEditorComponent,ExtensionInputComponent,ExtensionRunner,ExtensionSelectorComponent,FooterComponent,HUMAIN_AGENT_EXECUTION_FAILURE_CODES,HUMAIN_AGENT_EXECUTION_SCHEMA_VERSION,HumainAgentArtifactSchema,HumainAgentExecutionClaimSchema,HumainAgentExecutionControlsSchema,HumainAgentExecutionOutcomeSchema,HumainAgentExecutionRequestSchema,HumainAgentExecutionResponseSchema,HumainAgentRouteRefSchema,HumainAgentUsageSchema,InteractiveMode,LoginDialogComponent,ModelRegistry,ModelRuntime,ModelSelectorComponent,OAuthSelectorComponent,ProjectTrustStore,RpcClient,SessionManager,SessionSelectorComponent,SettingsManager,SettingsSelectorComponent,ShowImagesSelectorComponent,SkillInvocationMessageComponent,Theme,ThemeSelectorComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UPSTREAM_PI_VERSION,UserMessageComponent,UserMessageSelectorComponent,VERSION,buildContextEntries,buildSessionContext,calculateContextTokens,collectEntriesForBranchSummary,compact,convertToLlm,convertToPng,copyToClipboard,createAgentSession,createAgentSessionFromServices,createAgentSessionRuntime,createAgentSessionServices,createBashTool,createBashToolDefinition,createCodingTools,createEditTool,createEditToolDefinition,createEventBus,createExtensionRuntime,createFindTool,createFindToolDefinition,createGrepTool,createGrepToolDefinition,createLocalBashOperations,createLocalPowerShellOperations,createLsTool,createLsToolDefinition,createPiAgentExecutionHost,createPowerShellTool,createPowerShellToolDefinition,createReadOnlyTools,createReadTool,createReadToolDefinition,createSyntheticSourceInfo,createWriteTool,createWriteToolDefinition,defineTool,detectSupportedImageMimeTypeFromFile,discoverAndLoadExtensions,estimateTokens,executeHumainAgentRequest,findCutPoint,findTurnStartIndex,formatDimensionNote,formatSize,formatSkillsForPrompt,generateBranchSummary,generateDiffString,generateSummary,generateSummaryWithUsage,generateUnifiedPatch,getAgentDir,getDocsPath,getExamplesPath,getLanguageFromPath,getLastAssistantUsage,getLatestCompactionEntry,getMarkdownTheme,getPackageDir,getPowerShellConfig,getReadmePath,getSelectListTheme,getSettingsListTheme,getShellConfig,hasTrustRequiringProjectResources,highlightCode,initTheme,isBashToolResult,isEditToolResult,isFindToolResult,isGrepToolResult,isLsToolResult,isPowerShellToolResult,isReadToolResult,isToolCallEventType,isWriteToolResult,keyHint,keyText,loadProjectContextFiles,loadSkills,loadSkillsFromDir,main,migrateSessionEntries,parseArgs,parseFrontmatter,parseHumainAgentExecutionRequest,parseHumainAgentExecutionResponse,parseSessionEntries,parseSkillBlock,prepareBranchEntries,rawKeyHint,readStoredCredential,renderDiff,resizeImage,resolveCliModel,resolveModelScopeWithDiagnostics,runAgentExecMode,runPrintMode,runRpcMode,serializeConversation,sessionEntryToContextMessages,shouldCompact,stripFrontmatter,truncateHead,truncateLine,truncateTail,truncateToVisualLines,withFileMutationQueue,wrapRegisteredTool,wrapRegisteredTools};
|
package/dist/bundle/rpc-entry.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
3
|
-
import{configureHttpDispatcher,main}from"./chunks/chunk-
|
|
3
|
+
import{configureHttpDispatcher,main}from"./chunks/chunk-WKLAQTQ4.js";import"./chunks/chunk-S43N4JYF.js";import{APP_NAME}from"./chunks/chunk-LI2YVPWP.js";import"./chunks/chunk-CBTAWCW5.js";import"./chunks/chunk-SGTGQNNP.js";import"./chunks/chunk-ECWELYBH.js";import"./chunks/chunk-74NVHVNZ.js";import"./chunks/chunk-PL7O7J4J.js";import"./chunks/chunk-7T6XCLJF.js";import"./chunks/chunk-USJZMAIR.js";import"./chunks/chunk-7DDKXS2Q.js";import"./chunks/chunk-D7XAASZM.js";import"./chunks/chunk-E6KP6V7F.js";import"./chunks/chunk-72KO4OMP.js";import"./chunks/chunk-JXWJOIH4.js";process.title=`${APP_NAME}-rpc`;process.env.PI_CODING_AGENT="true";process.env.AI_AGENT="pi";process.emitWarning=(()=>{});configureHttpDispatcher();main(["--mode","rpc",...process.argv.slice(2)]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anysearch.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/anysearch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"anysearch.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/anysearch.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAmBrE,UAAU,sBAAuB,SAAQ,aAAa;IACrD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAsFD,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,cAAc,CAAC,CAkEtH"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { activityMonitor } from "./activity.js";
|
|
3
|
+
import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
|
|
4
|
+
import { normalizeSearchResultCount } from "./search-result-count-normalization.js";
|
|
3
5
|
import { redactCredential, resolveCredential } from "./credential-source.js";
|
|
4
6
|
import { getWebSearchConfigPath } from "./utils.js";
|
|
5
7
|
const ANYSEARCH_API_URL = "https://api.anysearch.com/v1/search";
|
|
@@ -36,11 +38,6 @@ async function getApiKey(signal) {
|
|
|
36
38
|
signal,
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
|
-
function normalizeCount(value) {
|
|
40
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
41
|
-
return 5;
|
|
42
|
-
return Math.max(1, Math.min(Math.floor(value), 20));
|
|
43
|
-
}
|
|
44
41
|
function errorMessage(err) {
|
|
45
42
|
return err instanceof Error ? err.message : String(err);
|
|
46
43
|
}
|
|
@@ -85,19 +82,12 @@ function parseResponse(value) {
|
|
|
85
82
|
}
|
|
86
83
|
return { code: 0, data: { results, metadata: data.metadata } };
|
|
87
84
|
}
|
|
88
|
-
function buildAnswer(results) {
|
|
89
|
-
return results
|
|
90
|
-
.map((result) => result.snippet
|
|
91
|
-
? `${result.snippet}\nSource: ${result.title} (${result.url})`
|
|
92
|
-
: `Source: ${result.title} (${result.url})`)
|
|
93
|
-
.join("\n\n");
|
|
94
|
-
}
|
|
95
85
|
export function isAnySearchAvailable() {
|
|
96
86
|
return true;
|
|
97
87
|
}
|
|
98
88
|
export async function searchWithAnySearch(query, options = {}) {
|
|
99
89
|
const apiKey = await getApiKey(options.signal);
|
|
100
|
-
const numResults =
|
|
90
|
+
const numResults = normalizeSearchResultCount(options.numResults);
|
|
101
91
|
const body = { query, max_results: numResults };
|
|
102
92
|
const activityId = activityMonitor.logStart({ type: "api", query });
|
|
103
93
|
let response;
|
|
@@ -155,7 +145,7 @@ export async function searchWithAnySearch(query, options = {}) {
|
|
|
155
145
|
url: result.url,
|
|
156
146
|
snippet: result.snippet,
|
|
157
147
|
}));
|
|
158
|
-
const mapped = { answer:
|
|
148
|
+
const mapped = { answer: formatSearchResultsAsAnswer(results), results };
|
|
159
149
|
if (options.includeContent) {
|
|
160
150
|
const inlineContent = data.data.results.slice(0, numResults)
|
|
161
151
|
.filter(result => result.content.length > 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anysearch.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/anysearch.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst ANYSEARCH_API_URL = \"https://api.anysearch.com/v1/search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 30_000;\n\ninterface WebSearchConfig {\n\tanysearchApiKey?: unknown;\n}\n\ninterface AnySearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n\tcontent: string;\n}\n\ninterface AnySearchSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\ninterface AnySearchResponse {\n\tcode: 0;\n\tdata: {\n\t\tresults: AnySearchResult[];\n\t\tmetadata: Record<string, unknown>;\n\t};\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"AnySearch\",\n\t\tconfiguredValue: loadConfig().anysearchApiKey,\n\t\tenvironmentValue: process.env.ANYSEARCH_API_KEY,\n\t\tsignal,\n\t});\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`AnySearch API returned invalid response: ${message}`);\n}\n\nfunction parseResponse(value: unknown): AnySearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst envelope = value as Record<string, unknown>;\n\tif (envelope.code !== 0) throw invalidResponse(\"expected code 0\");\n\tif (!envelope.data || typeof envelope.data !== \"object\" || Array.isArray(envelope.data)) {\n\t\tthrow invalidResponse(\"expected data object\");\n\t}\n\tconst data = envelope.data as Record<string, unknown>;\n\tif (!Array.isArray(data.results)) throw invalidResponse(\"expected data.results array\");\n\tif (!data.metadata || typeof data.metadata !== \"object\" || Array.isArray(data.metadata)) {\n\t\tthrow invalidResponse(\"expected data.metadata object\");\n\t}\n\n\tconst results: AnySearchResult[] = [];\n\tfor (const [index, value] of data.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\t\tthrow invalidResponse(`expected data.results[${index}] object`);\n\t\t}\n\t\tconst result = value as Record<string, unknown>;\n\t\tconst { title, url, snippet, content } = result;\n\t\tif (typeof title !== \"string\") throw invalidResponse(`expected data.results[${index}].title string`);\n\t\tif (typeof url !== \"string\") throw invalidResponse(`expected data.results[${index}].url string`);\n\t\tif (typeof snippet !== \"string\") throw invalidResponse(`expected data.results[${index}].snippet string`);\n\t\tif (content !== undefined && content !== null && typeof content !== \"string\") {\n\t\t\tthrow invalidResponse(`expected data.results[${index}].content string`);\n\t\t}\n\t\tif (!url) throw invalidResponse(`expected data.results[${index}].url to be non-empty`);\n\t\tresults.push({ title, url, snippet, content: typeof content === \"string\" ? content : \"\" });\n\t}\n\n\treturn { code: 0, data: { results, metadata: data.metadata as Record<string, unknown> } };\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results\n\t\t.map((result) => result.snippet\n\t\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t\t: `Source: ${result.title} (${result.url})`)\n\t\t.join(\"\\n\\n\");\n}\n\nexport function isAnySearchAvailable(): boolean {\n\treturn true;\n}\n\nexport async function searchWithAnySearch(query: string, options: AnySearchSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst body = { query, max_results: numResults };\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\n\ttry {\n\t\tresponse = await fetch(ANYSEARCH_API_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`AnySearch API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`AnySearch API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tlet data: AnySearchResponse;\n\ttry {\n\t\tdata = parseResponse(rawData);\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow err;\n\t}\n\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.data.results.slice(0, numResults).map((result) => ({\n\t\ttitle: result.title,\n\t\turl: result.url,\n\t\tsnippet: result.snippet,\n\t}));\n\tconst mapped: SearchResponse = { answer: buildAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"anysearch.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/anysearch.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport { normalizeSearchResultCount } from \"./search-result-count-normalization.ts\";\nimport type { ExtractedContent } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst ANYSEARCH_API_URL = \"https://api.anysearch.com/v1/search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 30_000;\n\ninterface WebSearchConfig {\n\tanysearchApiKey?: unknown;\n}\n\ninterface AnySearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n\tcontent: string;\n}\n\ninterface AnySearchSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\ninterface AnySearchResponse {\n\tcode: 0;\n\tdata: {\n\t\tresults: AnySearchResult[];\n\t\tmetadata: Record<string, unknown>;\n\t};\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"AnySearch\",\n\t\tconfiguredValue: loadConfig().anysearchApiKey,\n\t\tenvironmentValue: process.env.ANYSEARCH_API_KEY,\n\t\tsignal,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`AnySearch API returned invalid response: ${message}`);\n}\n\nfunction parseResponse(value: unknown): AnySearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst envelope = value as Record<string, unknown>;\n\tif (envelope.code !== 0) throw invalidResponse(\"expected code 0\");\n\tif (!envelope.data || typeof envelope.data !== \"object\" || Array.isArray(envelope.data)) {\n\t\tthrow invalidResponse(\"expected data object\");\n\t}\n\tconst data = envelope.data as Record<string, unknown>;\n\tif (!Array.isArray(data.results)) throw invalidResponse(\"expected data.results array\");\n\tif (!data.metadata || typeof data.metadata !== \"object\" || Array.isArray(data.metadata)) {\n\t\tthrow invalidResponse(\"expected data.metadata object\");\n\t}\n\n\tconst results: AnySearchResult[] = [];\n\tfor (const [index, value] of data.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\t\tthrow invalidResponse(`expected data.results[${index}] object`);\n\t\t}\n\t\tconst result = value as Record<string, unknown>;\n\t\tconst { title, url, snippet, content } = result;\n\t\tif (typeof title !== \"string\") throw invalidResponse(`expected data.results[${index}].title string`);\n\t\tif (typeof url !== \"string\") throw invalidResponse(`expected data.results[${index}].url string`);\n\t\tif (typeof snippet !== \"string\") throw invalidResponse(`expected data.results[${index}].snippet string`);\n\t\tif (content !== undefined && content !== null && typeof content !== \"string\") {\n\t\t\tthrow invalidResponse(`expected data.results[${index}].content string`);\n\t\t}\n\t\tif (!url) throw invalidResponse(`expected data.results[${index}].url to be non-empty`);\n\t\tresults.push({ title, url, snippet, content: typeof content === \"string\" ? content : \"\" });\n\t}\n\n\treturn { code: 0, data: { results, metadata: data.metadata as Record<string, unknown> } };\n}\n\nexport function isAnySearchAvailable(): boolean {\n\treturn true;\n}\n\nexport async function searchWithAnySearch(query: string, options: AnySearchSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = normalizeSearchResultCount(options.numResults);\n\tconst body = { query, max_results: numResults };\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\n\ttry {\n\t\tresponse = await fetch(ANYSEARCH_API_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`AnySearch API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`AnySearch API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tlet data: AnySearchResponse;\n\ttry {\n\t\tdata = parseResponse(rawData);\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow err;\n\t}\n\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.data.results.slice(0, numResults).map((result) => ({\n\t\ttitle: result.title,\n\t\turl: result.url,\n\t\tsnippet: result.snippet,\n\t}));\n\tconst mapped: SearchResponse = { answer: formatSearchResultsAsAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bocha.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/bocha.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bocha.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/bocha.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA+IrE,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAkDzG"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { activityMonitor } from "./activity.js";
|
|
3
|
+
import { normalizeDomain } from "./domain-filter-normalization.js";
|
|
4
|
+
import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
|
|
3
5
|
import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
|
|
4
6
|
import { getWebSearchConfigPath } from "./utils.js";
|
|
5
7
|
const BOCHA_SEARCH_URL = "https://api.bochaai.com/v1/web-search";
|
|
@@ -60,24 +62,6 @@ function mapFreshness(value) {
|
|
|
60
62
|
default: return "noLimit";
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
|
-
function normalizeDomain(value) {
|
|
64
|
-
let input = value.trim().toLowerCase();
|
|
65
|
-
if (!input)
|
|
66
|
-
return null;
|
|
67
|
-
if (input.startsWith("-"))
|
|
68
|
-
input = input.slice(1).trim();
|
|
69
|
-
if (!input)
|
|
70
|
-
return null;
|
|
71
|
-
try {
|
|
72
|
-
const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
|
|
73
|
-
input = parsed.hostname;
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
input = input.split("/")[0]?.split(":")[0] ?? "";
|
|
77
|
-
}
|
|
78
|
-
input = input.replace(/^\.+|\.+$/g, "");
|
|
79
|
-
return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
|
|
80
|
-
}
|
|
81
65
|
function parseDomainFilter(domainFilter) {
|
|
82
66
|
const filters = { include: [], exclude: [] };
|
|
83
67
|
for (const raw of domainFilter ?? []) {
|
|
@@ -148,11 +132,6 @@ function parseSearchResponse(value) {
|
|
|
148
132
|
}
|
|
149
133
|
return { results };
|
|
150
134
|
}
|
|
151
|
-
function buildAnswer(results) {
|
|
152
|
-
return results.map((result) => result.snippet
|
|
153
|
-
? `${result.snippet}\nSource: ${result.title} (${result.url})`
|
|
154
|
-
: `Source: ${result.title} (${result.url})`).join("\n\n");
|
|
155
|
-
}
|
|
156
135
|
export function isBochaAvailable() {
|
|
157
136
|
return hasCredentialSource({ provider: "Bocha", configuredValue: loadConfig().bochaApiKey, environmentValue: process.env.BOCHA_API_KEY });
|
|
158
137
|
}
|
|
@@ -214,6 +193,6 @@ export async function searchWithBocha(query, options = {}) {
|
|
|
214
193
|
}
|
|
215
194
|
activityMonitor.logComplete(activityId, response.status);
|
|
216
195
|
const results = parsed.results.filter((result) => passesDomainFilters(result.url, filters)).slice(0, numResults);
|
|
217
|
-
return { answer:
|
|
196
|
+
return { answer: formatSearchResultsAsAnswer(results), results };
|
|
218
197
|
}
|
|
219
198
|
//# sourceMappingURL=bocha.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bocha.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/bocha.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst BOCHA_SEARCH_URL = \"https://api.bochaai.com/v1/web-search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tbochaApiKey?: unknown;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Bocha\",\n\t\tconfiguredValue: loadConfig().bochaApiKey,\n\t\tenvironmentValue: process.env.BOCHA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Bocha API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"bochaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set BOCHA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://open.bochaai.com/\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 8;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction mapFreshness(value: SearchOptions[\"recencyFilter\"]): string {\n\tswitch (value) {\n\t\tcase \"day\": return \"oneDay\";\n\t\tcase \"week\": return \"oneWeek\";\n\t\tcase \"month\": return \"oneMonth\";\n\t\tcase \"year\": return \"oneYear\";\n\t\tdefault: return \"noLimit\";\n\t}\n}\n\ninterface DomainFilters {\n\tinclude: string[];\n\texclude: string[];\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction parseDomainFilter(domainFilter: string[] | undefined): DomainFilters {\n\tconst filters: DomainFilters = { include: [], exclude: [] };\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? filters.exclude : filters.include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn filters;\n}\n\nfunction passesDomainFilters(url: string, filters: DomainFilters): boolean {\n\tif (filters.include.length === 0 && filters.exclude.length === 0) return true;\n\tlet hostname: string;\n\ttry {\n\t\thostname = new URL(url).hostname.toLowerCase();\n\t} catch {\n\t\treturn false;\n\t}\n\tconst matches = (domain: string) => hostname === domain || hostname.endsWith(`.${domain}`);\n\tif (filters.exclude.some(matches)) return false;\n\treturn filters.include.length === 0 || filters.include.some(matches);\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Bocha API returned invalid response: ${message}`);\n}\n\nfunction firstString(...values: unknown[]): string | null {\n\tfor (const value of values) {\n\t\tif (typeof value === \"string\" && value.trim()) return value.trim();\n\t}\n\treturn null;\n}\n\nfunction parseSearchResponse(value: unknown): { results: SearchResponse[\"results\"] } {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (envelope.code !== undefined && Number(envelope.code) !== 200) {\n\t\tthrow invalidResponse(`code ${String(envelope.code)}: ${firstString(envelope.msg) ?? \"unknown error\"}`);\n\t}\n\tconst data = envelope.data;\n\tconst pages = (typeof data === \"object\" && data !== null && !Array.isArray(data))\n\t\t? (data as Record<string, unknown>).webPages\n\t\t: undefined;\n\tconst items = (typeof pages === \"object\" && pages !== null && !Array.isArray(pages))\n\t\t? (pages as Record<string, unknown>).value\n\t\t: undefined;\n\tif (!Array.isArray(items)) throw invalidResponse(\"missing data.webPages.value array\");\n\tconst results: SearchResponse[\"results\"] = [];\n\tfor (const item of items) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst entry = item as Record<string, unknown>;\n\t\tconst url = firstString(entry.url, entry.link, entry.href);\n\t\tif (!url) continue;\n\t\tconst title = firstString(entry.title, entry.name) ?? url;\n\t\tconst snippet = firstString(entry.summary, entry.snippet, entry.description, entry.content) ?? \"\";\n\t\tresults.push({ title, url, snippet });\n\t}\n\treturn { results };\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => result.snippet\n\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t: `Source: ${result.title} (${result.url})`).join(\"\\n\\n\");\n}\n\nexport function isBochaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Bocha\", configuredValue: loadConfig().bochaApiKey, environmentValue: process.env.BOCHA_API_KEY });\n}\n\nexport async function searchWithBocha(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst filters = parseDomainFilter(options.domainFilter);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(BOCHA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, count: numResults, freshness: mapFreshness(options.recencyFilter), summary: true }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Bocha API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Bocha API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tlet parsed: { results: SearchResponse[\"results\"] };\n\ttry {\n\t\tparsed = parseSearchResponse(rawData);\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = parsed.results.filter((result) => passesDomainFilters(result.url, filters)).slice(0, numResults);\n\treturn { answer: buildAnswer(results), results };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bocha.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/bocha.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { normalizeDomain } from \"./domain-filter-normalization.ts\";\nimport { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst BOCHA_SEARCH_URL = \"https://api.bochaai.com/v1/web-search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tbochaApiKey?: unknown;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Bocha\",\n\t\tconfiguredValue: loadConfig().bochaApiKey,\n\t\tenvironmentValue: process.env.BOCHA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Bocha API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"bochaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set BOCHA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://open.bochaai.com/\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 8;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction mapFreshness(value: SearchOptions[\"recencyFilter\"]): string {\n\tswitch (value) {\n\t\tcase \"day\": return \"oneDay\";\n\t\tcase \"week\": return \"oneWeek\";\n\t\tcase \"month\": return \"oneMonth\";\n\t\tcase \"year\": return \"oneYear\";\n\t\tdefault: return \"noLimit\";\n\t}\n}\n\ninterface DomainFilters {\n\tinclude: string[];\n\texclude: string[];\n}\n\nfunction parseDomainFilter(domainFilter: string[] | undefined): DomainFilters {\n\tconst filters: DomainFilters = { include: [], exclude: [] };\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? filters.exclude : filters.include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn filters;\n}\n\nfunction passesDomainFilters(url: string, filters: DomainFilters): boolean {\n\tif (filters.include.length === 0 && filters.exclude.length === 0) return true;\n\tlet hostname: string;\n\ttry {\n\t\thostname = new URL(url).hostname.toLowerCase();\n\t} catch {\n\t\treturn false;\n\t}\n\tconst matches = (domain: string) => hostname === domain || hostname.endsWith(`.${domain}`);\n\tif (filters.exclude.some(matches)) return false;\n\treturn filters.include.length === 0 || filters.include.some(matches);\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Bocha API returned invalid response: ${message}`);\n}\n\nfunction firstString(...values: unknown[]): string | null {\n\tfor (const value of values) {\n\t\tif (typeof value === \"string\" && value.trim()) return value.trim();\n\t}\n\treturn null;\n}\n\nfunction parseSearchResponse(value: unknown): { results: SearchResponse[\"results\"] } {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (envelope.code !== undefined && Number(envelope.code) !== 200) {\n\t\tthrow invalidResponse(`code ${String(envelope.code)}: ${firstString(envelope.msg) ?? \"unknown error\"}`);\n\t}\n\tconst data = envelope.data;\n\tconst pages = (typeof data === \"object\" && data !== null && !Array.isArray(data))\n\t\t? (data as Record<string, unknown>).webPages\n\t\t: undefined;\n\tconst items = (typeof pages === \"object\" && pages !== null && !Array.isArray(pages))\n\t\t? (pages as Record<string, unknown>).value\n\t\t: undefined;\n\tif (!Array.isArray(items)) throw invalidResponse(\"missing data.webPages.value array\");\n\tconst results: SearchResponse[\"results\"] = [];\n\tfor (const item of items) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst entry = item as Record<string, unknown>;\n\t\tconst url = firstString(entry.url, entry.link, entry.href);\n\t\tif (!url) continue;\n\t\tconst title = firstString(entry.title, entry.name) ?? url;\n\t\tconst snippet = firstString(entry.summary, entry.snippet, entry.description, entry.content) ?? \"\";\n\t\tresults.push({ title, url, snippet });\n\t}\n\treturn { results };\n}\n\nexport function isBochaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Bocha\", configuredValue: loadConfig().bochaApiKey, environmentValue: process.env.BOCHA_API_KEY });\n}\n\nexport async function searchWithBocha(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst filters = parseDomainFilter(options.domainFilter);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(BOCHA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, count: numResults, freshness: mapFreshness(options.recencyFilter), summary: true }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Bocha API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Bocha API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tlet parsed: { results: SearchResponse[\"results\"] };\n\ttry {\n\t\tparsed = parseSearchResponse(rawData);\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = parsed.results.filter((result) => passesDomainFilters(result.url, filters)).slice(0, numResults);\n\treturn { answer: formatSearchResultsAsAnswer(results), results };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brave.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/brave.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"brave.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/brave.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA4GnF,wBAAgB,gBAAgB,IAAI,OAAO,CAM1C;AAED,wBAAsB,eAAe,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GACzB,OAAO,CAAC,cAAc,CAAC,CAwFzB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { activityMonitor } from "./activity.js";
|
|
3
|
+
import { normalizeDomain } from "./domain-filter-normalization.js";
|
|
4
|
+
import { normalizeSearchResultCount } from "./search-result-count-normalization.js";
|
|
3
5
|
import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
|
|
4
6
|
import { fetchWithCredentialRedirects, getWebSearchConfigPath, resolveApiBaseUrl } from "./utils.js";
|
|
5
7
|
const BRAVE_API_BASE_URL = "https://api.search.brave.com/res/v1";
|
|
@@ -40,29 +42,6 @@ function getApiUrl() {
|
|
|
40
42
|
environmentValue: process.env.BRAVE_BASE_URL,
|
|
41
43
|
})}/web/search`;
|
|
42
44
|
}
|
|
43
|
-
function normalizeCount(value) {
|
|
44
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
45
|
-
return 5;
|
|
46
|
-
return Math.max(1, Math.min(Math.floor(value), 20));
|
|
47
|
-
}
|
|
48
|
-
function normalizeDomain(value) {
|
|
49
|
-
let input = value.trim().toLowerCase();
|
|
50
|
-
if (!input)
|
|
51
|
-
return null;
|
|
52
|
-
if (input.startsWith("-"))
|
|
53
|
-
input = input.slice(1).trim();
|
|
54
|
-
if (!input)
|
|
55
|
-
return null;
|
|
56
|
-
try {
|
|
57
|
-
const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
|
|
58
|
-
input = parsed.hostname;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
input = input.split("/")[0]?.split(":")[0] ?? "";
|
|
62
|
-
}
|
|
63
|
-
input = input.replace(/^\.+|\.+$/g, "");
|
|
64
|
-
return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
|
|
65
|
-
}
|
|
66
45
|
function normalizeDomainFilters(domainFilter) {
|
|
67
46
|
const filters = { allowed: [], blocked: [] };
|
|
68
47
|
if (!domainFilter?.length)
|
|
@@ -125,7 +104,7 @@ export async function searchWithBrave(query, options = {}) {
|
|
|
125
104
|
" 2. Set BRAVE_API_KEY environment variable\n" +
|
|
126
105
|
"Get a key at https://brave.com/search/api/");
|
|
127
106
|
}
|
|
128
|
-
const numResults =
|
|
107
|
+
const numResults = normalizeSearchResultCount(options.numResults);
|
|
129
108
|
const domainFilters = normalizeDomainFilters(options.domainFilter);
|
|
130
109
|
const searchQuery = buildBraveQuery(query, options.domainFilter);
|
|
131
110
|
const activityId = activityMonitor.logStart({ type: "api", query: searchQuery });
|