@code-yeongyu/senpi 2026.9.23-3 → 2026.9.23-4

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 (137) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/bundle/chunks/{app-server-command-U5Y46LHO.js → app-server-command-QRBQLEXY.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-UCTYTLP3.js → chunk-3RN6BFG2.js} +2 -2
  4. package/dist/bundle/chunks/{chunk-XTXBPXZZ.js → chunk-EN6KDFY2.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-2NFHX2FJ.js → chunk-J3QXPP4T.js} +1 -1
  6. package/dist/bundle/chunks/chunk-KBG7BJIL.js +8 -0
  7. package/dist/bundle/chunks/{chunk-TH4PERSI.js → chunk-N46LNXHU.js} +35 -53
  8. package/dist/bundle/chunks/{chunk-67Z5WNA4.js → chunk-PSMTQDII.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-Y4AJLTFT.js → chunk-WUYBEF7C.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-IDSOMHWS.js → chunk-WXIRFRXY.js} +1 -1
  11. package/dist/bundle/chunks/{chunk-R6F525XB.js → chunk-XDSQYM4F.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-TUVSARCZ.js → chunk-ZEFQYQOU.js} +1 -1
  13. package/dist/bundle/chunks/{cli-main-65WMMIRT.js → cli-main-ROBDBYAB.js} +1 -1
  14. package/dist/bundle/chunks/cursor-agent.js +1 -1
  15. package/dist/bundle/chunks/{help-fast-path-VXAZDQ3Z.js → help-fast-path-QXVCHTP3.js} +1 -1
  16. package/dist/bundle/chunks/{host-command-5PEFD4N6.js → host-command-3PUZYQOK.js} +1 -1
  17. package/dist/bundle/chunks/{host-lifecycle-BXW5C4JT.js → host-lifecycle-OHPSU5VU.js} +1 -1
  18. package/dist/bundle/chunks/{interactive-host-runtime-DUNYT24Q.js → interactive-host-runtime-57LEAJPU.js} +1 -1
  19. package/dist/bundle/chunks/{interactive-mode-SCG5PQZ6.js → interactive-mode-SLPAGRHH.js} +1 -1
  20. package/dist/bundle/chunks/{multi-session-host-QC6BZZNH.js → multi-session-host-3PACMEHC.js} +1 -1
  21. package/dist/bundle/chunks/{package-manager-cli-23GULCVL.js → package-manager-cli-6UIUSRQO.js} +1 -1
  22. package/dist/bundle/chunks/{pi-messages-B6RSUQKL.js → pi-messages-CAS467IY.js} +1 -1
  23. package/dist/bundle/chunks/{rotation-stream-ZIYWOB2N.js → rotation-stream-CZT4TRPD.js} +1 -1
  24. package/dist/bundle/chunks/{rpc-mode-ZQ4E6FFA.js → rpc-mode-47EVLL6X.js} +1 -1
  25. package/dist/bundle/chunks/{session-picker-CO2ZK3EC.js → session-picker-ZIBANFBQ.js} +1 -1
  26. package/dist/bundle/chunks/session-worker.js +40 -58
  27. package/dist/bundle/cli.js +1 -1
  28. package/dist/bundle/index.js +1 -1
  29. package/dist/bundle/rpc-entry.js +1 -1
  30. package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts.map +1 -1
  31. package/dist/core/extensions/builtin/cursor-cli-oauth/models.js +43 -26
  32. package/dist/core/extensions/builtin/cursor-cli-oauth/models.js.map +1 -1
  33. package/dist/core/extensions/builtin/nested-agents-md/index.js +1 -1
  34. package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -1
  35. package/dist/core/extensions/builtin/rule-activation/types.d.ts +2 -0
  36. package/dist/core/extensions/builtin/rule-activation/types.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/rule-activation/types.js +7 -1
  38. package/dist/core/extensions/builtin/rule-activation/types.js.map +1 -1
  39. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/rules/index.js +2 -1
  41. package/dist/core/extensions/builtin/rules/index.js.map +1 -1
  42. package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts +3 -1
  43. package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +9 -3
  45. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -1
  46. package/dist/core/model-resolver.d.ts.map +1 -1
  47. package/dist/core/model-resolver.js +87 -14
  48. package/dist/core/model-resolver.js.map +1 -1
  49. package/dist/core/tools/bash.d.ts.map +1 -1
  50. package/dist/core/tools/bash.js +12 -7
  51. package/dist/core/tools/bash.js.map +1 -1
  52. package/dist/core/tools/find.d.ts.map +1 -1
  53. package/dist/core/tools/find.js +9 -6
  54. package/dist/core/tools/find.js.map +1 -1
  55. package/dist/core/tools/grep/format.d.ts +3 -2
  56. package/dist/core/tools/grep/format.d.ts.map +1 -1
  57. package/dist/core/tools/grep/format.js +5 -3
  58. package/dist/core/tools/grep/format.js.map +1 -1
  59. package/dist/core/tools/grep/index.js +2 -2
  60. package/dist/core/tools/grep/index.js.map +1 -1
  61. package/dist/core/tools/ls.d.ts.map +1 -1
  62. package/dist/core/tools/ls.js +5 -3
  63. package/dist/core/tools/ls.js.map +1 -1
  64. package/dist/core/tools/model-only-text.d.ts +4 -0
  65. package/dist/core/tools/model-only-text.d.ts.map +1 -0
  66. package/dist/core/tools/model-only-text.js +12 -0
  67. package/dist/core/tools/model-only-text.js.map +1 -0
  68. package/dist/core/tools/read.d.ts.map +1 -1
  69. package/dist/core/tools/read.js +15 -5
  70. package/dist/core/tools/read.js.map +1 -1
  71. package/dist/core/tools/render-utils.d.ts.map +1 -1
  72. package/dist/core/tools/render-utils.js +2 -1
  73. package/dist/core/tools/render-utils.js.map +1 -1
  74. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  75. package/dist/core/tools/renderers/bash.js +1 -25
  76. package/dist/core/tools/renderers/bash.js.map +1 -1
  77. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  78. package/dist/core/tools/renderers/grep.js +0 -25
  79. package/dist/core/tools/renderers/grep.js.map +1 -1
  80. package/dist/core/tools/renderers/read.d.ts +8 -0
  81. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  82. package/dist/core/tools/renderers/read.js +2 -14
  83. package/dist/core/tools/renderers/read.js.map +1 -1
  84. package/dist/modes/interactive/components/exploration-call.d.ts +4 -1
  85. package/dist/modes/interactive/components/exploration-call.d.ts.map +1 -1
  86. package/dist/modes/interactive/components/exploration-call.js +17 -2
  87. package/dist/modes/interactive/components/exploration-call.js.map +1 -1
  88. package/dist/modes/interactive/components/exploration-group.d.ts +3 -1
  89. package/dist/modes/interactive/components/exploration-group.d.ts.map +1 -1
  90. package/dist/modes/interactive/components/exploration-group.js +7 -1
  91. package/dist/modes/interactive/components/exploration-group.js.map +1 -1
  92. package/dist/modes/interactive/components/exploration-rules.d.ts +5 -0
  93. package/dist/modes/interactive/components/exploration-rules.d.ts.map +1 -0
  94. package/dist/modes/interactive/components/exploration-rules.js +15 -0
  95. package/dist/modes/interactive/components/exploration-rules.js.map +1 -0
  96. package/dist/modes/interactive/components/exploration-transcript-container.d.ts.map +1 -1
  97. package/dist/modes/interactive/components/exploration-transcript-container.js +10 -1
  98. package/dist/modes/interactive/components/exploration-transcript-container.js.map +1 -1
  99. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  100. package/dist/modes/interactive/components/tool-execution.js +4 -1
  101. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  102. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
  103. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  104. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +4 -19
  105. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  106. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.d.ts.map +1 -1
  107. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +17 -1
  108. package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js.map +1 -1
  109. package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.d.ts +18 -1
  110. package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.d.ts.map +1 -1
  111. package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.js +103 -3
  112. package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.js.map +1 -1
  113. package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts +3 -1
  114. package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts.map +1 -1
  115. package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js +15 -3
  116. package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js.map +1 -1
  117. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts +7 -2
  118. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts.map +1 -1
  119. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js +92 -20
  120. package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js.map +1 -1
  121. package/node_modules/@earendil-works/pi-ai/dist/model.d.ts +9 -1
  122. package/node_modules/@earendil-works/pi-ai/dist/model.d.ts.map +1 -1
  123. package/node_modules/@earendil-works/pi-ai/dist/model.js.map +1 -1
  124. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.d.ts.map +1 -1
  125. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js +1 -0
  126. package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js.map +1 -1
  127. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  128. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  129. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +5 -0
  130. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  131. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  132. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  133. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  134. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  135. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  136. package/package.json +7 -7
  137. package/dist/bundle/chunks/chunk-XPDV6SIX.js +0 -8
