@xiaoso/dsh-tool-plus 0.1.0-beta.5 → 0.1.0-beta.6

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.
Files changed (71) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +2 -2
  3. package/THIRD_PARTY_NOTICES.md +42 -42
  4. package/lib/{abort-dIkZBV7Q.mjs → abort-CsjZitYv.mjs} +1 -1
  5. package/lib/{amazon-bedrock-WQhvjHYu.mjs → amazon-bedrock-CfNIDi5k.mjs} +7 -7
  6. package/lib/{anthropic-CJCauvYz.mjs → anthropic-BVfZdnMp.mjs} +12 -12
  7. package/lib/{anthropic-tTntD8BD.mjs → anthropic-DGXmmg43.mjs} +2 -2
  8. package/lib/{api-key-login-BzqNdM2y.mjs → api-key-login-BikQAfD-.mjs} +1 -1
  9. package/lib/{aws-credentials-CXryMobh.mjs → aws-credentials-DrssNMn_.mjs} +4 -4
  10. package/lib/{azure-openai-responses-DuukbD0F.mjs → azure-openai-responses-C-5q-5K2.mjs} +8 -8
  11. package/lib/browser-render-z6b8Ljo9.mjs +183 -0
  12. package/lib/{bundled-references-Cavaffah.mjs → bundled-references-D71z7_T3.mjs} +2 -2
  13. package/lib/{callback-server-CQ5Jo8F-.mjs → callback-server-Di6C4RqI.mjs} +1 -1
  14. package/lib/client.js +327 -4
  15. package/lib/{cursor-B6TUEmgP.mjs → cursor-CQQtygwl.mjs} +1 -1
  16. package/lib/{cursor-DkSX2h3H.mjs → cursor-DXJxwdcg.mjs} +7 -7
  17. package/lib/{cursor-aJrXeYCb.mjs → cursor-Hr5Zw1gt.mjs} +3 -3
  18. package/lib/{device-code-DBo3B5nh.mjs → device-code-wZUbgPdB.mjs} +1 -1
  19. package/lib/{devin-BHZZyMhO.mjs → devin-CF6UhCFw.mjs} +2 -2
  20. package/lib/{devin-BK7DHeca.mjs → devin-DXJoDlW2.mjs} +1 -1
  21. package/lib/{devin-vNZTNUON.mjs → devin-P37gURs_.mjs} +5 -5
  22. package/lib/{dom-DGdYAVTv.mjs → dom-CawWi8fa.mjs} +14 -1
  23. package/lib/{error-Dd8DIqs-.mjs → error-DoHuatWw.mjs} +1 -1
  24. package/lib/{event-stream-BbFZJy-z.mjs → event-stream-C-FmBYUt.mjs} +1 -1
  25. package/lib/{github-copilot-CYkjeTi3.mjs → github-copilot-C2dTonBX.mjs} +3 -3
  26. package/lib/{github-copilot-B1yiyVRh.mjs → github-copilot-qETlj_bD.mjs} +1 -1
  27. package/lib/{gitlab-duo-CM7Ref1H.mjs → gitlab-duo-FQZiFRQe.mjs} +3 -3
  28. package/lib/{gitlab-duo-workflow-BGAF6JDw.mjs → gitlab-duo-workflow-DLTabzOy.mjs} +2 -2
  29. package/lib/{google-BS4T25Pn.mjs → google-BilwFSzx.mjs} +3 -3
  30. package/lib/{google-antigravity-DGmwC2KV.mjs → google-antigravity-BfBiINdu.mjs} +2 -2
  31. package/lib/{google-auth-B6gjsZvg.mjs → google-auth-CWlKXJ-H.mjs} +3 -3
  32. package/lib/{google-gemini-cli-Dsztq0N5.mjs → google-gemini-cli-CB89ljNz.mjs} +3 -3
  33. package/lib/{google-gemini-cli-Cqds_Q5T.mjs → google-gemini-cli-CygFcR6N.mjs} +8 -8
  34. package/lib/{google-oauth-shared-CuEHaDDj.mjs → google-oauth-shared-Cn82h1o2.mjs} +2 -2
  35. package/lib/{google-shared-Dr-VG-ap.mjs → google-shared-CF1JrqTM.mjs} +6 -6
  36. package/lib/{google-vertex-BDN2tLaD.mjs → google-vertex-DgMhhFw8.mjs} +5 -5
  37. package/lib/{identity-Da1GPU9a.mjs → identity-C0SPVyIZ.mjs} +1 -1
  38. package/lib/{idle-iterator-DUjKQEGT.mjs → idle-iterator-HzbbfXP4.mjs} +2 -2
  39. package/lib/index.mjs +310 -29
  40. package/lib/{kimi-Dh0pv3WZ.mjs → kimi-DHDO6Fde.mjs} +3 -3
  41. package/lib/launch-DwpE70Pv.mjs +148 -0
  42. package/lib/{markit-BL3cH47U.mjs → markit-B9exZ0ZV.mjs} +1 -1
  43. package/lib/{minimax-code-Uq8Qu9LW.mjs → minimax-code-vAhEXhev.mjs} +1 -1
  44. package/lib/{models-SGASygJ3.mjs → models-Cp3PzU3l.mjs} +1 -1
  45. package/lib/{ollama-DPzBmq89.mjs → ollama-TrkXTNqE.mjs} +8 -8
  46. package/lib/{openai-codex-Ch8CkT3p.mjs → openai-codex-CrjHtSH4.mjs} +3 -3
  47. package/lib/{openai-codex-responses-pejZgdZo.mjs → openai-codex-responses-C4uMpWNy.mjs} +10 -10
  48. package/lib/{openai-completions-DIf361kF.mjs → openai-completions-1ydXm5vF.mjs} +13 -13
  49. package/lib/{openai-reasoning-fallback-Nj6yB2rY.mjs → openai-reasoning-fallback-CigKCyzc.mjs} +2 -2
  50. package/lib/{openai-responses-Db_a-U4-.mjs → openai-responses-CN79gRGQ.mjs} +10 -10
  51. package/lib/{opencode-Rq_Q2vAO.mjs → opencode-CEGlimzL.mjs} +1 -1
  52. package/lib/{perplexity-C4iLVMUj.mjs → perplexity-BLJN-8dM.mjs} +2 -2
  53. package/lib/{proxy-pM_NIv-H.mjs → proxy-XOYi58TM.mjs} +1 -1
  54. package/lib/readability-Cpm-ocau.mjs +455 -0
  55. package/lib/{scrapers-1FTlHNQV.mjs → scrapers-BlWQMGjU.mjs} +11 -10
  56. package/lib/{src-BgpusnsB.mjs → src-D_e1qMwi.mjs} +5 -1
  57. package/lib/{stream-CRtexYLe.mjs → stream-DveNFWSN.mjs} +56 -56
  58. package/lib/{stream-markup-healing-KMkiAA00.mjs → stream-markup-healing-C9eC7Gf8.mjs} +3 -3
  59. package/lib/tool-errors-DoyxivAR.mjs +47 -0
  60. package/lib/types-BUO0JXO-.mjs +251 -0
  61. package/lib/{utils-D2YknRk4.mjs → utils-B-mTYQBc.mjs} +1 -1
  62. package/lib/{utils-C616y7eF.mjs → utils-D1QPFbRk.mjs} +28 -268
  63. package/lib/{utils-Cp76gCyk.mjs → utils-fnV2zzp3.mjs} +3 -3
  64. package/lib/{vision-guard-01qSwFpf.mjs → vision-guard-BsvOWmfB.mjs} +2 -2
  65. package/lib/{wafer-CgtPHerf.mjs → wafer-Dpy7tL3l.mjs} +1 -1
  66. package/lib/{xai-oauth-Buk8XVvM.mjs → xai-oauth-BkPNQS-q.mjs} +2 -2
  67. package/lib/{xiaomi-D2qT5cAC.mjs → xiaomi-CG3TsYRz.mjs} +1 -1
  68. package/lib/{zai-C59YnomG.mjs → zai--cewobzN.mjs} +2 -2
  69. package/lib/{zip-Cg9ANN_U.mjs → zip-CqKW2-TK.mjs} +3 -46
  70. package/package.json +147 -145
  71. package/presets/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { F as $envpos, S as debug, y as isEnoent } from "./src-BgpusnsB.mjs";
