@xiaoso/dsh-tool-plus 0.1.0-beta.2 → 0.1.0-beta.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 (235) hide show
  1. package/README.en.md +122 -0
  2. package/README.md +3 -2
  3. package/THIRD_PARTY_NOTICES.md +4 -35
  4. package/lib/abort-B7izMMna.mjs +51 -0
  5. package/lib/abort-D1_Z5Ut5.mjs +51 -0
  6. package/lib/abort-dIkZBV7Q.mjs +51 -0
  7. package/lib/amazon-bedrock-B0nxT06F.mjs +917 -0
  8. package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
  9. package/lib/amazon-bedrock-WQhvjHYu.mjs +917 -0
  10. package/lib/anthropic-BWsZFzU8.mjs +262 -0
  11. package/lib/anthropic-CJCauvYz.mjs +3115 -0
  12. package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
  13. package/lib/anthropic-CZghe_9U.mjs +3115 -0
  14. package/lib/anthropic-sCMH7JID.mjs +262 -0
  15. package/lib/anthropic-tTntD8BD.mjs +262 -0
  16. package/lib/api-key-login-BzqNdM2y.mjs +157 -0
  17. package/lib/api-key-login-CWVwvHT1.mjs +157 -0
  18. package/lib/api-key-login-CpzSezsi.mjs +157 -0
  19. package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
  20. package/lib/aws-credentials-CXryMobh.mjs +867 -0
  21. package/lib/aws-credentials-ChG79ey-.mjs +867 -0
  22. package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
  23. package/lib/azure-openai-responses-Cgmc-rbL.mjs +274 -0
  24. package/lib/azure-openai-responses-DuukbD0F.mjs +274 -0
  25. package/lib/bun-shim.mjs +252 -12
  26. package/lib/bundled-references-CSuBco5p.mjs +55 -0
  27. package/lib/bundled-references-Cavaffah.mjs +55 -0
  28. package/lib/bundled-references-sLN0YdXU.mjs +55 -0
  29. package/lib/callback-server-BEFNf-jf.mjs +398 -0
  30. package/lib/callback-server-CQ5Jo8F-.mjs +398 -0
  31. package/lib/callback-server-DDSrZ6l_.mjs +398 -0
  32. package/lib/client.js +111 -41
  33. package/lib/cursor-B3zg7EHj.mjs +273 -0
  34. package/lib/cursor-B6TUEmgP.mjs +135 -0
  35. package/lib/cursor-BIQfBC6V.mjs +135 -0
  36. package/lib/cursor-D8gvtTL3.mjs +135 -0
  37. package/lib/cursor-DNk6eXDd.mjs +5470 -0
  38. package/lib/cursor-DkSX2h3H.mjs +5441 -0
  39. package/lib/cursor-MjSm74IJ.mjs +273 -0
  40. package/lib/cursor-aJrXeYCb.mjs +273 -0
  41. package/lib/cursor-mJQwUKXK.mjs +5441 -0
  42. package/lib/device-code-DBo3B5nh.mjs +51 -0
  43. package/lib/device-code-DIb0FU-H.mjs +51 -0
  44. package/lib/device-code-OI_tQcmc.mjs +51 -0
  45. package/lib/devin-BHZZyMhO.mjs +95 -0
  46. package/lib/devin-BK7DHeca.mjs +114 -0
  47. package/lib/devin-CfMp3cXS.mjs +95 -0
  48. package/lib/devin-CldyPD8K.mjs +95 -0
  49. package/lib/devin-CzRpTUOA.mjs +114 -0
  50. package/lib/devin-D9zR5B_R.mjs +542 -0
  51. package/lib/devin-DXOeNyU7.mjs +542 -0
  52. package/lib/devin-Q1yem3lp.mjs +114 -0
  53. package/lib/devin-vNZTNUON.mjs +542 -0
  54. package/lib/error-B3bevhrs.mjs +1449 -0
  55. package/lib/error-Dd8DIqs-.mjs +1449 -0
  56. package/lib/error-yCSG0mGC.mjs +1449 -0
  57. package/lib/event-stream-BDPi64mK.mjs +151 -0
  58. package/lib/event-stream-BbFZJy-z.mjs +151 -0
  59. package/lib/event-stream-loUa0s1T.mjs +151 -0
  60. package/lib/fs-promises-shim-Bx0fpxuk.mjs +57 -0
  61. package/lib/github-copilot-4GaMtQmg.mjs +208 -0
  62. package/lib/github-copilot-B1yiyVRh.mjs +104 -0
  63. package/lib/github-copilot-B2HGSIJK.mjs +104 -0
  64. package/lib/github-copilot-BWT3eAOF.mjs +208 -0
  65. package/lib/github-copilot-CYkjeTi3.mjs +208 -0
  66. package/lib/github-copilot-jscUZ8Hf.mjs +104 -0
  67. package/lib/gitlab-duo-CM7Ref1H.mjs +155 -0
  68. package/lib/gitlab-duo-akICyfeD.mjs +155 -0
  69. package/lib/gitlab-duo-gubO4FNw.mjs +155 -0
  70. package/lib/gitlab-duo-workflow-BGAF6JDw.mjs +91 -0
  71. package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
  72. package/lib/gitlab-duo-workflow-D78tdn8E.mjs +91 -0
  73. package/lib/google-BS4T25Pn.mjs +30 -0
  74. package/lib/google-TFe-7-of.mjs +30 -0
  75. package/lib/google-antigravity-DGmwC2KV.mjs +198 -0
  76. package/lib/google-antigravity-DNYhgTpA.mjs +198 -0
  77. package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
  78. package/lib/google-auth-B6gjsZvg.mjs +232 -0
  79. package/lib/google-auth-De7_s3eo.mjs +232 -0
  80. package/lib/google-auth-DhqpOYrX.mjs +232 -0
  81. package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
  82. package/lib/google-gemini-cli-CWu8HvXW.mjs +211 -0
  83. package/lib/google-gemini-cli-Cb97bzQc.mjs +850 -0
  84. package/lib/google-gemini-cli-Cqds_Q5T.mjs +850 -0
  85. package/lib/google-gemini-cli-Dsztq0N5.mjs +211 -0
  86. package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
  87. package/lib/google-oauth-shared-CuEHaDDj.mjs +147 -0
  88. package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
  89. package/lib/google-oauth-shared-yqlyqPPC.mjs +147 -0
  90. package/lib/google-shared-CgKmmdO3.mjs +760 -0
  91. package/lib/google-shared-Dr-VG-ap.mjs +760 -0
  92. package/lib/google-shared-DzhCb9b0.mjs +760 -0
  93. package/lib/google-vertex-BDN2tLaD.mjs +99 -0
  94. package/lib/google-vertex-DopVOQOG.mjs +99 -0
  95. package/lib/google-vertex-kscbkyRb.mjs +99 -0
  96. package/lib/google-zyDOG9x7.mjs +30 -0
  97. package/lib/identity-Da1GPU9a.mjs +219 -0
  98. package/lib/identity-DnB63pS7.mjs +219 -0
  99. package/lib/identity-xRP7_eSR.mjs +219 -0
  100. package/lib/idle-iterator-Baoyn3Hp.mjs +366 -0
  101. package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
  102. package/lib/idle-iterator-DUjKQEGT.mjs +366 -0
  103. package/lib/index.mjs +4608 -3935
  104. package/lib/kimi--wUOWER5.mjs +236 -0
  105. package/lib/kimi-DMVI-zrZ.mjs +236 -0
  106. package/lib/kimi-Dh0pv3WZ.mjs +236 -0
  107. package/lib/markit-BL3cH47U.mjs +1417 -0
  108. package/lib/markit-BNiNY6SE.mjs +1417 -0
  109. package/lib/markit-M0jhziqU.mjs +1417 -0
  110. package/lib/minimax-code-BK-3eBbz.mjs +53 -0
  111. package/lib/minimax-code-DCbuA6Yk.mjs +53 -0
  112. package/lib/minimax-code-Uq8Qu9LW.mjs +53 -0
  113. package/lib/models-CfT4coYT.mjs +104660 -0
  114. package/lib/models-D_XnT6ay.mjs +104660 -0
  115. package/lib/models-SGASygJ3.mjs +104660 -0
  116. package/lib/ollama-BQMGPxtV.mjs +589 -0
  117. package/lib/ollama-DPzBmq89.mjs +589 -0
  118. package/lib/ollama-DoBz5SFm.mjs +589 -0
  119. package/lib/openai-codex-Bi-4S4PX.mjs +255 -0
  120. package/lib/openai-codex-CQL_kvYL.mjs +255 -0
  121. package/lib/openai-codex-Ch8CkT3p.mjs +255 -0
  122. package/lib/openai-codex-responses-CvxL_FMF.mjs +3144 -0
  123. package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
  124. package/lib/openai-codex-responses-pejZgdZo.mjs +3144 -0
  125. package/lib/openai-completions-CF8IyNtP.mjs +1360 -0
  126. package/lib/openai-completions-DIf361kF.mjs +1360 -0
  127. package/lib/openai-completions-i8doczAk.mjs +1360 -0
  128. package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
  129. package/lib/openai-reasoning-fallback-Nj6yB2rY.mjs +286 -0
  130. package/lib/openai-reasoning-fallback-OdJREP1o.mjs +286 -0
  131. package/lib/openai-responses-BqXJInHX.mjs +867 -0
  132. package/lib/openai-responses-DTkBiiy-.mjs +867 -0
  133. package/lib/openai-responses-Db_a-U4-.mjs +867 -0
  134. package/lib/opencode-DaJjcUbf.mjs +38 -0
  135. package/lib/opencode-DhMolSoB.mjs +38 -0
  136. package/lib/opencode-Rq_Q2vAO.mjs +38 -0
  137. package/lib/perplexity-9b-RQ0mV.mjs +194 -0
  138. package/lib/perplexity-C4iLVMUj.mjs +194 -0
  139. package/lib/perplexity-Uu7Jzg5b.mjs +194 -0
  140. package/lib/proxy-DDqrmjjC.mjs +190 -0
  141. package/lib/proxy-ZtUcl6r5.mjs +190 -0
  142. package/lib/proxy-pM_NIv-H.mjs +190 -0
  143. package/lib/request-debug-HJMoJncL.mjs +183 -0
  144. package/lib/sanitize-text-CfcXzw5X.mjs +33 -0
  145. package/lib/scrapers-BkFfcPHj.mjs +9198 -0
  146. package/lib/scrapers-CL-WgdU1.mjs +9198 -0
  147. package/lib/scrapers-CVptboMs.mjs +9198 -0
  148. package/lib/scrapers-CipyKyCH.mjs +9198 -0
  149. package/lib/scrapers-DGfrYhtw.mjs +9198 -0
  150. package/lib/scrapers-DSUPYoUF.mjs +9198 -0
  151. package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
  152. package/lib/scrapers-nhQAvc8d.mjs +9198 -0
  153. package/lib/shell-snapshot-fn-env.sh +67 -43
  154. package/lib/src-BgpusnsB.mjs +5076 -0
  155. package/lib/src-DTid0g4K.mjs +5001 -0
  156. package/lib/src-lDmkSRbm.mjs +5006 -0
  157. package/lib/stream-BlldLkVq.mjs +10236 -0
  158. package/lib/stream-CRtexYLe.mjs +10236 -0
  159. package/lib/stream-C_RAoxJC.mjs +10236 -0
  160. package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
  161. package/lib/stream-markup-healing-DMsxBx1L.mjs +491 -0
  162. package/lib/stream-markup-healing-KMkiAA00.mjs +491 -0
  163. package/lib/turndown-DN7ByzEI.mjs +667 -0
  164. package/lib/types/client/locales.d.ts +1 -1
  165. package/lib/types/config/fields.d.ts +1 -1
  166. package/lib/types/config/settings.d.ts +25 -3
  167. package/lib/types/config/truncate.d.ts +9 -5
  168. package/lib/types/tools/bash/background.d.ts +1 -1
  169. package/lib/types/tools/bash/bash-executor.d.ts +4 -0
  170. package/lib/types/tools/bash/bash-interceptor.d.ts +10 -8
  171. package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
  172. package/lib/types/tools/bash/non-interactive-env.d.ts +2 -0
  173. package/lib/types/tools/bash/render.d.ts +4 -3
  174. package/lib/types/tools/bash/sanitize-text.d.ts +5 -0
  175. package/lib/types/tools/bash/shell-snapshot.d.ts +4 -1
  176. package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
  177. package/lib/types/tools/bash/streaming-output.d.ts +12 -212
  178. package/lib/types/tools/bash/which.d.ts +20 -0
  179. package/lib/types/tools/bash/windows-shell.d.ts +31 -0
  180. package/lib/types/tools/edit/adapter/index.d.ts +25 -3
  181. package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +7 -17
  182. package/lib/types/tools/glob/adapter/index.d.ts +27 -1
  183. package/lib/types/tools/grep/adapter/index.d.ts +29 -1
  184. package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
  185. package/lib/types/tools/omp/edit/hashline/noop-loop-guard.d.ts +3 -1
  186. package/lib/types/tools/omp/sdk.d.ts +6 -0
  187. package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
  188. package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
  189. package/lib/types/tools/omp/tools/read.d.ts +2 -8
  190. package/lib/types/tools/omp/tools/write.d.ts +4 -4
  191. package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
  192. package/lib/types/tools/read/adapter/index.d.ts +4 -1
  193. package/lib/types/tools/read-image/index.d.ts +4 -0
  194. package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -4
  195. package/lib/types/tools/shared/bun-shim.d.ts +39 -3
  196. package/lib/types/tools/shared/fs-promises-shim.d.ts +3 -1
  197. package/lib/types/tools/shared/image-bridge.d.ts +98 -0
  198. package/lib/types/tools/shared/omp-prompt.d.ts +17 -9
  199. package/lib/types/tools/shared/session-state.d.ts +9 -3
  200. package/lib/utils-2Wq2eATG.mjs +8119 -0
  201. package/lib/utils-BnX8O3vi.mjs +12303 -0
  202. package/lib/utils-Bw139LTz.mjs +8119 -0
  203. package/lib/utils-CE8N8P4Q.mjs +12315 -0
  204. package/lib/utils-CZw4tVZQ.mjs +12315 -0
  205. package/lib/utils-C_MrQ_0z.mjs +12301 -0
  206. package/lib/utils-CiGN7OHR.mjs +12315 -0
  207. package/lib/utils-Cp76gCyk.mjs +8119 -0
  208. package/lib/utils-D0GRDgAr.mjs +12315 -0
  209. package/lib/utils-D0Z1fyoO.mjs +12299 -0
  210. package/lib/utils-D2YknRk4.mjs +51 -0
  211. package/lib/utils-DppGHXQB.mjs +51 -0
  212. package/lib/utils-DzXZDfYc.mjs +51 -0
  213. package/lib/utils-W8WdSBpX.mjs +12315 -0
  214. package/lib/vision-guard-01qSwFpf.mjs +92 -0
  215. package/lib/vision-guard-BDD4OrKo.mjs +92 -0
  216. package/lib/vision-guard-DzZGaOga.mjs +92 -0
  217. package/lib/wafer-CgtPHerf.mjs +17 -0
  218. package/lib/wafer-DRU0EjZX.mjs +17 -0
  219. package/lib/wafer-cBtrn6q9.mjs +17 -0
  220. package/lib/xai-oauth-Buk8XVvM.mjs +446 -0
  221. package/lib/xai-oauth-CMal8l1O.mjs +446 -0
  222. package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
  223. package/lib/xiaomi-CZgwvX2G.mjs +157 -0
  224. package/lib/xiaomi-D2qT5cAC.mjs +157 -0
  225. package/lib/xiaomi-Dd87KSg5.mjs +157 -0
  226. package/lib/zai-7DWMkEqM.mjs +203 -0
  227. package/lib/zai-C59YnomG.mjs +203 -0
  228. package/lib/zai-CFeOt-53.mjs +203 -0
  229. package/lib/zip-Cg9ANN_U.mjs +1316 -0
  230. package/lib/zip-D36ZKsP8.mjs +1316 -0
  231. package/lib/zip-D6QXpvaJ.mjs +1316 -0
  232. package/package.json +14 -10
  233. package/presets/package.json +1 -1
  234. package/presets/tool-plus-ptc/preset.yml +1 -1
  235. package/presets/tool-plus-standard/preset.yml +1 -1