@@ -1,5 +1,6 @@
1
1
  import { StringEnum } from "@earendil-works/pi-ai";
2
2
  import { Type } from "typebox";
3
+ import { modelOnlyText } from "../../../../tools/model-only-text.js";
3
4
  import { defineTool } from "../../../types.js";
4
5
  import { htmlToMarkdown, htmlToText } from "./content.lazy.js";
5
6
  import { clampTimeout, fetchUrl } from "./fetcher.js";
@@ -107,8 +108,13 @@ export const webfetch = defineTool({
107
108
  outputBytes: capped.outputBytes,
108
109
  outputTotalBytes: capped.totalBytes,
109
110
  };
111
+ const content = [
112
+ { type: "text", text: capped.notice === undefined ? capped.text : `${capped.text}\n` },
113
+ ];
114
+ if (capped.notice !== undefined)
115
+ content.push(modelOnlyText(capped.notice));
110
116
  return {
111
- content: [{ type: "text", text: capped.text }],
117
+ content,
112
118
  details,
113
119
  };
114
120
  },
@@ -138,8 +144,8 @@ export function capWebfetchOutput(text) {
138
144
  }
139
145
  const head = takeHeadBytes(text, DEFAULT_OUTPUT_MAX_BYTES);
140
146
  const outputBytes = Buffer.byteLength(head, "utf-8");