4
- import { c as OAuthError, g as MissingApiKeyError, t as ConfigurationError } from "./error-Dd8DIqs-.mjs";
5
- import { n as raceWithSignal } from "./abort-dIkZBV7Q.mjs";
3
+ import { F as $envpos, S as debug, y as isEnoent } from "./src-D_e1qMwi.mjs";
4
+ import { c as OAuthError, g as MissingApiKeyError, t as ConfigurationError } from "./error-DoHuatWw.mjs";
5
+ import { n as raceWithSignal } from "./abort-CsjZitYv.mjs";
6
6
  import * as path from "node:path";
7
7
  import * as os from "node:os";
8
8
  import { Buffer } from "node:buffer";
@@ -1,9 +1,9 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { P as $env } from "./src-BgpusnsB.mjs";
4
- import { c as OAuthError } from "./error-Dd8DIqs-.mjs";
3
+ import { P as $env } from "./src-D_e1qMwi.mjs";
4
+ import { c as OAuthError } from "./error-DoHuatWw.mjs";
5
5
  import { i as getGeminiCliHeaders } from "./gemini-headers-DKUShltF.mjs";
6
- import { n as runGoogleOAuthLogin, r as throwIfLoginCancelled, t as oauthFetch } from "./google-oauth-shared-CuEHaDDj.mjs";
6
+ import { n as runGoogleOAuthLogin, r as throwIfLoginCancelled, t as oauthFetch } from "./google-oauth-shared-Cn82h1o2.mjs";
7
7
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/google-gemini-cli.ts
8
8
  /**
9
9
  * Gemini CLI OAuth flow (Google Cloud Code Assist)
@@ -1,15 +1,15 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { o as readSseJson } from "./src-BgpusnsB.mjs";
4
- import { G as fetchWithRetry, L as GeminiCliApiError, S as classify, W as extractHttpStatusFromError, a as isTransientStatus, c as OAuthError, j as retriable, l as finalize, n as StreamTimeoutError, r as ValidationError, s as ProviderResponseError, t as ConfigurationError, v as AbortError } from "./error-Dd8DIqs-.mjs";
5
- import { M as normalizeSchemaForCCA, a as normalizeSystemPrompts } from "./utils-Cp76gCyk.mjs";
6
- import { t as calculateCost } from "./models-SGASygJ3.mjs";
7
- import { t as AssistantMessageEventStream } from "./event-stream-BbFZJy-z.mjs";
3
+ import { o as readSseJson } from "./src-D_e1qMwi.mjs";
4
+ import { G as fetchWithRetry, L as GeminiCliApiError, S as classify, W as extractHttpStatusFromError, a as isTransientStatus, c as OAuthError, j as retriable, l as finalize, n as StreamTimeoutError, r as ValidationError, s as ProviderResponseError, t as ConfigurationError, v as AbortError } from "./error-DoHuatWw.mjs";
5
+ import { M as normalizeSchemaForCCA, a as normalizeSystemPrompts } from "./utils-fnV2zzp3.mjs";
6
+ import { t as calculateCost } from "./models-Cp3PzU3l.mjs";
7
+ import { t as AssistantMessageEventStream } from "./event-stream-C-FmBYUt.mjs";
8
8
  import { i as getGeminiCliHeaders, n as getAntigravityUserAgent, t as getAntigravityModelWireProfile } from "./gemini-headers-DKUShltF.mjs";
9
- import { i as getStreamFirstEventTimeoutMs, o as iterateWithIdleTimeout, t as armPreResponseTimeout } from "./idle-iterator-DUjKQEGT.mjs";
10
- import { t as StreamMarkupHealing } from "./stream-markup-healing-KMkiAA00.mjs";
9
+ import { i as getStreamFirstEventTimeoutMs, o as iterateWithIdleTimeout, t as armPreResponseTimeout } from "./idle-iterator-HzbbfXP4.mjs";
10
+ import { t as StreamMarkupHealing } from "./stream-markup-healing-C9eC7Gf8.mjs";
11
11
  import { n as formatGoogleValidationRequiredMessage, t as extractGoogleValidationUrl } from "./google-validation-Cgbn3tWJ.mjs";
12
- import { a as isThinkingPart, c as nextToolCallId, d as retainThoughtSignature, f as startTextOrThinkingBlock, i as hasMeaningfulGoogleContent, l as pushBlockEndEvent, n as convertMessages, o as mapStopReasonString, r as convertTools, s as mapToolChoice, u as pushToolCallEvents } from "./google-shared-Dr-VG-ap.mjs";
12
+ import { a as isThinkingPart, c as nextToolCallId, d as retainThoughtSignature, f as startTextOrThinkingBlock, i as hasMeaningfulGoogleContent, l as pushBlockEndEvent, n as convertMessages, o as mapStopReasonString, r as convertTools, s as mapToolChoice, u as pushToolCallEvents } from "./google-shared-CF1JrqTM.mjs";
13
13
  import { scheduler } from "node:timers/promises";
14
14
  import { createHash, randomBytes, randomUUID } from "node:crypto";
15
15
  import { type } from "@oh-my-pi/omptype";
@@ -1,7 +1,7 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { c as OAuthError, h as LoginCancelledError } from "./error-Dd8DIqs-.mjs";
4
- import { t as OAuthCallbackFlow } from "./callback-server-CQ5Jo8F-.mjs";
3
+ import { c as OAuthError, h as LoginCancelledError } from "./error-DoHuatWw.mjs";
4
+ import { t as OAuthCallbackFlow } from "./callback-server-Di6C4RqI.mjs";
5
5
  import { n as formatGoogleValidationRequiredMessage, t as extractGoogleValidationUrl } from "./google-validation-Cgbn3tWJ.mjs";
6
6
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/google-oauth-shared.ts
7
7
  /**
@@ -1,11 +1,11 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { o as readSseJson } from "./src-BgpusnsB.mjs";
4
- import { R as GoogleApiError, l as finalize, r as ValidationError, s as ProviderResponseError, t as ConfigurationError, v as AbortError } from "./error-Dd8DIqs-.mjs";
5
- import { M as normalizeSchemaForCCA, N as normalizeSchemaForGoogle, a as normalizeSystemPrompts, k as toolWireSchema, m as transformMessages, w as renderDemotedThinking } from "./utils-Cp76gCyk.mjs";
6
- import { t as calculateCost } from "./models-SGASygJ3.mjs";
7
- import { o as shouldSendServiceTier, t as NON_VISION_IMAGE_PLACEHOLDER } from "./vision-guard-01qSwFpf.mjs";
8
- import { t as AssistantMessageEventStream } from "./event-stream-BbFZJy-z.mjs";
3
+ import { o as readSseJson } from "./src-D_e1qMwi.mjs";
4
+ import { R as GoogleApiError, l as finalize, r as ValidationError, s as ProviderResponseError, t as ConfigurationError, v as AbortError } from "./error-DoHuatWw.mjs";
5
+ import { M as normalizeSchemaForCCA, N as normalizeSchemaForGoogle, a as normalizeSystemPrompts, k as toolWireSchema, m as transformMessages, w as renderDemotedThinking } from "./utils-fnV2zzp3.mjs";
6
+ import { t as calculateCost } from "./models-Cp3PzU3l.mjs";
7
+ import { o as shouldSendServiceTier, t as NON_VISION_IMAGE_PLACEHOLDER } from "./vision-guard-BsvOWmfB.mjs";
8
+ import { t as AssistantMessageEventStream } from "./event-stream-C-FmBYUt.mjs";
9
9
  import { scheduler } from "node:timers/promises";
10
10
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/providers/google-shared.ts
11
11
  /**
@@ -1,10 +1,10 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { P as $env } from "./src-BgpusnsB.mjs";
4
- import { t as ConfigurationError } from "./error-Dd8DIqs-.mjs";
5
- import { P as resolveVertexEndpointHost } from "./models-SGASygJ3.mjs";
6
- import { t as getVertexAccessToken } from "./google-auth-B6gjsZvg.mjs";
7
- import { p as streamGoogleGenAI, t as buildGoogleGenerateContentParams } from "./google-shared-Dr-VG-ap.mjs";
3
+ import { P as $env } from "./src-D_e1qMwi.mjs";
4
+ import { t as ConfigurationError } from "./error-DoHuatWw.mjs";
5
+ import { P as resolveVertexEndpointHost } from "./models-Cp3PzU3l.mjs";
6
+ import { t as getVertexAccessToken } from "./google-auth-CWlKXJ-H.mjs";
7
+ import { p as streamGoogleGenAI, t as buildGoogleGenerateContentParams } from "./google-shared-CF1JrqTM.mjs";
8
8
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/providers/google-vertex.ts
9
9
  const API_VERSION = "v1";
10
10
  const streamGoogleVertex = (model, context, options) => {
@@ -1,6 +1,6 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { i as getBundledProviders, r as getBundledModels, w as modelFamilyToken } from "./models-SGASygJ3.mjs";
3
+ import { i as getBundledProviders, r as getBundledModels, w as modelFamilyToken } from "./models-Cp3PzU3l.mjs";
4
4
  //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/identity/id.ts
5
5
  const LEADING_BRACKETED_AFFIX_PATTERN = /^(?:\s*(?:\[|【)[^\]】]+(?:\]|】)\s*)+/u;
6
6
  const TRAILING_BRACKETED_AFFIX_PATTERN = /(?:\s*(?:\[|【)[^\]】]+(?:\]|】)\s*)+$/u;
@@ -1,7 +1,7 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
- import { P as $env } from "./src-BgpusnsB.mjs";
4
- import { n as StreamTimeoutError, v as AbortError } from "./error-Dd8DIqs-.mjs";
3
+ import { P as $env } from "./src-D_e1qMwi.mjs";
4
+ import { n as StreamTimeoutError, v as AbortError } from "./error-DoHuatWw.mjs";
5
5
  //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/utils/idle-iterator.ts
6
6
  const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
7
7
  const DEFAULT_STREAM_FIRST_EVENT_TIMEOUT_MS = 3e5;
package/lib/index.mjs CHANGED
@@ -1,11 +1,14 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
3
  import { n as fs_promises_shim_exports, t as exists } from "./fs-promises-shim-Bx0fpxuk.mjs";
4
- import { A as formatAge, C as error, F as $envpos, I as $flag, M as formatCount, P as $env, Q as peekFile, S as debug, T as warn, U as getAutoQaDbPath, V as VERSION, Y as getRemoteDir, Z as isProbablyBinary, b as isEnotdir, c as combineSignals, d as $which, et as untilAborted, j as formatBytes$1, k as installBunShim, l as exec, p as readImageMetadata, q as getInstallId, u as render, v as hasFsCode, y as isEnoent } from "./src-BgpusnsB.mjs";
5
- import { A as shortenPath, C as Settings, D as capParseErrors, E as OMP_DEFAULTS, M as padding, N as replaceTabs, O as formatCodeFrameLine, P as truncateToWidth$1, S as convertFileWithMarkit, T as settings, _ as extractWithParallel, a as fetchBinary, b as ensureTool, g as looksLikeHtml, h as loadPage, i as convertWithMarkit, j as LRUCache, k as formatParseErrors, o as MAX_BYTES, s as MAX_OUTPUT_CHARS, u as finalizeOutput, v as findParallelApiKey, w as isSettingsInitialized, x as CONVERTIBLE_EXTENSIONS, y as getParallelExtractContent } from "./utils-C616y7eF.mjs";
4
+ import { i as setRuntimeLogger, n as systemChromiumCandidatesForTest, r as runtimeLogger } from "./launch-DwpE70Pv.mjs";
5
+ import { $ as peekFile, A as formatAge, C as error, F as $envpos, I as $flag, M as formatCount, P as $env, Q as isProbablyBinary, S as debug, T as warn, U as getAutoQaDbPath, V as VERSION, X as getRemoteDir, Y as getPuppeteerDir, b as isEnotdir, c as combineSignals, d as $which, j as formatBytes$1, k as installBunShim, l as exec, p as readImageMetadata, q as getInstallId, tt as untilAborted, u as render, v as hasFsCode, y as isEnoent } from "./src-D_e1qMwi.mjs";
6
+ import { C as truncateToWidth$1, S as replaceTabs, _ as formatCodeFrameLine, a as fetchBinary, b as LRUCache, c as getParallelExtractContent, d as convertFileWithMarkit, f as Settings, g as capParseErrors, h as OMP_DEFAULTS, i as convertWithMarkit, l as ensureTool, m as settings, o as extractWithParallel, p as isSettingsInitialized, s as findParallelApiKey, u as CONVERTIBLE_EXTENSIONS, v as formatParseErrors, x as padding, y as shortenPath } from "./utils-D1QPFbRk.mjs";
6
7
  import { t as sanitizeText } from "./sanitize-text-CfcXzw5X.mjs";
7
8
  import { n as isRecord$2 } from "./type-guards-B9VVjRDK.mjs";
8
- import { a as openArchive, c as sniffArchiveFormat, d as writeArchive, f as ToolAbortError, i as listArchiveRoot, m as throwIfAborted, o as parseArchivePathCandidates, p as ToolError, r as formatArchiveEntryLines, s as readArchiveEntries, t as archiveFormatFromPath } from "./zip-Cg9ANN_U.mjs";
9
+ import { n as ToolError, r as throwIfAborted, t as ToolAbortError } from "./tool-errors-DoyxivAR.mjs";
10
+ import { a as openArchive, c as sniffArchiveFormat, d as writeArchive, i as listArchiveRoot, o as parseArchivePathCandidates, r as formatArchiveEntryLines, s as readArchiveEntries, t as archiveFormatFromPath } from "./zip-CqKW2-TK.mjs";
11
+ import { a as finalizeOutput, d as looksLikeHtml, n as MAX_OUTPUT_CHARS, t as MAX_BYTES, u as loadPage } from "./types-BUO0JXO-.mjs";
9
12
  import * as path from "node:path";
10
13
  import { TOOL_ABORTED, defineTool } from "@deepseek-ai/dsh-tools";
11
14
  import { HarnessError } from "@deepseek-ai/dsh-llm";
@@ -385,22 +388,6 @@ function checkBashInterception(command, availableTools, rules = DEFAULT_BASH_INT
385
388
  return { block: false };
386
389
  }
387
390
  //#endregion
388
- //#region src/tools/bash/logger.ts
389
- let current = {
390
- info: (message, ...args) => console.info(`[bash-plus] ${message}`, ...args),
391
- warn: (message, ...args) => console.warn(`[bash-plus] ${message}`, ...args),
392
- error: (message, ...args) => console.error(`[bash-plus] ${message}`, ...args),
393
- debug: (message, ...args) => console.debug(`[bash-plus] ${message}`, ...args)
394
- };
395
- /** Install the composition logger (Cordis `ctx.logger`); replaces the console adapter. */
396
- function setRuntimeLogger(logger) {
397
- current = logger;
398
- }
399
- /** The installed logger; defaults to the console adapter. */
400
- function runtimeLogger() {
401
- return current;
402
- }
403
- //#endregion
404
391
  //#region src/tools/bash/which.ts