@@ -1,20 +1,10 @@
1
- import { type Settings } from "../../../omp/config/settings.ts";
2
1
  /**
3
- * Check if a file is auto-generated by examining its content.
4
- * Throws ToolError if the file appears to be auto-generated.
2
+ * A-3 合并后的纯转发层(second-impl-audit.md A-3)。
5
3
  *
6
- * @param absolutePath - Absolute path to the file
7
- * @param displayPath - Path to show in error messages (relative or as provided)
8
- * @param activeSettings - Session settings; falls back to global settings or the schema default
4
+ * 唯一实现在 `src/tools/omp/tools/auto-generated-guard.ts`(OMP refs
5
+ * packages/coding-agent/src/tools/auto-generated-guard.ts 的逐字移植,
6
+ * 含 T17-1 Windows basename 修复)。本文件不再持有任何守卫逻辑,仅为
7
+ * 既有 import 路径(omp/edit/hashline/filesystem.ts 等历史引用与单测)
8
+ * 保留转发。
9
9
  */
10
- export declare function assertEditableFile(absolutePath: string, displayPath?: string, activeSettings?: Settings): Promise<void>;
11
- /**
12
- * Check if file content is auto-generated.
13
- * Uses only the first CHECK_BYTE_COUNT characters of the content.
14
- * Throws ToolError if the content appears to be auto-generated.
15
- *
16
- * @param content - File content to check (can be full content or prefix)
17
- * @param displayPath - Path to show in error messages
18
- * @param activeSettings - Session settings; falls back to global settings or the schema default
19
- */
20
- export declare function assertEditableFileContent(content: string, displayPath: string, activeSettings?: Settings): void;
10
+ export { assertEditableFile, assertEditableFileContent, } from "../../../omp/tools/auto-generated-guard.ts";
@@ -6,16 +6,42 @@
6
6
  * this adapter only:
7
7
  * - builds an OMP `ToolSession` from the DSH exec context + tool-plus config,
8
8
  * - constructs the verbatim `GlobTool` and calls its `execute`,
9
- * - converts the `AgentToolResult` back to a DSH tool result.
9
+ * - converts the `AgentToolResult` back to a DSH tool result, appending the
10
+ * OMP session-layer meta notice (`formatOutputNotice`, A-6) to the
11
+ * model-visible text.
10
12
  *
11
13
  * plan.md 拍板:glob keeps OMP's native single-param style (`path` with a
12
14
  * semicolon-delimited multi-target list). DSH `hidden`/`gitignore`/`limit`
13
15
  * are surfaced verbatim as optional parameters.
14
16
  */
15
17
  import type { Context } from '@deepseek-ai/cordis';
18
+ import type { AgentToolResult } from '@oh-my-pi/pi-agent-core';
16
19
  import type { RuntimeConfig } from '../../../config/settings.ts';
17
20
  export type { Settings } from '../../omp/config/settings.ts';
18
21
  export type { ToolSession } from '../../omp/sdk.ts';
22
+ /** DSH glob 工具输出形状(output.schema 镜像)。 */
23
+ export interface GlobToolOutput {
24
+ path: string;
25
+ text: string;
26
+ fileCount?: number;
27
+ truncated?: boolean;
28
+ }
29
+ /**
30
+ * 把 OMP AgentToolResult 转成 DSH glob 工具输出。
31
+ *
32
+ * 上游 session 层会把 `formatOutputNotice(details.meta)` 的限量/截断提示追加
33
+ * 进模型可见文本(wrapToolWithMetaNotice → appendOutputNotice,refs
34
+ * tools/output-meta.ts:586);DSH 无 session 层,适配层在此补上(A-6),
35
+ * 否则 glob 超限截断对模型静默。
36
+ */
37
+ export declare function toGlobToolResult(result: AgentToolResult<any>, args: any): GlobToolOutput;
38
+ /**
39
+ * 完整执行链路(defineTool.execute 与单测共用)。
40
+ *
41
+ * `ctx` 参数与 read 的 executeReadTool 对齐(glob 引擎不需要 image bridge /
42
+ * session state,仅占位保持签名一致)。
43
+ */
44
+ export declare function executeGlobTool(exec: any, cfg: RuntimeConfig, args: any, ctx: Context): Promise<GlobToolOutput>;
19
45
  /**
20
46
  * Register the glob tool (OMP native `path` + optional `hidden`/`gitignore`/
21
47
  * `limit` parameters).
@@ -6,15 +6,43 @@
6
6
  * this adapter only:
7
7
  * - builds an OMP `ToolSession` from the DSH exec context + tool-plus config,
8
8
  * - constructs the verbatim `GrepTool` and calls its `execute`,
9
- * - converts the `AgentToolResult` back to a DSH tool result.
9
+ * - converts the `AgentToolResult` back to a DSH tool result, appending the
10
+ * OMP session-layer meta notice (`formatOutputNotice`, A-6) to the
11
+ * model-visible text.
10
12
  *
11
13
  * Parameters follow OMP's native style (`pattern` regex + `path` with inline
12
14
  * `:N-M` selectors); the DSH tool exposes the same schema so nothing is lost.
13
15
  */