141
- const notice = `\n\n[Output truncated: ${formatByteSize(outputBytes)} of ${formatByteSize(totalBytes)} shown (${formatByteSize(DEFAULT_OUTPUT_MAX_BYTES)} limit). Re-fetch a more specific URL or use web_search for targeted content.]`;
142
- return { text: head + notice, truncated: true, outputBytes, totalBytes };
147
+ const notice = `[Output truncated: ${formatByteSize(outputBytes)} of ${formatByteSize(totalBytes)} shown (${formatByteSize(DEFAULT_OUTPUT_MAX_BYTES)} limit). Re-fetch a more specific URL or use web_search for targeted content.]`;
148
+ return { text: head, notice, truncated: true, outputBytes, totalBytes };
143
149
  }
144
150
  /** Keep whole leading lines within the byte ceiling; fall back to a UTF-8-safe byte prefix for one oversized line. */
145
151
  function takeHeadBytes(text, maxBytes) {
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/webfetch/webfetch/tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport { defineTool } from \"../../../types.ts\";\n\nimport { htmlToMarkdown, htmlToText } from \"./content.lazy.ts\";\nimport { clampTimeout, fetchUrl, type WebfetchFormat } from \"./fetcher.ts\";\n\nconst WEBFETCH_FORMATS = [\"markdown\", \"text\", \"html\"] as const;\n\nconst Params = Type.Object({\n\turl: Type.String({ description: \"The URL to fetch content from\" }),\n\tformat: Type.Optional(\n\t\tStringEnum([\"markdown\", \"text\", \"html\"] as const, {\n\t\t\tdescription: \"The format to return the content in. Defaults to markdown.\",\n\t\t}),\n\t),\n\ttimeout: Type.Optional(Type.Number({ description: \"Optional timeout in seconds. Maximum 120.\" })),\n});\n\nexport interface WebfetchDetails {\n\turl: string;\n\tfinalUrl: string;\n\tformat: WebfetchFormat;\n\tstatus: number;\n\tstatusText: string;\n\tcontentType: string;\n\tbytes: number;\n\ttimeoutSeconds: number;\n\tconverted: boolean;\n\t/** Whether the network response body was truncated at the {@link MAX_RESPONSE_SIZE_BYTES} fetch limit. */\n\ttruncated: boolean;\n\t/** Whether the text handed to the model was capped below the raw content size. */\n\toutputTruncated: boolean;\n\t/** Byte length of the text handed to the model (excluding the truncation notice). */\n\toutputBytes: number;\n\t/** Byte length of the full converted text before the output cap. */\n\toutputTotalBytes: number;\n}\n\nexport interface WebfetchProgressDetails {\n\tphase: \"fetching\" | \"downloading\" | \"converting\";\n\turl: string;\n\tformat: WebfetchFormat;\n\ttimeoutSeconds: number;\n\tbytesRead?: number;\n\ttotalBytes?: number;\n\tprogress: {\n\t\tactivity: string;\n\t\tstartedAt: number;\n\t\tmaxWaitMs: number;\n\t};\n}\n\nexport type WebfetchRenderDetails = WebfetchDetails | WebfetchProgressDetails;\n\nexport const webfetch = defineTool<typeof Params, WebfetchRenderDetails>({\n\tname: \"webfetch\",\n\tlabel: \"Web Fetch\",\n\tdescription:\n\t\t\"Fetches content from a URL and returns it as markdown, plain text, or HTML. \" +\n\t\t\"Network use is bounded by timeout and response size limits.\",\n\tpromptSnippet: \"webfetch: retrieve URL content as markdown, text, or html\",\n\tpromptGuidelines: [\n\t\t\"Use webfetch when a specific URL must be retrieved.\",\n\t\t\"Prefer markdown format unless raw HTML or plain text is explicitly needed.\",\n\t\t\"The tool is read-only and does not modify files.\",\n\t],\n\tparameters: Params,\n\tasync execute(_toolCallId, params, signal, onUpdate, _ctx) {\n\t\tconst format = parseWebfetchFormat(params.format);\n\t\tconst timeoutSeconds = clampTimeout(params.timeout);\n\t\tconst startedAt = Date.now();\n\t\tconst progress = {\n\t\t\tactivity: `fetching ${params.url}`,\n\t\t\tstartedAt,\n\t\t\tmaxWaitMs: timeoutSeconds * 1000,\n\t\t};\n\t\tlet downloadedTotalBytes: number | undefined;\n\t\tconst emitProgress = (details: WebfetchProgressDetails): void => {\n\t\t\tonUpdate?.({\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Fetching ${params.url} as ${format} (timeout ${timeoutSeconds}s)`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails,\n\t\t\t});\n\t\t};\n\t\temitProgress({\n\t\t\tphase: \"fetching\",\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\tprogress,\n\t\t});\n\n\t\tconst fetched = await fetchUrl({\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\tonProgress: (bytesRead, totalBytes) => {\n\t\t\t\tdownloadedTotalBytes = totalBytes;\n\t\t\t\temitProgress({\n\t\t\t\t\tphase: \"downloading\",\n\t\t\t\t\turl: params.url,\n\t\t\t\t\tformat,\n\t\t\t\t\ttimeoutSeconds,\n\t\t\t\t\tbytesRead,\n\t\t\t\t\t...(totalBytes === undefined ? {} : { totalBytes }),\n\t\t\t\t\tprogress,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t\tconst raw = new TextDecoder().decode(fetched.body);\n\t\tconst contentType = fetched.contentType.toLowerCase();\n\t\temitProgress({\n\t\t\tphase: \"converting\",\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\tbytesRead: fetched.bytes,\n\t\t\t...(downloadedTotalBytes === undefined ? {} : { totalBytes: downloadedTotalBytes }),\n\t\t\tprogress,\n\t\t});\n\t\tconst isHtml = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\t\tlet text = raw;\n\t\tlet converted = false;\n\n\t\tif (isHtml && format === \"markdown\") {\n\t\t\ttext = await htmlToMarkdown(raw, fetched.url);\n\t\t\tconverted = true;\n\t\t} else if (isHtml && format === \"text\") {\n\t\t\ttext = await htmlToText(raw, fetched.url);\n\t\t\tconverted = true;\n\t\t}\n\n\t\tconst capped = capWebfetchOutput(text);\n\n\t\tconst details: WebfetchDetails = {\n\t\t\turl: params.url,\n\t\t\tfinalUrl: fetched.url,\n\t\t\tformat,\n\t\t\tstatus: fetched.status,\n\t\t\tstatusText: fetched.statusText,\n\t\t\tcontentType: fetched.contentType,\n\t\t\tbytes: fetched.bytes,\n\t\t\ttimeoutSeconds,\n\t\t\tconverted,\n\t\t\ttruncated: fetched.truncated,\n\t\t\toutputTruncated: capped.truncated,\n\t\t\toutputBytes: capped.outputBytes,\n\t\t\toutputTotalBytes: capped.totalBytes,\n\t\t};\n\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text: capped.text }],\n\t\t\tdetails,\n\t\t};\n\t},\n});\n\nexport function parseWebfetchFormat(value: unknown): WebfetchFormat {\n\tif (value === undefined) return \"markdown\";\n\tfor (const format of WEBFETCH_FORMATS) {\n\t\tif (value === format) return format;\n\t}\n\treturn \"markdown\";\n}\n\n/** Byte ceiling for the text handed to the model, mirroring senpi's read-tool output cap. */\nexport const DEFAULT_OUTPUT_MAX_BYTES = 50 * 1024;\n\nexport interface WebfetchOutputCap {\n\t/** Model-facing text after the output cap, with a notice appended when truncated. */\n\ttext: string;\n\t/** Whether the text was capped below the full converted size. */\n\ttruncated: boolean;\n\t/** Byte length of {@link WebfetchOutputCap.text} excluding the appended notice. */\n\toutputBytes: number;\n\t/** Byte length of the full converted text before capping. */\n\ttotalBytes: number;\n}\n\n/**\n * Bound the text handed to the model so a single fetch cannot flood the context\n * window and force an unwanted compaction. Keeps whole leading lines until the\n * byte ceiling is hit; when the first line alone exceeds the ceiling (minified\n * JSON, single-line payloads) it falls back to a UTF-8-safe byte prefix so the\n * head is preserved instead of dropped.\n */\nexport function capWebfetchOutput(text: string): WebfetchOutputCap {\n\tconst totalBytes = Buffer.byteLength(text, \"utf-8\");\n\tif (totalBytes <= DEFAULT_OUTPUT_MAX_BYTES) {\n\t\treturn { text, truncated: false, outputBytes: totalBytes, totalBytes };\n\t}\n\n\tconst head = takeHeadBytes(text, DEFAULT_OUTPUT_MAX_BYTES);\n\tconst outputBytes = Buffer.byteLength(head, \"utf-8\");\n\tconst notice = `\\n\\n[Output truncated: ${formatByteSize(outputBytes)} of ${formatByteSize(\n\t\ttotalBytes,\n\t)} shown (${formatByteSize(DEFAULT_OUTPUT_MAX_BYTES)} limit). Re-fetch a more specific URL or use web_search for targeted content.]`;\n\treturn { text: head + notice, truncated: true, outputBytes, totalBytes };\n}\n\n/** Keep whole leading lines within the byte ceiling; fall back to a UTF-8-safe byte prefix for one oversized line. */\nfunction takeHeadBytes(text: string, maxBytes: number): string {\n\tconst lines: string[] = [];\n\tlet usedBytes = 0;\n\tlet start = 0;\n\twhile (start <= text.length) {\n\t\tconst newlineIndex = text.indexOf(\"\\n\", start);\n\t\tconst line = newlineIndex === -1 ? text.slice(start) : text.slice(start, newlineIndex);\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (lines.length > 0 ? 1 : 0);\n\t\tif (usedBytes + lineBytes > maxBytes) break;\n\t\tlines.push(line);\n\t\tusedBytes += lineBytes;\n\t\tif (newlineIndex === -1) break;\n\t\tstart = newlineIndex + 1;\n\t}\n\treturn lines.length === 0 ? sliceUtf8Head(text, maxBytes) : lines.join(\"\\n\");\n}\n\n/** Slice the first {@link maxBytes} bytes of a UTF-8 string without leaving a split code point. */\nfunction sliceUtf8Head(value: string, maxBytes: number): string {\n\tconst buffer = Buffer.from(value, \"utf-8\");\n\tif (buffer.length <= maxBytes) return value;\n\tconst decoded = new TextDecoder(\"utf-8\").decode(buffer.subarray(0, maxBytes));\n\t// A trailing partial code point decodes to U+FFFD; drop it so no split byte remains.\n\treturn decoded.endsWith(\"\\uFFFD\") ? decoded.slice(0, -1) : decoded;\n}\n\n/** Human-readable byte size (B / KB / MB). */\nfunction formatByteSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n"]}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/webfetch/webfetch/tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { StringEnum, type TextContent } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport { modelOnlyText } from \"../../../../tools/model-only-text.ts\";\nimport { defineTool } from \"../../../types.ts\";\n\nimport { htmlToMarkdown, htmlToText } from \"./content.lazy.ts\";\nimport { clampTimeout, fetchUrl, type WebfetchFormat } from \"./fetcher.ts\";\n\nconst WEBFETCH_FORMATS = [\"markdown\", \"text\", \"html\"] as const;\n\nconst Params = Type.Object({\n\turl: Type.String({ description: \"The URL to fetch content from\" }),\n\tformat: Type.Optional(\n\t\tStringEnum([\"markdown\", \"text\", \"html\"] as const, {\n\t\t\tdescription: \"The format to return the content in. Defaults to markdown.\",\n\t\t}),\n\t),\n\ttimeout: Type.Optional(Type.Number({ description: \"Optional timeout in seconds. Maximum 120.\" })),\n});\n\nexport interface WebfetchDetails {\n\turl: string;\n\tfinalUrl: string;\n\tformat: WebfetchFormat;\n\tstatus: number;\n\tstatusText: string;\n\tcontentType: string;\n\tbytes: number;\n\ttimeoutSeconds: number;\n\tconverted: boolean;\n\t/** Whether the network response body was truncated at the {@link MAX_RESPONSE_SIZE_BYTES} fetch limit. */\n\ttruncated: boolean;\n\t/** Whether the text handed to the model was capped below the raw content size. */\n\toutputTruncated: boolean;\n\t/** Byte length of the text handed to the model (excluding the truncation notice). */\n\toutputBytes: number;\n\t/** Byte length of the full converted text before the output cap. */\n\toutputTotalBytes: number;\n}\n\nexport interface WebfetchProgressDetails {\n\tphase: \"fetching\" | \"downloading\" | \"converting\";\n\turl: string;\n\tformat: WebfetchFormat;\n\ttimeoutSeconds: number;\n\tbytesRead?: number;\n\ttotalBytes?: number;\n\tprogress: {\n\t\tactivity: string;\n\t\tstartedAt: number;\n\t\tmaxWaitMs: number;\n\t};\n}\n\nexport type WebfetchRenderDetails = WebfetchDetails | WebfetchProgressDetails;\n\nexport const webfetch = defineTool<typeof Params, WebfetchRenderDetails>({\n\tname: \"webfetch\",\n\tlabel: \"Web Fetch\",\n\tdescription:\n\t\t\"Fetches content from a URL and returns it as markdown, plain text, or HTML. \" +\n\t\t\"Network use is bounded by timeout and response size limits.\",\n\tpromptSnippet: \"webfetch: retrieve URL content as markdown, text, or html\",\n\tpromptGuidelines: [\n\t\t\"Use webfetch when a specific URL must be retrieved.\",\n\t\t\"Prefer markdown format unless raw HTML or plain text is explicitly needed.\",\n\t\t\"The tool is read-only and does not modify files.\",\n\t],\n\tparameters: Params,\n\tasync execute(_toolCallId, params, signal, onUpdate, _ctx) {\n\t\tconst format = parseWebfetchFormat(params.format);\n\t\tconst timeoutSeconds = clampTimeout(params.timeout);\n\t\tconst startedAt = Date.now();\n\t\tconst progress = {\n\t\t\tactivity: `fetching ${params.url}`,\n\t\t\tstartedAt,\n\t\t\tmaxWaitMs: timeoutSeconds * 1000,\n\t\t};\n\t\tlet downloadedTotalBytes: number | undefined;\n\t\tconst emitProgress = (details: WebfetchProgressDetails): void => {\n\t\t\tonUpdate?.({\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Fetching ${params.url} as ${format} (timeout ${timeoutSeconds}s)`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails,\n\t\t\t});\n\t\t};\n\t\temitProgress({\n\t\t\tphase: \"fetching\",\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\tprogress,\n\t\t});\n\n\t\tconst fetched = await fetchUrl({\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\tonProgress: (bytesRead, totalBytes) => {\n\t\t\t\tdownloadedTotalBytes = totalBytes;\n\t\t\t\temitProgress({\n\t\t\t\t\tphase: \"downloading\",\n\t\t\t\t\turl: params.url,\n\t\t\t\t\tformat,\n\t\t\t\t\ttimeoutSeconds,\n\t\t\t\t\tbytesRead,\n\t\t\t\t\t...(totalBytes === undefined ? {} : { totalBytes }),\n\t\t\t\t\tprogress,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t\tconst raw = new TextDecoder().decode(fetched.body);\n\t\tconst contentType = fetched.contentType.toLowerCase();\n\t\temitProgress({\n\t\t\tphase: \"converting\",\n\t\t\turl: params.url,\n\t\t\tformat,\n\t\t\ttimeoutSeconds,\n\t\t\tbytesRead: fetched.bytes,\n\t\t\t...(downloadedTotalBytes === undefined ? {} : { totalBytes: downloadedTotalBytes }),\n\t\t\tprogress,\n\t\t});\n\t\tconst isHtml = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\t\tlet text = raw;\n\t\tlet converted = false;\n\n\t\tif (isHtml && format === \"markdown\") {\n\t\t\ttext = await htmlToMarkdown(raw, fetched.url);\n\t\t\tconverted = true;\n\t\t} else if (isHtml && format === \"text\") {\n\t\t\ttext = await htmlToText(raw, fetched.url);\n\t\t\tconverted = true;\n\t\t}\n\n\t\tconst capped = capWebfetchOutput(text);\n\n\t\tconst details: WebfetchDetails = {\n\t\t\turl: params.url,\n\t\t\tfinalUrl: fetched.url,\n\t\t\tformat,\n\t\t\tstatus: fetched.status,\n\t\t\tstatusText: fetched.statusText,\n\t\t\tcontentType: fetched.contentType,\n\t\t\tbytes: fetched.bytes,\n\t\t\ttimeoutSeconds,\n\t\t\tconverted,\n\t\t\ttruncated: fetched.truncated,\n\t\t\toutputTruncated: capped.truncated,\n\t\t\toutputBytes: capped.outputBytes,\n\t\t\toutputTotalBytes: capped.totalBytes,\n\t\t};\n\n\t\tconst content: TextContent[] = [\n\t\t\t{ type: \"text\", text: capped.notice === undefined ? capped.text : `${capped.text}\\n` },\n\t\t];\n\t\tif (capped.notice !== undefined) content.push(modelOnlyText(capped.notice));\n\t\treturn {\n\t\t\tcontent,\n\t\t\tdetails,\n\t\t};\n\t},\n});\n\nexport function parseWebfetchFormat(value: unknown): WebfetchFormat {\n\tif (value === undefined) return \"markdown\";\n\tfor (const format of WEBFETCH_FORMATS) {\n\t\tif (value === format) return format;\n\t}\n\treturn \"markdown\";\n}\n\n/** Byte ceiling for the text handed to the model, mirroring senpi's read-tool output cap. */\nexport const DEFAULT_OUTPUT_MAX_BYTES = 50 * 1024;\n\nexport interface WebfetchOutputCap {\n\t/** Model-facing body after the output cap. */\n\ttext: string;\n\t/** Separate model-only continuation notice when truncated. */\n\tnotice?: string;\n\t/** Whether the text was capped below the full converted size. */\n\ttruncated: boolean;\n\t/** Byte length of {@link WebfetchOutputCap.text} excluding the appended notice. */\n\toutputBytes: number;\n\t/** Byte length of the full converted text before capping. */\n\ttotalBytes: number;\n}\n\n/**\n * Bound the text handed to the model so a single fetch cannot flood the context\n * window and force an unwanted compaction. Keeps whole leading lines until the\n * byte ceiling is hit; when the first line alone exceeds the ceiling (minified\n * JSON, single-line payloads) it falls back to a UTF-8-safe byte prefix so the\n * head is preserved instead of dropped.\n */\nexport function capWebfetchOutput(text: string): WebfetchOutputCap {\n\tconst totalBytes = Buffer.byteLength(text, \"utf-8\");\n\tif (totalBytes <= DEFAULT_OUTPUT_MAX_BYTES) {\n\t\treturn { text, truncated: false, outputBytes: totalBytes, totalBytes };\n\t}\n\n\tconst head = takeHeadBytes(text, DEFAULT_OUTPUT_MAX_BYTES);\n\tconst outputBytes = Buffer.byteLength(head, \"utf-8\");\n\tconst notice = `[Output truncated: ${formatByteSize(outputBytes)} of ${formatByteSize(\n\t\ttotalBytes,\n\t)} shown (${formatByteSize(DEFAULT_OUTPUT_MAX_BYTES)} limit). Re-fetch a more specific URL or use web_search for targeted content.]`;\n\treturn { text: head, notice, truncated: true, outputBytes, totalBytes };\n}\n\n/** Keep whole leading lines within the byte ceiling; fall back to a UTF-8-safe byte prefix for one oversized line. */\nfunction takeHeadBytes(text: string, maxBytes: number): string {\n\tconst lines: string[] = [];\n\tlet usedBytes = 0;\n\tlet start = 0;\n\twhile (start <= text.length) {\n\t\tconst newlineIndex = text.indexOf(\"\\n\", start);\n\t\tconst line = newlineIndex === -1 ? text.slice(start) : text.slice(start, newlineIndex);\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (lines.length > 0 ? 1 : 0);\n\t\tif (usedBytes + lineBytes > maxBytes) break;\n\t\tlines.push(line);\n\t\tusedBytes += lineBytes;\n\t\tif (newlineIndex === -1) break;\n\t\tstart = newlineIndex + 1;\n\t}\n\treturn lines.length === 0 ? sliceUtf8Head(text, maxBytes) : lines.join(\"\\n\");\n}\n\n/** Slice the first {@link maxBytes} bytes of a UTF-8 string without leaving a split code point. */\nfunction sliceUtf8Head(value: string, maxBytes: number): string {\n\tconst buffer = Buffer.from(value, \"utf-8\");\n\tif (buffer.length <= maxBytes) return value;\n\tconst decoded = new TextDecoder(\"utf-8\").decode(buffer.subarray(0, maxBytes));\n\t// A trailing partial code point decodes to U+FFFD; drop it so no split byte remains.\n\treturn decoded.endsWith(\"\\uFFFD\") ? decoded.slice(0, -1) : decoded;\n}\n\n/** Human-readable byte size (B / KB / MB). */\nfunction formatByteSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Model resolution, scoping, and initial selection
3
3
  */