405
392
  /**
406
393
  * Minimal PATH (+ PATHEXT on Windows) executable lookup, standing in for
@@ -3610,6 +3597,64 @@ const TOOL_PLUS_FIELDS = [
3610
3597
  tool: "read",
3611
3598
  visibility: { requiresEnabled: "fetchEnabled" }
3612
3599
  },
3600
+ {
3601
+ name: "fetchReader",
3602
+ kind: "select",
3603
+ default: "auto",
3604
+ labelKey: "fetchReader",
3605
+ hintKey: "fetchReaderHint",
3606
+ group: "fetch",
3607
+ tool: "read",
3608
+ options: [
3609
+ {
3610
+ value: "auto",
3611
+ labelKey: "optReaderAuto"
3612
+ },
3613
+ {
3614
+ value: "native",
3615
+ labelKey: "optReaderNative"
3616
+ },
3617
+ {
3618
+ value: "trafilatura",
3619
+ labelKey: "optReaderTrafilatura"
3620
+ },
3621
+ {
3622
+ value: "lynx",
3623
+ labelKey: "optReaderLynx"
3624
+ },
3625
+ {
3626
+ value: "parallel",
3627
+ labelKey: "optReaderParallel"
3628
+ },
3629
+ {
3630
+ value: "jina",
3631
+ labelKey: "optReaderJina"
3632
+ },
3633
+ {
3634
+ value: "browser",
3635
+ labelKey: "optReaderBrowser"
3636
+ }
3637
+ ]
3638
+ },
3639
+ {
3640
+ name: "browserReaderEnabled",
3641
+ kind: "boolean",
3642
+ default: true,
3643
+ labelKey: "browserReaderEnabled",
3644
+ hintKey: "browserReaderEnabledHint",
3645
+ group: "fetch",
3646
+ tool: "read"
3647
+ },
3648
+ {
3649
+ name: "browserProbe",
3650
+ kind: "action",
3651
+ default: "",
3652
+ labelKey: "browserProbe",
3653
+ hintKey: "browserProbeHint",
3654
+ group: "fetch",
3655
+ tool: "read",
3656
+ actionKey: "browser/detect"
3657
+ },
3613
3658
  {
3614
3659
  name: "imagesBlockImages",
3615
3660
  kind: "boolean",
@@ -3896,6 +3941,16 @@ const Config = z.object({
3896
3941
  astEditEnabled: z.boolean().default(fieldDefault("astEditEnabled", true)),
3897
3942
  fetchEnabled: z.boolean().default(fieldDefault("fetchEnabled", true)),
3898
3943
  fetchMaxTimeoutSeconds: z.number().default(fieldDefault("fetchMaxTimeoutSeconds", 0)),
3944
+ fetchReader: z.union([
3945
+ "auto",
3946
+ "native",
3947
+ "trafilatura",
3948
+ "lynx",
3949
+ "parallel",
3950
+ "jina",
3951
+ "browser"
3952
+ ]).default(fieldDefault("fetchReader", "auto")),
3953
+ browserReaderEnabled: z.boolean().default(fieldDefault("browserReaderEnabled", true)),
3899
3954
  imagesAutoResize: z.boolean().default(fieldDefault("imagesAutoResize", true)),
3900
3955
  imagesBlockImages: z.boolean().default(fieldDefault("imagesBlockImages", false)),
3901
3956
  imagesExcludeWebp: z.boolean().default(fieldDefault("imagesExcludeWebp", false)),
@@ -3971,6 +4026,8 @@ function resolveConfig(config) {
3971
4026
  astEditEnabled: config.astEditEnabled ?? fieldDefault("astEditEnabled", true),
3972
4027
  fetchEnabled: config.fetchEnabled ?? fieldDefault("fetchEnabled", true),
3973
4028
  fetchMaxTimeoutSeconds: config.fetchMaxTimeoutSeconds ?? fieldDefault("fetchMaxTimeoutSeconds", 0),
4029
+ fetchReader: config.fetchReader ?? fieldDefault("fetchReader", "auto"),
4030
+ browserReaderEnabled: config.browserReaderEnabled ?? fieldDefault("browserReaderEnabled", true),
3974
4031
  imagesAutoResize: config.imagesAutoResize ?? fieldDefault("imagesAutoResize", true),
3975
4032
  imagesBlockImages: config.imagesBlockImages ?? fieldDefault("imagesBlockImages", false),
3976
4033
  imagesExcludeWebp: config.imagesExcludeWebp ?? fieldDefault("imagesExcludeWebp", false),
@@ -4006,6 +4063,183 @@ function installBashPlusSettings(ctx, entry, onSource) {
4006
4063
  });
4007
4064
  }
4008
4065
  //#endregion
4066
+ //#region src/tools/shared/browser-rpc-channel.ts
4067
+ /**
4068
+ * Shared RPC channel constants for the browser-detection round trip between
4069
+ * the settings panel (client half) and the host. Both halves import this
4070
+ * module so the channel/endpoint never drift.
4071
+ *
4072
+ * The channel rides the official `@deepseek-ai/dsh-client-connection` generic
4073
+ * RPC transport (host registers with `ctx.connection.rpc.handle`; the client
4074
+ * calls via `createWebConnectionRpc().call`). Channel names must match
4075
+ * `/^\/[A-Za-z0-9._~-]+$/` and `/api` is reserved — `/tool-plus` is ours.
4076
+ * @module @xiaoso/dsh-tool-plus/browser-rpc-channel
4077
+ */
4078
+ /** Logical RPC channel registered by the host half of this plugin. */
4079
+ const TOOL_PLUS_RPC_CHANNEL = "/tool-plus";
4080
+ //#endregion
4081
+ //#region src/tools/shared/browser-detect.ts
4082
+ /**
4083
+ * Browser executable detection for the read browser renderer — a thin,
4084
+ * fully-injectable shell over the OMP probe family (`src/tools/omp/browser/launch.ts`).
4085
+ *
4086
+ * Two entry points share one candidate pipeline:
4087
+ * - {@link probeBrowsers} — no caching; every call walks the candidate table.
4088
+ * Backs the settings-panel "探测浏览器" button via the host RPC, so a user
4089
+ * can re-probe after installing a browser.
4090
+ * - {@link detectBrowser} — memoizes the first success as the renderer's
4091
+ * executable choice, so repeated reads do not re-stat the filesystem.
4092
+ *
4093
+ * Candidate kinds are annotated for display (`edge` / `chrome` / `chromium` /
4094
+ * `cfr` / `env`); the renderer itself only needs the resolved path, so the
4095
+ * detection result and the launch path never drift.
4096
+ *
4097
+ * Host-side only: this module imports node:fs, so it must never be reached
4098
+ * from the browser client half (it isn't — the client imports the channel
4099
+ * constants module, not this one).
4100
+ * @module @xiaoso/dsh-tool-plus/browser-detect
4101
+ */
4102
+ /** Default environment: the real platform/homedir/which/filesystem. */
4103
+ function defaultBrowserDetectEnv() {
4104
+ return {
4105
+ platform: process.platform,
4106
+ home: process.env.HOME ?? process.env.USERPROFILE ?? "",
4107
+ which: $which,
4108
+ exists: (p) => {
4109
+ try {
4110
+ return fs.existsSync(p);
4111
+ } catch {
4112
+ return false;
4113
+ }
4114
+ },
4115
+ readdir: (p) => fs.readdirSync(p),
4116
+ envPath: process.env.PUPPETEER_EXECUTABLE_PATH,
4117
+ cacheDirs: [getPuppeteerDir()]
4118
+ };
4119
+ }
4120
+ const FAMILY_NAMES = {
4121
+ edge: "Microsoft Edge",
4122
+ chrome: "Google Chrome",
4123
+ chromium: "Chromium",
4124
+ cfr: "Chrome for Testing",
4125
+ env: "PUPPETEER_EXECUTABLE_PATH"
4126
+ };
4127
+ /** Label a candidate path with its browser family (by filename). */
4128
+ function kindOf(executablePath) {
4129
+ const lower = (executablePath.replaceAll("\\", "/").split("/").pop() ?? executablePath).toLowerCase();
4130
+ if (lower.includes("msedge")) return "edge";
4131
+ if (lower.includes("chromium")) return "chromium";
4132
+ return "chrome";
4133
+ }
4134
+ /**
4135
+ * Candidate paths for the given platform with family labels, in the OMP
4136
+ * system table order (see `systemChromiumCandidates`). `env` paths are
4137
+ * injected separately by the caller.
4138
+ */
4139
+ function tableCandidates(env) {
4140
+ const out = [];
4141
+ for (const p of systemChromiumCandidatesForTest(env.platform, env.home, env.which)) {
4142
+ if (!p) continue;
4143
+ out.push({
4144
+ kind: kindOf(p),
4145
+ path: p
4146
+ });
4147
+ }
4148
+ return out;
4149
+ }
4150
+ /**
4151
+ * Scan a Chrome-for-Testing cache root for installed browsers
4152
+ * (`<root>/chrome/<platform>-<build>/chrome(.exe)` layout used by
4153
+ * @puppeteer/browsers and OMP's getPuppeteerDir cache).
4154
+ */
4155
+ function cfrCandidates(env) {
4156
+ const out = [];
4157
+ const execName = env.platform === "win32" ? "chrome.exe" : "chrome";
4158
+ const sep = env.platform === "win32" ? "\\" : "/";
4159
+ for (const root of env.cacheDirs ?? []) try {
4160
+ const chromeDir = `${root}${root.endsWith("/") || root.endsWith("\\") ? "" : sep}chrome`;
4161
+ if (!env.exists(chromeDir)) continue;
4162
+ const list = env.readdir?.(chromeDir) ?? [];
4163
+ for (const build of list) {
4164
+ if (build === "." || build === "..") continue;
4165
+ const exe = `${chromeDir}${sep}${build}${sep}${execName}`;
4166
+ if (env.exists(exe)) out.push({
4167
+ kind: "cfr",
4168
+ path: exe
4169
+ });
4170
+ }
4171
+ } catch {}
4172
+ return out;
4173
+ }
4174
+ /** Detect every usable browser on the machine, best first. No caching. */
4175
+ function probeBrowsers(env = defaultBrowserDetectEnv()) {
4176
+ const found = [];
4177
+ const seen = /* @__PURE__ */ new Set();
4178
+ const push = (browser) => {
4179
+ if (browser === void 0 || seen.has(browser.path)) return;
4180
+ seen.add(browser.path);
4181
+ found.push(browser);
4182
+ };
4183
+ if (env.envPath) push({
4184
+ kind: "env",
4185
+ name: FAMILY_NAMES.env,
4186
+ path: env.envPath
4187
+ });
4188
+ for (const candidate of [...tableCandidates(env), ...cfrCandidates(env)]) {
4189
+ if (!env.exists(candidate.path)) continue;
4190
+ push({
4191
+ kind: candidate.kind,
4192
+ name: FAMILY_NAMES[candidate.kind],
4193
+ path: candidate.path
4194
+ });
4195
+ }
4196
+ return found;
4197
+ }
4198
+ //#endregion
4199
+ //#region src/host/browser-probe-rpc.ts
4200
+ /**
4201
+ * Install the browser/detect RPC endpoint. Returns a disposer that removes
4202
+ * the registration (call it from the plugin's `ctx.effect` teardown).
4203
+ * Never throws for "unavailable" — the return value tells the caller whether
4204
+ * the channel is actually live.
4205
+ */
4206
+ function installBrowserProbeRpc(ctx) {
4207
+ let disposer;
4208
+ ctx.inject(["connection"], (connectionCtx) => {
4209
+ try {
4210
+ const handler = async (endpoint, _payload, _signal) => {
4211
+ if (endpoint !== "browser/detect") return {
4212
+ ok: false,
4213
+ error: {
4214
+ code: "bad-request",
4215
+ message: `Unknown tool-plus endpoint: ${endpoint}`,
4216
+ details: { issues: [] }
4217
+ }
4218
+ };
4219
+ try {
4220
+ return {
4221
+ ok: true,
4222
+ value: { found: probeBrowsers() }
4223
+ };
4224
+ } catch (error) {
4225
+ return {
4226
+ ok: false,
4227
+ error: {
4228
+ code: "internal",
4229
+ message: error instanceof Error ? error.message : String(error),
4230
+ details: {}
4231
+ }
4232
+ };
4233
+ }
4234
+ };
4235
+ disposer = connectionCtx.connection.rpc.handle(TOOL_PLUS_RPC_CHANNEL, handler, { authority: "loopback" });
4236
+ } catch {
4237
+ disposer = void 0;
4238
+ }
4239
+ });
4240
+ return () => disposer?.();
4241
+ }
4242
+ //#endregion
4009
4243
  //#region src/config/truncate.ts