14
16
  import type { Context } from '@deepseek-ai/cordis';
17
+ import type { AgentToolResult } from '@oh-my-pi/pi-agent-core';
15
18
  import type { RuntimeConfig } from '../../../config/settings.ts';
16
19
  export type { Settings } from '../../omp/config/settings.ts';
17
20
  export type { ToolSession } from '../../omp/sdk.ts';
21
+ /** DSH grep 工具输出形状(output.schema 镜像)。 */
22
+ export interface GrepToolOutput {
23
+ text: string;
24
+ matchCount?: number;
25
+ fileCount?: number;
26
+ files?: string[];
27
+ scopePath?: string;
28
+ truncated?: boolean;
29
+ }
30
+ /**
31
+ * 把 OMP AgentToolResult 转成 DSH grep 工具输出。
32
+ *
33
+ * 上游 session 层会把 `formatOutputNotice(details.meta)` 的限量/截断提示追加
34
+ * 进模型可见文本(wrapToolWithMetaNotice → appendOutputNotice,refs
35
+ * tools/output-meta.ts:586);DSH 无 session 层,适配层在此补上(A-6),
36
+ * 否则 grep 的列宽截断/限量对模型静默。
37
+ */
38
+ export declare function toGrepToolResult(result: AgentToolResult<any>): GrepToolOutput;
39
+ /**
40
+ * 完整执行链路(defineTool.execute 与单测共用)。
41
+ *
42
+ * `ctx` 参数与 read 的 executeReadTool 对齐(grep 引擎不需要 image bridge /
43
+ * session state,仅占位保持签名一致)。
44
+ */
45
+ export declare function executeGrepTool(exec: any, cfg: RuntimeConfig, args: any, ctx: Context): Promise<GrepToolOutput>;
18
46
  /**
19
47
  * Register the grep tool (OMP-native `pattern` + `path` parameters; the `path`
20
48
  * accepts an inline `:N-M` selector and may be a semicolon-delimited list).
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Edit dispatch layer — path resolution + multi-entry/multi-file aggregation.
3
+ *
4
+ * Ported verbatim from upstream `packages/coding-agent/src/edit/index.ts`
5
+ * (refs/oh-my-pi, 17.3.5): `resolveEditPath` (:77-93), `executeApplyPatchPerFile`
6
+ * (:139-256) and `executeSinglePathEntries` (:258-365). Algorithm and user-facing
7
+ * copy are byte-for-byte upstream; only the import surface was redirected to the
8
+ * DSH-resident modules and the LSP-only surface was cut, per the established
9
+ * omp/ adaptation conventions:
10
+ * - `renderer` → `./details` (TUI renderer cut, plan.md 拍板#17): the
11
+ * `EditToolDetails` / `EditToolPerFileResult` shapes live in `./details.ts`;
12
+ * the upstream per-file `diagnostics` field went with the LSP layer.
13
+ * - `resolvePlanPath` → DSH adapter shim (`edit/adapter/tools/plan-mode-guard`,
14
+ * verbatim resolution minus local:// schemes) — same redirection the local
15
+ * engines (modes/replace.ts, modes/patch.ts) already use.
16
+ * - `LspBatchRequest` / `flushLspWritethroughBatch` → local type + no-op below.
17
+ * DSH never constructs an outer batch request, so every `batchRequest` inside
18
+ * the aggregators resolves to `undefined` and the flush branches stay
19
+ * unreachable; the flow is kept verbatim so this file stays diffable
20
+ * against refs.
21
+ */
22
+ import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
23
+ import type { ToolSession } from "../tools/index.ts";
24
+ import type { EditToolDetails } from "./details";
25
+ /**
26
+ * LSP write-batch handle (upstream `tools/render-utils.ts`, surfaced through the
27
+ * edit renderer). Shape verbatim; DSH cuts the LSP layer (plan.md 拍板#5), so no
28
+ * caller ever constructs one — see {@link flushLspWritethroughBatch}.
29
+ */
30
+ export interface LspBatchRequest {
31
+ id: string;
32
+ flush: boolean;
33
+ }
34
+ export declare function resolveEditPath(session: ToolSession, authoredPath: string, options: {
35
+ mustExist: boolean;
36
+ signal?: AbortSignal;
37
+ }): Promise<string>;
38
+ /** Run apply_patch file operations and aggregate their multi-file result. */
39
+ export declare function executeApplyPatchPerFile(fileEntries: {
40
+ path: string;
41
+ run: (batchRequest: LspBatchRequest | undefined) => Promise<AgentToolResult<EditToolDetails>>;
42
+ }[], outerBatchRequest: LspBatchRequest | undefined, cwd: string, signal: AbortSignal | undefined, onUpdate?: (partialResult: AgentToolResult<EditToolDetails>) => void): Promise<AgentToolResult<EditToolDetails>>;
43
+ export declare function executeSinglePathEntries(path: string, runs: ((batchRequest: LspBatchRequest | undefined) => Promise<AgentToolResult<EditToolDetails>>)[], outerBatchRequest: LspBatchRequest | undefined, onUpdate: ((partialResult: AgentToolResult<EditToolDetails>) => void) | undefined, cwd: string, signal: AbortSignal | undefined): Promise<AgentToolResult<EditToolDetails>>;
@@ -65,8 +65,10 @@ export declare function recordNoopEdit(session: NoopLoopGuardOwner, canonicalPat
65
65
  */
66
66
  export declare function resetNoopEdit(session: NoopLoopGuardOwner, canonicalPath: string): void;
67
67
  /**
68
- * Stable hash of the raw patch input. Bun's `Bun.hash` is xxHash64 — fast,
68
+ * Stable hash of the raw patch input. Bun's `Bun.hash` is wyhash64 — fast,
69
69
  * non-cryptographic, more than adequate for "is this the same payload?".
70
+ * (xxHash64 is the separate `Bun.hash.xxHash64` namespace; the shim serves
71
+ * both — second-impl-audit.md S-3.)
70
72
  */
71
73
  export declare function hashPatchInput(input: string): string;
72
74
  export {};
@@ -39,6 +39,12 @@ export interface ToolSession {
39
39
  getActiveModelString?: () => string | undefined;
40
40
  /** Active model object (image-capability checks; optional in DSH). */
41
41
  getActiveModel?: () => Model | undefined;
42
+ /**
43
+ * DSH image bridge (拍板#22): attachment store + route vision-capability
44
+ * probe handed to the read/fetch image paths. Optional — engines degrade to
45
+ * a model-facing metadata text when absent.
46
+ */
47
+ imageBridge?: () => import('../shared/image-bridge.ts').ImageBridge | undefined;
42
48
  /** Clipboard state carried on the session (hashline clipboard). */
43
49
  editClipboard?: Record<string, unknown>;
44
50
  /** Hashline snapshot store (created lazily by the engine). */
@@ -0,0 +1,20 @@
1
+ import { type Settings } from "../config/settings.ts";
2
+ /**
3
+ * Check if a file is auto-generated by examining its content.
4
+ * Throws ToolError if the file appears to be auto-generated.
5
+ *
6
+ * @param absolutePath - Absolute path to the file
7
+ * @param displayPath - Path to show in error messages (relative or as provided)
8
+ * @param activeSettings - Session settings; falls back to global settings or the schema default
9
+ */
10
+ export declare function assertEditableFile(absolutePath: string, displayPath?: string, activeSettings?: Settings): Promise<void>;
11
+ /**
12
+ * Check if file content is auto-generated.
13
+ * Uses only the first CHECK_BYTE_COUNT characters of the content.
14
+ * Throws ToolError if the content appears to be auto-generated.
15
+ *
16
+ * @param content - File content to check (can be full content or prefix)
17
+ * @param displayPath - Path to show in error messages
18
+ * @param activeSettings - Session settings; falls back to global settings or the schema default
19
+ */
20
+ export declare function assertEditableFileContent(content: string, displayPath: string, activeSettings?: Settings): void;
@@ -49,6 +49,8 @@ export interface ReadUrlToolDetails {
49
49
  truncated: boolean;
50
50
  notes: string[];
51
51
  meta?: OutputMeta;
52
+ /** DSH (拍板#22): committed attachment facts when the URL image went through the bridge. */
53
+ image?: import("../../shared/image-bridge.ts").SavedImageRef;
52
54
  }
53
55
  interface ReadUrlEntry {
54
56
  artifactId?: string;
@@ -17,6 +17,8 @@ export interface ReadToolDetails {
17
17
  from: string;
18
18
  to: string;
19
19
  };
20
+ /** DSH image bridge (拍板#22): committed attachment facts for an image read. */
21
+ image?: import("../../shared/image-bridge.ts").SavedImageRef;
20
22
  url?: string;
21
23
  finalUrl?: string;
22
24
  contentType?: string;
@@ -63,14 +65,6 @@ export declare class ReadTool implements AgentTool<typeof readSchema, ReadToolDe
63
65
  get parameters(): typeof readSchema;
64
66
  readonly strict = true;
65
67
  constructor(session: ToolSession);
66
- /**
67
- * Re-evaluate the effective inspect_image state; it can flip when the model
68
- * or the `/vision` override changes after this tool was constructed. Keeps
69
- * the behavior branch and the advertised description in lockstep. Called
70
- * per image read and by tool reconciliation before prompt rebuilds (which
71
- * passes the post-change availability as `availableOverride`).
72
- */
73
- syncInspectImageState(availableOverride?: boolean): boolean;
74
68
  execute(_toolCallId: string, params: ReadParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<ReadToolDetails>, _toolContext?: AgentToolContext): Promise<AgentToolResult<ReadToolDetails>>;
75
69
  }
76
70
  export {};
@@ -3,11 +3,11 @@ import type { ToolSession } from "../../omp/sdk.ts";
3
3
  import type { OutputMeta } from "../../omp/tools/output-meta.ts";
4
4
  import { type XdevDispatch } from "../../omp/tools/resolve.ts";
5
5
  declare const writeSchema: import("@oh-my-pi/omptype").FluentType<{
6
- content: string;
7
6
  path: string;
8
- }, {
9
7
  content: string;
8
+ }, {
10
9
  path: string;
10
+ content: string;
11
11
  }>;
12
12
  export type WriteToolInput = typeof writeSchema.infer;
13
13
  /** Details returned by the write tool for TUI rendering */
@@ -36,11 +36,11 @@ export declare class WriteTool implements AgentTool<typeof writeSchema, WriteToo
36
36
  readonly label = "Write";
37
37
  readonly description: string;
38
38
  readonly parameters: import("@oh-my-pi/omptype").FluentType<{
39
- content: string;
40
39
  path: string;
41
- }, {
42
40
  content: string;
41
+ }, {
43
42
  path: string;
43
+ content: string;
44
44
  }>;
45
45
  readonly strict = true;
46
46
  readonly concurrency = "exclusive";
@@ -1,7 +1,5 @@
1
- import type { Context, ImageContent, Message, Model } from "@oh-my-pi/pi-ai";
1
+ import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
2
2
  import { type ImageResizeOptions } from "./image-resize";
3
- export declare const MAX_IMAGE_INPUT_BYTES: number;
4
- export declare const SUPPORTED_INPUT_IMAGE_MIME_TYPES: Set<string>;
5
3
  /**
6
4
  * Ollama and its local-backend family decode image input through llama.cpp /
7
5
  * `stb_image`, which is compiled without WebP support, so a WebP upload fails
@@ -15,6 +13,8 @@ export declare function modelLacksWebpSupport(model: Pick<Model, "provider" | "a
15
13
  * into {@link ImageResizeOptions.excludeWebP}.
16
14
  */
17
15
  export declare function webpExclusionForModel(model: Pick<Model, "provider" | "api"> | undefined): true | undefined;
16
+ export declare const MAX_IMAGE_INPUT_BYTES: number;
17
+ export declare const SUPPORTED_INPUT_IMAGE_MIME_TYPES: Set<string>;
18
18
  export interface LoadImageInputOptions {
19
19
  path: string;
20
20
  cwd: string;
@@ -24,16 +24,13 @@ export interface LoadImageInputOptions {
24
24
  detectedMimeType?: string;
25
25
  /** Force non-WebP output (e.g. for Ollama). Leave unset to honor `OMP_NO_WEBP`. */
26
26
  excludeWebP?: boolean;
27
- }
28
- /** Options for loading an in-memory chat image attachment as a vision-model input. */
29
- export interface LoadImageAttachmentInputOptions {
30
- image: ImageContent;
31
- label: string;
32
- uri: string;
33
- autoResize: boolean;
34
- maxBytes?: number;
35
- /** Force non-WebP output (e.g. for Ollama). Leave unset to honor `OMP_NO_WEBP`. */
36
- excludeWebP?: boolean;
27
+ /**
28
+ * DSH extension (拍板#22 config expansion): resize-knob passthrough onto
29
+ * {@link resizeImage}. Upstream never passes these — it relies on the
30
+ * hardcoded 1568px/500KB/200px/quality-80 defaults; the tool-plus config
31
+ * panel wires user-tunable values through here. Unset = upstream behavior.
32
+ */
33
+ resize?: ImageResizeOptions;
37
34
  }
38
35
  export interface LoadedImageInput {
39
36
  resolvedPath: string;
@@ -51,27 +48,4 @@ export declare class ImageInputTooLargeError extends Error {
51
48
  /** Converts an image to PNG, rejecting when the runtime cannot decode or encode it. */
52
49
  export declare function convertImageToPng(image: ImageContent): Promise<ImageContent>;
53
50
  export declare function ensureSupportedImageInput(image: ImageContent): Promise<ImageContent | null>;
54
- export interface NormalizeModelContextImagesOptions {
55
- /** Model the images are bound for; used to derive encoder constraints (WebP exclusion for Ollama). */
56
- model?: Model;
57
- resize?: ImageResizeOptions;
58
- }
59
- /**
60
- * Normalize image blocks before they enter agent/model context. This keeps
61
- * provider request construction from having to resize an unbounded batch of
62
- * large images on the streaming hot path. Images are processed sequentially on
63
- * purpose: `resizeImage` may fan out multiple encoders for one image, so the
64
- * outer image batch must stay bounded.
65
- */
66
- export declare function normalizeModelContextImages(images: ImageContent[] | undefined, options?: NormalizeModelContextImagesOptions): Promise<ImageContent[] | undefined>;
67
- /**
68
- * Rewrites historical/resumed WebP blocks in the ephemeral provider request.
69
- * Persisted session messages remain untouched, while STB-backed local servers
70
- * never receive a format they cannot decode.
71
- */
72
- export declare function normalizeModelContextMessages(messages: Message[], model: Model | undefined): Promise<Message[]>;
73
- /** Normalizes historical image blocks in an ephemeral provider request. */
74
- export declare function normalizeProviderContextImagesForModel(context: Context, model: Model): Promise<Context>;
75
51
  export declare function loadImageInput(options: LoadImageInputOptions): Promise<LoadedImageInput | null>;
76
- /** Loads a chat attachment image through the same size and encoder policy as file-backed image inputs. */
77
- export declare function loadImageAttachmentInput(options: LoadImageAttachmentInputOptions): Promise<LoadedImageInput | null>;
@@ -14,6 +14,7 @@
14
14
  import type { Context } from '@deepseek-ai/cordis';
15
15
  import type { AgentToolResult } from '@oh-my-pi/pi-agent-core';
16
16
  import type { RuntimeConfig } from '../../../config/settings.ts';
17
+ import type { SavedImageRef } from '../../shared/image-bridge.ts';
17
18
  export type { Settings } from '../../omp/config/settings.ts';
18
19
  export type { ToolSession } from '../../omp/sdk.ts';
19
20
  /** DSH read 工具输出形状(output.schema 镜像)。 */
@@ -24,6 +25,8 @@ export interface ReadToolOutput {
24
25
  notice?: string;
25
26
  totalLines?: number;
26
27
  truncated?: boolean;
28
+ /** 拍板#22:图片读取的附件提交结果(信封文本已并入 text,此字段供 UI/审计)。 */
29
+ image?: SavedImageRef;
27
30
  }
28
31
  /**
29
32
  * 把 OMP AgentToolResult 转成 DSH read 工具输出。
@@ -35,7 +38,7 @@ export declare function toReadToolResult(result: AgentToolResult<any>, args: any
35
38
  /** render:模型可见文本 = 工具文本 + session 层提示(OMP messages.ts 语义)。 */
36
39
  export declare function renderReadOutput(value: ReadToolOutput): string;
37
40
  /** 完整执行链路(defineTool.execute 与单测共用)。 */
38
- export declare function executeReadTool(exec: any, cfg: RuntimeConfig, args: any): Promise<ReadToolOutput>;
41
+ export declare function executeReadTool(exec: any, cfg: RuntimeConfig, args: any, ctx: Context): Promise<ReadToolOutput>;
39
42
  /**
40
43
  * Register the read tool (OMP native `path` + inline selector parameter,
41
44
  * plan.md 拍板#2).
@@ -17,6 +17,10 @@ export interface ImageReadValue {
17
17
  width: number;
18
18
  height: number;
19
19
  name?: string;
20
+ originalDimensions?: {
21
+ width: number;
22
+ height: number;
23
+ };
20
24
  };
21
25
  }
22
26
  export declare function imageMediaTypeForPath(filePath: string): ImageMediaType | undefined;
@@ -1,4 +1,16 @@
1
- /** Update whether auto-generated files are blocked (`edit.blockAutoGenerated`). */
2
- export declare function setBlockAutoGenerated(enabled: boolean): void;
3
- export declare function assertEditableFile(absolutePath: string, displayPath?: string, _activeSettings?: unknown): Promise<void>;
4
- export declare function assertEditableFileContent(content: string, displayPath: string): void;
1
+ /**
2
+ * A-3 合并后的兼容转发层(second-impl-audit.md A-3)。
3
+ *
4
+ * 唯一实现在 `../omp/tools/auto-generated-guard.ts`(OMP 逐字移植 + T17-1
5
+ * Windows basename 修复)。原「简化重写」已删除:SimpleLRU、手搓 peekFile、
6
+ * 截断的三步整改文案、推送开关全部移除;开关语义改为 settings-pull
7
+ * (`edit.blockAutoGenerated`,三级回退 activeSettings → 全局 settings →
8
+ * schema 默认 true,refs settings-schema.ts:3230)。
9
+ */
10
+ export { assertEditableFile, assertEditableFileContent, } from '../omp/tools/auto-generated-guard.ts';
11
+ /**
12
+ * @deprecated 兼容旧推送式 API:守卫已改为 settings-pull(调用方传
13
+ * session.settings,未传时回退全局/默认),推送开关不再参与行为判定。
14
+ * 保留为 no-op 以兼容既有 import;src/index.ts 的调用点已删除。
15
+ */
16
+ export declare function setBlockAutoGenerated(_enabled: boolean): void;
@@ -31,6 +31,8 @@ export declare class BunFileSliceShim extends BunFileShim {
31
31
  text(): Promise<string>;
32
32
  bytes(): Promise<Uint8Array>;
33
33
  arrayBuffer(): Promise<ArrayBuffer>;
34
+ /** Blob semantics: stream yields only the slice window. */
35
+ stream(): ReadableStream<Uint8Array>;
34
36
  }
35
37
  export declare class FileSinkShim {
36
38
  #private;
@@ -57,13 +59,46 @@ declare class CryptoHasherShim {
57
59
  update(data: string | Uint8Array): this;
58
60
  digest(encoding: 'hex' | 'base64' | 'buffer' | string): string | Buffer;
59
61
  }
60
- declare class BunImageUnavailable {
61
- constructor();
62
+ interface ImageStep {
63
+ op: 'resize' | 'png' | 'jpeg' | 'webp' | 'rotate' | 'flip' | 'blur' | 'sharpen';
64
+ args: unknown[];
65
+ }
66
+ export declare class BunImageShim {
67
+ #private;
68
+ constructor(bytes: Uint8Array | ArrayBuffer, steps?: readonly ImageStep[]);
69
+ metadata(): Promise<{
70
+ width: number;
71
+ height: number;
72
+ format?: string;
73
+ hasAlpha?: boolean;
74
+ }>;
75
+ resize(widthOrOpts?: number | {
76
+ width?: number;
77
+ height?: number;
78
+ quality?: number;
79
+ }, height?: number): BunImageShim;
80
+ /** Bun's resize() accepts { width, height, fit } — expose fit through to sharp. */
81
+ resizeWithFit(width: number, height: number, fit: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'): BunImageShim;
82
+ png(): BunImageShim;
83
+ jpeg(opts?: {
84
+ quality?: number;
85
+ }): BunImageShim;
86
+ webp(opts?: {
87
+ quality?: number;
88
+ }): BunImageShim;
89
+ rotate(): BunImageShim;
90
+ flip(flip: boolean): BunImageShim;
91
+ blur(radius: number): BunImageShim;
92
+ sharpen(radius?: number): BunImageShim;
93
+ bytes(): Promise<Uint8Array>;
94
+ toBase64(): Promise<string>;
95
+ write(destPath: string): Promise<number>;
62
96
  }
63
97
  type ArchiveMemberContent = string | Uint8Array | Blob;
64
98
  declare function archiveWrite(destPath: string, record: Record<string, ArchiveMemberContent>, opts?: {
65
99
  compress?: 'gzip';
66
100
  }): Promise<void>;
101
+ export declare function bunStripANSI(text: string): string;
67
102
  export interface BunShimSurface {
68
103
  file(path: string): BunFileShim;
69
104
  write(path: string, data: string | Uint8Array | Blob | ArrayBuffer): Promise<void>;
@@ -76,9 +111,10 @@ export interface BunShimSurface {
76
111
  write: typeof archiveWrite;
77
112
  };
78
113
  FileSink: typeof FileSinkShim;
79
- Image: typeof BunImageUnavailable;
114
+ Image: typeof BunImageShim;
80
115
  CryptoHasher: typeof CryptoHasherShim;
81
116
  color(color: string, format?: string): string;
117
+ stripANSI(text: string): string;
82
118
  JSON: {
83
119
  parse(s: string): unknown;
84
120
  stringify(v: unknown): string;
@@ -1,5 +1,7 @@
1
1
  export * from 'fs/promises';
2
- /** Bun's `node:fs/promises` extension: `exists(path)` → `Promise<boolean>`. */
2
+ /** Bun's `node:fs/promises` extension: `exists(path)` → `Promise<boolean>`.
3
+ * Bun swallows every stat error, not just ENOENT — ENAMETOOLONG on a 60k-char
4
+ * path also yields false (probe audit-probes/S15/s15-exists4.ts). */
3
5
  export declare function exists(path: string): Promise<boolean>;
4
6
  /**
5
7
  * Augment the real `node:fs/promises` module type with Bun's `exists` so tsc
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Shared image bridge (拍板#22, 2026-08-28) — the single DSH-facing seam
3
+ * through which the OMP engines (read's restored image path, fetch's URL
4
+ * image path) turn image bytes into model-visible content.
5
+ *
6
+ * DSH's content model has no inline base64 image block: an ImageBlock is
7
+ * exactly `{ type: 'image', attachment: ImageAttachmentRef }`
8
+ * (dsh-llm types). Every image entering the model therefore MUST pass
9
+ * through the host `attachments` service (saveImage → content-addressed
10
+ * normalized master → per-request variants). This module owns:
11
+ *
12
+ * - the extension → media-type table (mirrors official dsh-tool-fs),
13
+ * - the route vision-capability probe (omp flavor: unknown passes, explicit
14
+ * non-image routes soft-refuse to a model-facing metadata text instead of
15
+ * a thrown error — 用户拍板 2026-08-28),
16
+ * - saveImage + AttachmentError → recoverable-message mapping (official
17
+ * read_image's five-branch design, verbatim wording),
18
+ * - the `<path>/<type>/<content>` envelope with originalDimensions
19
+ * coordinate-multiplier advice (official formatImageReadOutput).
20
+ *
21
+ * The OMP layer never imports cordis/dsh packages: engines call these helpers
22
+ * through `ToolSession.getAttachments` and the exec context the adapter
23
+ * hands them, keeping the omp/ copies upstream-shaped.
24
+ */
25
+ export type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';
26
+ /** Normalized outcome of one attachment-store commit (official ref shape). */
27
+ export interface SavedImageRef {
28
+ attachmentId: string;
29
+ mediaType: ImageMediaType;
30
+ bytes: number;
31
+ width: number;
32
+ height: number;
33
+ name?: string;
34
+ originalDimensions?: {
35
+ width: number;
36
+ height: number;
37
+ };
38
+ }
39
+ /** Minimal structural view of the host `attachments` service. */
40
+ export interface AttachmentsService {
41
+ imageLimits?: {
42
+ maxImageBytes?: number;
43
+ maxMessageImageBytes?: number;
44
+ maxImagePixels?: number;
45
+ maxImageDimension?: number;
46
+ mediaTypes?: readonly string[];
47
+ };
48
+ saveImage?: (input: {
49
+ data: Uint8Array;
50
+ mediaType: string;
51
+ name?: string;
52
+ }) => Promise<unknown>;
53
+ }
54
+ /** Minimal structural view of the host `llm` service. */
55
+ export interface LlmRouteService {
56
+ resolveModelInfo?: (provider: string, model: string, signal: AbortSignal) => Promise<{
57
+ inputModalities?: readonly string[];
58
+ }>;
59
+ }
60
+ /**
61
+ * Facade the DSH adapter builds over ctx.get('attachments')/ctx.get('llm')
62
+ * plus the calling route, handed to the engines via ToolSession.
63
+ */
64
+ export interface ImageBridge {
65
+ attachments: AttachmentsService | undefined;
66
+ /** 'supported' = route declares image input; 'unsupported' = declares it does not; 'unknown' = not resolvable. */
67
+ routeImageSupport: () => Promise<'supported' | 'unsupported' | 'unknown'>;
68
+ }
69
+ export declare const IMAGE_EXTENSIONS: Readonly<Record<string, ImageMediaType>>;
70
+ export declare function imageMediaTypeForExtension(ext: string): ImageMediaType | undefined;
71
+ /** Admission byte cap: min(source cap, per-message cap) — official formula. */
72
+ export declare function imageByteCap(bridge: ImageBridge, fallback?: number): number;
73
+ /** Commit bytes to the attachment store, mapping AttachmentErrors to the
74
+ * official read_image recoverable messages. `displayPath` is only used for
75
+ * message rendering. Throws Error (not AttachmentError) for model consumption. */
76
+ export declare function saveImageViaBridge(bridge: ImageBridge, input: {
77
+ data: Uint8Array;
78
+ mediaType: ImageMediaType;
79
+ name?: string;
80
+ displayPath: string;
81
+ }): Promise<SavedImageRef>;
82
+ /** Accept either the official branded ref or a plain object from a mock. */
83
+ export declare function normalizeSavedImageRef(ref: unknown): SavedImageRef;
84
+ export declare function formatImageEnvelope(displayPath: string, image: SavedImageRef): string;
85
+ /** Content blocks for one committed image: envelope text + attachment block. */
86
+ export declare function imageContentBlocks(displayPath: string, image: SavedImageRef): Array<{
87
+ type: 'text';
88
+ text: string;
89
+ } | {
90
+ type: 'image';
91
+ attachment: SavedImageRef;
92
+ }>;
93
+ export declare function formatImageUnsupportedNote(displayPath: string, metadata: {
94
+ mimeType?: string;
95
+ width?: number;
96
+ height?: number;
97
+ bytes?: number;
98
+ } | undefined, reason: string): string;
@@ -1,10 +1,15 @@
1
1
  /**
2
2
  * OMP prompt.md → DSH tool description 适配层(verbatim md 不动,适配在此)。
3
3
  *
4
- * OMP 的 prompts/tools/*.md 用 Handlebars 条件渲染(prompt.render),DSH 的
5
- * defineTool description 是静态字符串,这里提供:
6
- * - `renderOmpPrompt`:支持 `{{#if KEY}}A{{else}}B{{/if}}` 与
7
- * `{{#if KEY}}A{{/if}}` 两种条件(md 内无嵌套、无插值变量,无需完整引擎)
4
+ * OMP 的 prompts/tools/*.md 用 Handlebars 条件渲染,DSH 的 defineTool
5
+ * description 是静态字符串,这里提供:
6
+ * - `renderOmpPrompt`:完全委托 OMP 自家引擎(@oh-my-pi/pi-utils 的
7
+ * prompt.render = 结构化 Handlebars 解析 + post-render format 后处理,
8
+ * 与上游 read.ts 渲染工具描述同一条管线)。按「移植绝不允许第二套实现」
9
+ * (notebook T10-1 同类教训):自写 regex 渲染器已删除——其全文懒匹配
10
+ * 会跨条件边界吞并并在真值分支残留孤立 `{{/if}}`(2026-08-28 tools:sdk
11
+ * "malformed prompt variable" 事故根源)。strict:false → 未传变量按 falsy
12
+ * 取 else 分支;畸形模板 compile 期抛错(注册期 fail-loud)。
8
13
  * - `sanitizeOmpPrompt`:按工具剔除 DSH 不适用的 OMP 提法(内部协议
9
14
  * artifact:// ssh:// memory:// xd://、browser、scout/Task 子代理、inspect_image),
10
15
  * 全部剔除点记录在 step.md「提示词接入」节;md 源文件保持 verbatim 不变。
@@ -12,20 +17,23 @@
12
17
  export interface OmpPromptVars {
13
18
  /** read 输出是否带 [PATH#TAG] hashline 锚点头(= edit.mode === 'hashline') */
14
19
  IS_HL_MODE?: boolean;
15
- /** DSH 无 inspect_image 工具(有 read_image),恒 false → 取 else 分支 */
20
+ /** DSH 无 inspect_image 工具:read.md 图片条件句恒渲染 else 分支(引擎内部
21
+ * #renderDescription 用),DSH 面再经 sanitizeReadPrompt 改写为附件提交语义
22
+ * (拍板#22:图片经 attachments 入库,非 vision 路由降级 metadata 文本)。 */
16
23
  INSPECT_IMAGE_ENABLED?: boolean;
17
24
  /** DSH 无 OMP Task/scout 子代理,恒 false → 相关句在 sanitize 中整体剔除,无需变量 */
18
25
  scoutAvailable?: boolean;
19
26
  }
20
- /** 渲染 {{#if KEY}}A{{else}}B{{/if}} 与 {{#if KEY}}A{{/if}}(不支持嵌套)。 */
27
+ /** 渲染 {{#if KEY}}A{{else}}B{{/if}} 与 {{#if KEY}}A{{/if}}——委托 OMP 引擎
28
+ * (@oh-my-pi/pi-utils prompt.render,strict:false:未传变量按 falsy 取 else
29
+ * 分支;畸形模板 compile 期抛错,注册期 fail-loud)。保留首尾 trim 对齐
30
+ * 既有调用点行为。 */
21
31
  export declare function renderOmpPrompt(text: string, vars: OmpPromptVars): string;
22
- /** 剔除非空白/注释行——供剔除后再次 trim。 */
23
- export declare function cleanLines(text: string): string;
24
32
  /** grep.md:internal URLs 提法 + scout 句剔除。 */
25
33
  export declare function sanitizeGrepPrompt(text: string): string;
26
34
  /** glob.md:internal URL/memory:// 提法 + scout avoid 句剔除。 */
27
35
  export declare function sanitizeGlobPrompt(text: string): string;
28
- /** read.md:browser/inspect_image 提法剔除 + internal URIs 段删除({{#if}} 由 renderer 处理)。 */
36
+ /** read.md:browser 提法剔除 + 图片句改为 DSH 实际行为(拍板#22 附件提交)+ internal URIs 段删除({{#if}} 由 renderer 处理)。 */
29
37
  export declare function sanitizeReadPrompt(text: string): string;
30
38
  /** ast-edit.md:xd://resolve 预演确认协议已随内部路由删除;DSH 为预览后自动落盘(拍板#14)。 */
31
39
  export declare function sanitizeAstEditPrompt(text: string): string;