4
- import { getCursorVariantAlias, modelsAreEqual, } from "@earendil-works/pi-ai";
4
+ import { getCursorVariantAlias, modelsAreEqual, parseCursorVariantId, } from "@earendil-works/pi-ai";
5
5
  import chalk from "chalk";
6
6
  import { minimatch } from "minimatch";
7
7
  import { isValidThinkingLevel } from "../cli/args.js";
@@ -120,6 +120,44 @@ function legacySelection(legacyVariantId) {
120
120
  return undefined;
121
121
  return { level: alias.level, source: "legacy-variant", legacyVariantId };
122
122
  }
123
+ function derivedCursorVariantIds(model) {
124
+ if ((model.provider !== "cursor" || model.api !== "cursor-agent") &&
125
+ (model.provider !== "cursor-cli-oauth" || model.api !== "cursor-cli-oauth"))
126
+ return undefined;
127
+ // The CLI provider registers its own API id but shares Cursor's catalog compat schema.
128
+ return model.compat?.cursorReasoning?.variantIds;
129
+ }
130
+ /**
131
+ * Reverse lookup through variant ids a runtime-derived Cursor group observed (senpi#2038).
132
+ * Case-insensitive like `findExactModelReferenceMatch`, which resolved these ids before grouping.
133
+ */
134
+ function derivedCursorVariantMatch(model, reference) {
135
+ const variantIds = derivedCursorVariantIds(model);
136
+ if (variantIds === undefined)
137
+ return undefined;
138
+ const normalized = reference.toLowerCase();
139
+ for (const [level, id] of Object.entries(variantIds)) {
140
+ if (id?.toLowerCase() === normalized)
141
+ return { level: level, variantId: id };
142
+ }
143
+ return undefined;
144
+ }
145
+ function derivedResolution(model, match) {
146
+ return {
147
+ model,
148
+ thinkingLevel: match.level,
149
+ thinkingSelection: { level: match.level, source: "legacy-variant", legacyVariantId: match.variantId },
150
+ };
151
+ }
152
+ function cursorLegacySelection(model, variantId) {
153
+ const alias = legacySelection(variantId);
154
+ if (alias)
155
+ return alias;
156
+ const match = derivedCursorVariantMatch(model, variantId);
157
+ return match === undefined
158
+ ? undefined
159
+ : { level: match.level, source: "legacy-variant", legacyVariantId: match.variantId };
160
+ }
123
161
  function resolveLegacyCursorReference(modelReference, availableModels) {
124
162
  const trimmed = modelReference.trim();
125
163
  if (!trimmed)
@@ -128,19 +166,31 @@ function resolveLegacyCursorReference(modelReference, availableModels) {
128
166
  const explicitProvider = slashIndex === -1 ? undefined : trimmed.slice(0, slashIndex);
129
167
  const legacyVariantId = slashIndex === -1 ? trimmed : trimmed.slice(slashIndex + 1);
130
168
  const alias = getCursorVariantAlias(legacyVariantId);
131
- if (!alias)
169
+ const providerMatches = (model) => CURSOR_PROVIDER_IDS.has(model.provider) &&
170
+ (!explicitProvider || model.provider.toLowerCase() === explicitProvider.toLowerCase());
171
+ if (alias) {
172
+ const candidates = availableModels.filter((model) => providerMatches(model) && model.id === alias.targetId);
173
+ if (candidates.length !== 1)
174
+ return undefined;
175
+ const thinkingSelection = legacySelection(legacyVariantId);
176
+ return {
177
+ model: candidates[0],
178
+ thinkingLevel: thinkingSelection?.level,
179
+ thinkingSelection,
180
+ };
181
+ }
182
+ // Unlike static aliases, derived aliases must not displace an exact raw model.
183
+ const exactCandidates = explicitProvider ? availableModels.filter(providerMatches) : availableModels;
184
+ if (findExactModelReferenceMatch(trimmed, [...exactCandidates]))
132
185
  return undefined;
133
- const candidates = availableModels.filter((model) => CURSOR_PROVIDER_IDS.has(model.provider) &&
134
- (!explicitProvider || model.provider.toLowerCase() === explicitProvider.toLowerCase()) &&
135
- model.id === alias.targetId);
136
- if (candidates.length !== 1)
186
+ // Variant ids only the runtime derivation groups resolve through the observed ids (senpi#2038).
187
+ const derivedCandidates = availableModels.flatMap((model) => {
188
+ const match = providerMatches(model) ? derivedCursorVariantMatch(model, legacyVariantId) : undefined;
189
+ return match === undefined ? [] : [{ model, match }];
190
+ });
191
+ if (derivedCandidates.length !== 1)
137
192
  return undefined;
138
- const thinkingSelection = legacySelection(legacyVariantId);
139
- return {
140
- model: candidates[0],
141
- thinkingLevel: thinkingSelection?.level,
142
- thinkingSelection,
143
- };
193
+ return derivedResolution(derivedCandidates[0].model, derivedCandidates[0].match);
144
194
  }
145
195
  function cursorLegacyAliasesForModel(model) {
146
196
  if (!CURSOR_PROVIDER_IDS.has(model.provider))
@@ -154,7 +204,22 @@ function cursorLegacyAliasesForModel(model) {
154
204
  candidates.add(`${baseId}-${level}-thinking`);
155
205
  candidates.add(`${targetId}-${level}`);
156
206
  }
157
- return [...candidates].filter((candidate) => getCursorVariantAlias(candidate)?.targetId === targetId);
207
+ const aliases = [...candidates].filter((candidate) => getCursorVariantAlias(candidate)?.targetId === targetId);
208
+ for (const derivedId of Object.values(derivedCursorVariantIds(model) ?? {})) {
209
+ aliases.push(derivedId);
210
+ }
211
+ return aliases;
212
+ }
213
+ function resolveDerivedCursorVariant(provider, modelId, modelSource) {
214
+ const parsed = parseCursorVariantId(modelId);
215
+ if (parsed.fast || parsed.level === undefined || parsed.baseId === "")
216
+ return undefined;
217
+ const targetId = parsed.thinking === true ? `${parsed.baseId}-thinking` : parsed.baseId;
218
+ const model = modelSource.getModel(provider, targetId);
219
+ const match = model === undefined ? undefined : derivedCursorVariantMatch(model, modelId);
220
+ if (model === undefined || match === undefined)
221
+ return undefined;
222
+ return derivedResolution(model, match);
158
223
  }
159
224
  export function resolveStoredModelReference(provider, modelId, modelSource) {
160
225
  if (CURSOR_PROVIDER_IDS.has(provider)) {
@@ -166,6 +231,14 @@ export function resolveStoredModelReference(provider, modelId, modelSource) {
166
231
  return { model, thinkingLevel: thinkingSelection?.level, thinkingSelection };
167
232
  }
168
233
  }
234
+ else {
235
+ const direct = modelSource.getModel(provider, modelId);
236
+ if (direct)
237
+ return { model: direct };
238
+ const derived = resolveDerivedCursorVariant(provider, modelId, modelSource);
239
+ if (derived)
240
+ return derived;
241
+ }
169
242
  }
170
243
  const direct = modelSource.getModel(provider, modelId);
171
244
  return direct ? { model: direct } : undefined;
@@ -361,7 +434,7 @@ export function resolveModelScopeFromModels(patterns, models) {
361
434
  if (!matches(model.provider, aliasId))
362
435
  continue;
363
436
  const projection = projections.get(id) ?? { model, aliases: [] };
364
- projection.aliases.push({ id: aliasId, selection: legacySelection(aliasId) });
437
+ projection.aliases.push({ id: aliasId, selection: cursorLegacySelection(model, aliasId) });
365
438
  projections.set(id, projection);
366
439
  }
367
440
  }