4010
4244
  /**
4011
4245
  * Config-driven output truncation for background→foreground completion text.
@@ -13938,7 +14172,7 @@ function cleanFeedText(text) {
13938
14172
  * Parse RSS/Atom feed to markdown
13939
14173
  */
13940
14174
  async function parseFeedToMarkdown(content, maxItems = 10) {
13941
- const { parseHTML } = await import("./dom-DGdYAVTv.mjs");
14175
+ const { parseHTML } = await import("./dom-CawWi8fa.mjs");
13942
14176
  try {
13943
14177
  const doc = parseHTML(content).document;
13944
14178
  const channel = doc.querySelector("channel");
@@ -14000,16 +14234,32 @@ const FETCH_PROVIDER_ORDER = [
14000
14234
  "trafilatura",
14001
14235
  "lynx",
14002
14236
  "parallel",
14003
- "jina"
14237
+ "jina",
14238
+ "browser"
14004
14239
  ];
14240
+ /** Backends that cannot execute page JavaScript — held back on CSR shells. */
14241
+ const CSR_SUSCEPTIBLE = /* @__PURE__ */ new Set([
14242
+ "native",
14243
+ "trafilatura",
14244
+ "lynx"
14245
+ ]);
14005
14246
  /**
14006
14247
  * Render HTML to markdown by trying reader backends in priority order: native
14007
- * (in-process), trafilatura, lynx, Parallel, then Jina. The `providers.fetch`
14008
- * setting picks the order — `auto` uses the default above; any specific backend
14009
- * is tried first, then the remaining backends as fallbacks. Every backend's
14010
- * output must clear the same quality gate (>100 non-whitespace chars and not
14011
- * {@link isLowQualityOutput}) before it is accepted, otherwise the next backend
14012
- * is tried.
14248
+ * (in-process), trafilatura, lynx, Parallel, Jina, then the browser
14249
+ * (headless-Chromium JS rendering, see {@link renderUrlWithBrowser} — gated
14250
+ * behind `browser.readerEnabled`). The `providers.fetch` setting picks the
14251
+ * order — `auto` uses the default above; any specific backend is tried first,
14252
+ * then the remaining backends as fallbacks. Every backend's output must clear
14253
+ * the same quality gate (>100 non-whitespace chars and not
14254
+ * {@link isLowQualityOutput}) before it is accepted, otherwise the next
14255
+ * backend is tried.
14256
+ *
14257
+ * When the raw HTML is a CSR app shell (script-heavy, text-light), output
14258
+ * from {@link CSR_SUSCEPTIBLE} backends (which cannot execute page
14259
+ * JavaScript) is held back as low quality so the chain still reaches the
14260
+ * browser backend; with no usable browser the parked shell is returned as
14261
+ * before, so degradation is unchanged. The browser's own output on a shell
14262
+ * is accepted as-is (a noscript remnant is expected in it).
14013
14263
  *
14014
14264
  * The overall `timeout` budget bounds the whole call; remote backends (Parallel,
14015
14265
  * Jina) are additionally capped at `REMOTE_READER_MAX_MS` so a hung endpoint
@@ -14081,17 +14331,31 @@ async function renderHtmlToText(url, html, timeout, settings, userSignal, storag
14081
14331
  const contentLength = Number(response.headers.get("content-length"));
14082
14332
  if (Number.isFinite(contentLength) && contentLength > JINA_READER_MAX_BYTES) return null;
14083
14333
  return parseJinaReaderContent(await response.text());
14334
+ },
14335
+ browser: async () => {
14336
+ if (settings.get("browser.readerEnabled") === false) return null;
14337
+ const { renderUrlWithBrowser } = await import("./browser-render-z6b8Ljo9.mjs");
14338
+ return renderUrlWithBrowser(url, {
14339
+ timeoutMs: remoteBudgetMs,
14340
+ signal: userSignal
14341
+ });
14084
14342
  }
14085
14343
  };
14086
14344
  const preference = settings.get("providers.fetch");
14087
14345
  const order = preference === "auto" ? FETCH_PROVIDER_ORDER : [preference, ...FETCH_PROVIDER_ORDER.filter((method) => method !== preference)];
14088
14346
  let lowQuality = null;
14347
+ const csrShell = isCsrHtmlShell(html);
14089
14348
  for (const method of order) {
14090
14349
  userSignal?.throwIfAborted();
14091
14350
  try {
14092
14351
  const content = await runners[method]();
14093
14352
  if (!content || content.trim().length <= 100) continue;
14094
- if (!isLowQualityOutput(content)) return {
14353
+ if (csrShell && method === "browser") return {
14354
+ content,
14355
+ ok: true,
14356
+ method
14357
+ };
14358
+ if (!(csrShell && CSR_SUSCEPTIBLE.has(method)) && !isLowQualityOutput(content)) return {
14095
14359
  content,
14096
14360
  ok: true,
14097
14361
  method
@@ -14133,6 +14397,21 @@ function isLowQualityOutput(content) {
14133
14397
  return false;
14134
14398
  }
14135
14399
  /**
14400
+ * Detect a client-side-rendered (CSR) app shell in raw HTML: script-dense
14401
+ * markup with almost no statically visible text. Such pages only produce body
14402
+ * content after JavaScript executes, so JS-unaware extractors (native/
14403
+ * trafilatura/lynx) necessarily return a shell remnant (title/meta remnants)
14404
+ * while the browser backend can render the real body. Deliberately
14405
+ * conservative — compact HTML, multiple script tags, sparse static text — so
14406
+ * genuine SSR pages are never flagged and their rendering order is unchanged.
14407
+ * @returns true when the HTML looks like an unrendered SPA shell.
14408
+ */
14409
+ function isCsrHtmlShell(html) {
14410
+ if (html.length > 2e5) return false;
14411
+ if ((html.match(/<script\b/gi)?.length ?? 0) < 3) return false;
14412
+ return html.replace(/<script\b[\s\S]*?<\/script>/gi, " ").replace(/<style\b[\s\S]*?<\/style>/gi, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<[^>]+>/g, " ").replace(/&[a-z#0-9]+;/gi, " ").replace(/\s+/g, " ").trim().length < 2e3;
14413
+ }
14414
+ /**
14136
14415
  * Format JSON
14137
14416
  */
14138
14417
  function formatJson(content) {
@@ -14276,7 +14555,7 @@ let specialHandlersPromise;
14276
14555
  * requires a special handler, so we keep them out of the cold-startup graph.
14277
14556
  */
14278
14557
  function loadSpecialHandlers() {
14279
- specialHandlersPromise ??= import("./scrapers-1FTlHNQV.mjs").then((m) => m.specialHandlers);
14558
+ specialHandlersPromise ??= import("./scrapers-BlWQMGjU.mjs").then((m) => m.specialHandlers);
14280
14559
  return specialHandlersPromise;
14281
14560
  }
14282
14561
  /**
@@ -25493,6 +25772,7 @@ function apply(ctx, config = {}) {
25493
25772
  cfg = current();
25494
25773
  registerModeSensitive();
25495
25774
  });
25775
+ const disposeBrowserProbe = installBrowserProbeRpc(ctx);
25496
25776
  ctx.systemPrompt.section({
25497
25777
  name: "tool:bash",
25498
25778
  order: 105,
@@ -25502,6 +25782,7 @@ function apply(ctx, config = {}) {
25502
25782
  closeSessionShells("");
25503
25783
  cleanupSnapshots();
25504
25784
  sessionStates.clear();
25785
+ disposeBrowserProbe();
25505
25786
  }, "bash-plus teardown");
25506
25787
  ctx.on("agent/disposed", ({ agent }) => {
25507
25788
  closeSessionShells(agent.session.id);
@@ -1,9 +1,9 @@
1
1
  import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
2
  __installBunShim();
3
3
  import { r as __exportAll } from "./fs-promises-shim-Bx0fpxuk.mjs";
4
- import { H as getAgentDir, P as $env } from "./src-BgpusnsB.mjs";
5
- import { c as OAuthError, h as LoginCancelledError } from "./error-Dd8DIqs-.mjs";
6
- import "./utils-Cp76gCyk.mjs";
4
+ import { H as getAgentDir, P as $env } from "./src-D_e1qMwi.mjs";
5
+ import { c as OAuthError, h as LoginCancelledError } from "./error-DoHuatWw.mjs";
6
+ import "./utils-fnV2zzp3.mjs";
7
7
  import { n as isRecord } from "./type-guards-B9VVjRDK.mjs";
8
8
  import * as path from "node:path";
9
9
  import * as fs from "node:fs";