dominds 1.25.1 → 1.25.2

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 (181) hide show
  1. package/README.md +4 -3
  2. package/README.zh.md +4 -3
  3. package/dist/team.js +4 -1
  4. package/dist/tools/builtins.js +30 -0
  5. package/dist/tools/fs.d.ts +2 -0
  6. package/dist/tools/fs.js +281 -2
  7. package/dist/tools/os.d.ts +11 -0
  8. package/dist/tools/os.js +20 -9
  9. package/dist/tools/picture.d.ts +1 -0
  10. package/dist/tools/picture.js +64 -1
  11. package/dist/tools/prompts/codex_inspect_and_patch_tools/en/tools.md +5 -0
  12. package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/tools.md +5 -0
  13. package/dist/tools/prompts/fs_read/en/errors.md +6 -0
  14. package/dist/tools/prompts/fs_read/en/index.md +17 -0
  15. package/dist/tools/prompts/fs_read/en/principles.md +5 -0
  16. package/dist/tools/prompts/fs_read/en/scenarios.md +3 -0
  17. package/dist/tools/prompts/fs_read/en/tools.md +11 -0
  18. package/dist/tools/prompts/fs_read/zh/errors.md +6 -0
  19. package/dist/tools/prompts/fs_read/zh/index.md +17 -0
  20. package/dist/tools/prompts/fs_read/zh/principles.md +5 -0
  21. package/dist/tools/prompts/fs_read/zh/scenarios.md +3 -0
  22. package/dist/tools/prompts/fs_read/zh/tools.md +11 -0
  23. package/dist/tools/prompts/os/en/index.md +1 -1
  24. package/dist/tools/prompts/os/en/principles.md +1 -1
  25. package/dist/tools/prompts/os/en/scenarios.md +21 -0
  26. package/dist/tools/prompts/os/en/tools.md +6 -0
  27. package/dist/tools/prompts/os/zh/index.md +1 -1
  28. package/dist/tools/prompts/os/zh/principles.md +1 -1
  29. package/dist/tools/prompts/os/zh/scenarios.md +21 -0
  30. package/dist/tools/prompts/os/zh/tools.md +6 -0
  31. package/dist/tools/registry.d.ts +6 -0
  32. package/dist/tools/ripgrep.d.ts +5 -0
  33. package/dist/tools/ripgrep.js +482 -1
  34. package/dist/tools/txt.d.ts +34 -0
  35. package/dist/tools/txt.js +221 -1
  36. package/package.json +3 -3
  37. package/webapp/dist/assets/{_basePickBy-CG55qWp2.js → _basePickBy-CbWZ8qnS.js} +3 -3
  38. package/webapp/dist/assets/_basePickBy-CbWZ8qnS.js.map +1 -0
  39. package/webapp/dist/assets/{_baseUniq-Dd4UGB2O.js → _baseUniq-IY-Vfzx1.js} +2 -2
  40. package/webapp/dist/assets/_baseUniq-IY-Vfzx1.js.map +1 -0
  41. package/webapp/dist/assets/{arc-C2qiF4r3.js → arc--U2Vks6y.js} +2 -2
  42. package/webapp/dist/assets/arc--U2Vks6y.js.map +1 -0
  43. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DQ4Z8fy_.js → architectureDiagram-VXUJARFQ-DpryGqjy.js} +8 -26
  44. package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DpryGqjy.js.map +1 -0
  45. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CPvOuMZA.js → blockDiagram-VD42YOAC-TTufCfiE.js} +170 -187
  46. package/webapp/dist/assets/blockDiagram-VD42YOAC-TTufCfiE.js.map +1 -0
  47. package/webapp/dist/assets/{c4Diagram-IC4MRINW-DElaFpnJ.js → c4Diagram-YG6GDRKO-B4RPsw5H.js} +4 -4
  48. package/webapp/dist/assets/c4Diagram-YG6GDRKO-B4RPsw5H.js.map +1 -0
  49. package/webapp/dist/assets/{channel-BR7mZa90.js → channel-DAtGYJHZ.js} +2 -2
  50. package/webapp/dist/assets/channel-DAtGYJHZ.js.map +1 -0
  51. package/webapp/dist/assets/{chunk-4BX2VUAB-DTmXCBYX.js → chunk-4BX2VUAB-JtO__vAF.js} +2 -2
  52. package/webapp/dist/assets/chunk-4BX2VUAB-JtO__vAF.js.map +1 -0
  53. package/webapp/dist/assets/{chunk-55IACEB6-DeBB4aJ4.js → chunk-55IACEB6-JMRC8yG1.js} +2 -2
  54. package/webapp/dist/assets/chunk-55IACEB6-JMRC8yG1.js.map +1 -0
  55. package/webapp/dist/assets/{chunk-WL4C6EOR-V3Fq1ULq.js → chunk-B4BG7PRW-BDIpf8Iz.js} +121 -171
  56. package/webapp/dist/assets/chunk-B4BG7PRW-BDIpf8Iz.js.map +1 -0
  57. package/webapp/dist/assets/{chunk-NQ4KR5QH-DRcsqoac.js → chunk-DI55MBZ5-j9B4rifK.js} +7 -9
  58. package/webapp/dist/assets/chunk-DI55MBZ5-j9B4rifK.js.map +1 -0
  59. package/webapp/dist/assets/{chunk-FMBD7UC4-CXpgeev4.js → chunk-FMBD7UC4-DFXKLjHC.js} +2 -2
  60. package/webapp/dist/assets/chunk-FMBD7UC4-DFXKLjHC.js.map +1 -0
  61. package/webapp/dist/assets/{chunk-KX2RTZJC-DWG_wpHB.js → chunk-QN33PNHL-BKzkeJ-b.js} +2 -2
  62. package/webapp/dist/assets/chunk-QN33PNHL-BKzkeJ-b.js.map +1 -0
  63. package/webapp/dist/assets/{chunk-QZHKN3VN-B9GPAJ2s.js → chunk-QZHKN3VN-DiZd3UNl.js} +2 -2
  64. package/webapp/dist/assets/chunk-QZHKN3VN-DiZd3UNl.js.map +1 -0
  65. package/webapp/dist/assets/{chunk-JSJVCQXG-DWfckfhO.js → chunk-TZMSLE5B-BaE4C244.js} +6 -14
  66. package/webapp/dist/assets/chunk-TZMSLE5B-BaE4C244.js.map +1 -0
  67. package/webapp/dist/assets/{classDiagram-VBA2DB6C-DspG486Z.js → classDiagram-2ON5EDUG-CNF8ZohD.js} +6 -7
  68. package/webapp/dist/assets/classDiagram-2ON5EDUG-CNF8ZohD.js.map +1 -0
  69. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-DspG486Z.js → classDiagram-v2-WZHVMYZB-CNF8ZohD.js} +6 -7
  70. package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CNF8ZohD.js.map +1 -0
  71. package/webapp/dist/assets/{clone-M8ztABN5.js → clone-Nq0Ko0Gv.js} +2 -2
  72. package/webapp/dist/assets/clone-Nq0Ko0Gv.js.map +1 -0
  73. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-DZihobe3.js → cose-bilkent-S5V4N54A-uHPLSeKv.js} +2 -2
  74. package/webapp/dist/assets/cose-bilkent-S5V4N54A-uHPLSeKv.js.map +1 -0
  75. package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
  76. package/webapp/dist/assets/{dagre-KLK3FWXG-DBLWy3vi.js → dagre-6UL2VRFP-C1awWpU3.js} +7 -7
  77. package/webapp/dist/assets/dagre-6UL2VRFP-C1awWpU3.js.map +1 -0
  78. package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
  79. package/webapp/dist/assets/{diagram-E7M64L7V-D7IrPWaY.js → diagram-PSM6KHXK-Bf69p76M.js} +10 -10
  80. package/webapp/dist/assets/diagram-PSM6KHXK-Bf69p76M.js.map +1 -0
  81. package/webapp/dist/assets/{diagram-IFDJBPK2-DbF-vN3U.js → diagram-QEK2KX5R-Bvlbx8Jp.js} +8 -9
  82. package/webapp/dist/assets/diagram-QEK2KX5R-Bvlbx8Jp.js.map +1 -0
  83. package/webapp/dist/assets/{diagram-P4PSJMXO-BxBVRVaM.js → diagram-S2PKOQOG-CGjGalBu.js} +8 -8
  84. package/webapp/dist/assets/diagram-S2PKOQOG-CGjGalBu.js.map +1 -0
  85. package/webapp/dist/assets/{erDiagram-INFDFZHY-ny9JoOhV.js → erDiagram-Q2GNP2WA-Ds3qhwkG.js} +75 -96
  86. package/webapp/dist/assets/erDiagram-Q2GNP2WA-Ds3qhwkG.js.map +1 -0
  87. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-BMgWUlvY.js → flowDiagram-NV44I4VS-B1wDG_l5.js} +81 -98
  88. package/webapp/dist/assets/flowDiagram-NV44I4VS-B1wDG_l5.js.map +1 -0
  89. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-CCYpj3PM.js → ganttDiagram-JELNMOA3-BwuYt2bO.js} +3 -28
  90. package/webapp/dist/assets/ganttDiagram-JELNMOA3-BwuYt2bO.js.map +1 -0
  91. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-BFJGaDtk.js → gitGraphDiagram-V2S2FVAM-B2Tw773z.js} +46 -38
  92. package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-B2Tw773z.js.map +1 -0
  93. package/webapp/dist/assets/graph-CS_H7jBi.js +425 -0
  94. package/webapp/dist/assets/graph-CS_H7jBi.js.map +1 -0
  95. package/webapp/dist/assets/{index-EvfDN91D.js → index-arD81Nnh.js} +1056 -1031
  96. package/webapp/dist/assets/{index-EvfDN91D.js.map → index-arD81Nnh.js.map} +1 -1
  97. package/webapp/dist/assets/{index-BQoNJEGT.css → index-yycTJNYb.css} +1 -1
  98. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-Dnve0aOc.js → infoDiagram-HS3SLOUP-C9_JKYhm.js} +7 -7
  99. package/webapp/dist/assets/infoDiagram-HS3SLOUP-C9_JKYhm.js.map +1 -0
  100. package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
  101. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-D8_2EbDV.js → journeyDiagram-XKPGCS4Q-BhZggYOL.js} +5 -5
  102. package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BhZggYOL.js.map +1 -0
  103. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-BdmMXQQk.js → kanban-definition-3W4ZIXB7-B-R2Xm4Y.js} +3 -5
  104. package/webapp/dist/assets/kanban-definition-3W4ZIXB7-B-R2Xm4Y.js.map +1 -0
  105. package/webapp/dist/assets/{layout-3tA84hoP.js → layout-BzMatxDa.js} +5 -5
  106. package/webapp/dist/assets/layout-BzMatxDa.js.map +1 -0
  107. package/webapp/dist/assets/{linear-CpN6Japh.js → linear-BuuJkw_U.js} +2 -2
  108. package/webapp/dist/assets/linear-BuuJkw_U.js.map +1 -0
  109. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-HiYNz7qL.js → mindmap-definition-VGOIOE7T-BR7oDKBR.js} +5 -7
  110. package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BR7oDKBR.js.map +1 -0
  111. package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
  112. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DCVp50CX.js → pieDiagram-ADFJNKIX--QWeT2vZ.js} +8 -8
  113. package/webapp/dist/assets/pieDiagram-ADFJNKIX--QWeT2vZ.js.map +1 -0
  114. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-CCX7dwY0.js → quadrantDiagram-AYHSOK5B-BpqtmN3r.js} +3 -3
  115. package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-BpqtmN3r.js.map +1 -0
  116. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Cba7jjkf.js → requirementDiagram-UZGBJVZJ-CIXjIi4F.js} +6 -16
  117. package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-CIXjIi4F.js.map +1 -0
  118. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-Bz4iUubD.js → sankeyDiagram-TZEHDZUN-DJIt7SRz.js} +2 -2
  119. package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-DJIt7SRz.js.map +1 -0
  120. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DsFI9bic.js → sequenceDiagram-WL72ISMW-BpDK1ROT.js} +201 -601
  121. package/webapp/dist/assets/sequenceDiagram-WL72ISMW-BpDK1ROT.js.map +1 -0
  122. package/webapp/dist/assets/{stateDiagram-RAJIS63D-DLv9OSg4.js → stateDiagram-FKZM4ZOC-BoKGfmHf.js} +9 -9
  123. package/webapp/dist/assets/stateDiagram-FKZM4ZOC-BoKGfmHf.js.map +1 -0
  124. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DVlwzCvy.js → stateDiagram-v2-4FDKWEC3--haXC2JK.js} +5 -5
  125. package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3--haXC2JK.js.map +1 -0
  126. package/webapp/dist/assets/{timeline-definition-YZTLITO2-DnKbq6n0.js → timeline-definition-IT6M3QCI-BmSg3Hjf.js} +3 -3
  127. package/webapp/dist/assets/timeline-definition-IT6M3QCI-BmSg3Hjf.js.map +1 -0
  128. package/webapp/dist/assets/{treemap-KZPCXAKY-D9fYHZ__.js → treemap-GDKQZRPO-D9OuyDVA.js} +24 -37
  129. package/webapp/dist/assets/treemap-GDKQZRPO-D9OuyDVA.js.map +1 -0
  130. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-Bt-gKvam.js → xychartDiagram-PRI3JC2R-CVqSvO_S.js} +4 -4
  131. package/webapp/dist/assets/xychartDiagram-PRI3JC2R-CVqSvO_S.js.map +1 -0
  132. package/webapp/dist/index.html +2 -2
  133. package/webapp/dist/assets/_basePickBy-CG55qWp2.js.map +0 -1
  134. package/webapp/dist/assets/_baseUniq-Dd4UGB2O.js.map +0 -1
  135. package/webapp/dist/assets/arc-C2qiF4r3.js.map +0 -1
  136. package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-DQ4Z8fy_.js.map +0 -1
  137. package/webapp/dist/assets/blockDiagram-WCTKOSBZ-CPvOuMZA.js.map +0 -1
  138. package/webapp/dist/assets/c4Diagram-IC4MRINW-DElaFpnJ.js.map +0 -1
  139. package/webapp/dist/assets/channel-BR7mZa90.js.map +0 -1
  140. package/webapp/dist/assets/chunk-4BX2VUAB-DTmXCBYX.js.map +0 -1
  141. package/webapp/dist/assets/chunk-55IACEB6-DeBB4aJ4.js.map +0 -1
  142. package/webapp/dist/assets/chunk-FMBD7UC4-CXpgeev4.js.map +0 -1
  143. package/webapp/dist/assets/chunk-JSJVCQXG-DWfckfhO.js.map +0 -1
  144. package/webapp/dist/assets/chunk-KX2RTZJC-DWG_wpHB.js.map +0 -1
  145. package/webapp/dist/assets/chunk-NQ4KR5QH-DRcsqoac.js.map +0 -1
  146. package/webapp/dist/assets/chunk-QZHKN3VN-B9GPAJ2s.js.map +0 -1
  147. package/webapp/dist/assets/chunk-WL4C6EOR-V3Fq1ULq.js.map +0 -1
  148. package/webapp/dist/assets/classDiagram-VBA2DB6C-DspG486Z.js.map +0 -1
  149. package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-DspG486Z.js.map +0 -1
  150. package/webapp/dist/assets/clone-M8ztABN5.js.map +0 -1
  151. package/webapp/dist/assets/cose-bilkent-S5V4N54A-DZihobe3.js.map +0 -1
  152. package/webapp/dist/assets/dagre-KLK3FWXG-DBLWy3vi.js.map +0 -1
  153. package/webapp/dist/assets/diagram-E7M64L7V-D7IrPWaY.js.map +0 -1
  154. package/webapp/dist/assets/diagram-IFDJBPK2-DbF-vN3U.js.map +0 -1
  155. package/webapp/dist/assets/diagram-P4PSJMXO-BxBVRVaM.js.map +0 -1
  156. package/webapp/dist/assets/erDiagram-INFDFZHY-ny9JoOhV.js.map +0 -1
  157. package/webapp/dist/assets/flowDiagram-PKNHOUZH-BMgWUlvY.js.map +0 -1
  158. package/webapp/dist/assets/ganttDiagram-A5KZAMGK-CCYpj3PM.js.map +0 -1
  159. package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-BFJGaDtk.js.map +0 -1
  160. package/webapp/dist/assets/graph-Cp0m7fHH.js +0 -782
  161. package/webapp/dist/assets/graph-Cp0m7fHH.js.map +0 -1
  162. package/webapp/dist/assets/infoDiagram-LFFYTUFH-Dnve0aOc.js.map +0 -1
  163. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-DkSZM5sz.js +0 -966
  164. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-DkSZM5sz.js.map +0 -1
  165. package/webapp/dist/assets/journeyDiagram-4ABVD52K-D8_2EbDV.js.map +0 -1
  166. package/webapp/dist/assets/kanban-definition-K7BYSVSG-BdmMXQQk.js.map +0 -1
  167. package/webapp/dist/assets/layout-3tA84hoP.js.map +0 -1
  168. package/webapp/dist/assets/linear-CpN6Japh.js.map +0 -1
  169. package/webapp/dist/assets/mindmap-definition-YRQLILUH-HiYNz7qL.js.map +0 -1
  170. package/webapp/dist/assets/pieDiagram-SKSYHLDU-DCVp50CX.js.map +0 -1
  171. package/webapp/dist/assets/quadrantDiagram-337W2JSQ-CCX7dwY0.js.map +0 -1
  172. package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-Cba7jjkf.js.map +0 -1
  173. package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-Bz4iUubD.js.map +0 -1
  174. package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-DsFI9bic.js.map +0 -1
  175. package/webapp/dist/assets/stateDiagram-RAJIS63D-DLv9OSg4.js.map +0 -1
  176. package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-DVlwzCvy.js.map +0 -1
  177. package/webapp/dist/assets/timeline-definition-YZTLITO2-DnKbq6n0.js.map +0 -1
  178. package/webapp/dist/assets/treemap-KZPCXAKY-D9fYHZ__.js.map +0 -1
  179. package/webapp/dist/assets/vennDiagram-LZ73GAT5-CzKI47Ba.js +0 -2487
  180. package/webapp/dist/assets/vennDiagram-LZ73GAT5-CzKI47Ba.js.map +0 -1
  181. package/webapp/dist/assets/xychartDiagram-JWTSCODW-Bt-gKvam.js.map +0 -1
package/README.md CHANGED
@@ -103,7 +103,8 @@ Supported proxy variables:
103
103
  Practical guidance:
104
104
 
105
105
  - Set both `HTTP_PROXY` and `HTTPS_PROXY` when your network uses the same proxy for both schemes. Lowercase forms also work.
106
- - Use `NO_PROXY` for localhost, loopback, and internal domains that should bypass the proxy.
106
+ - Use `NO_PROXY` for hosts that should bypass the proxy. Node's built-in support includes exact hosts, suffix matches like `.company.com`, wildcard hosts like `*.company.com`, exact IPs, IP ranges like `192.168.1.1-192.168.1.100`, and `host:port` entries.
107
+ - `NO_PROXY` syntax is not standardized across languages and clients. Do not assume CIDR notation such as `192.168.0.0/16` is supported unless the specific runtime documents it.
107
108
  - Values should be standard proxy URLs, for example `http://proxy.company.com:8080`.
108
109
  - If your shell already exports proxy variables, Dominds will read them too; clear unrelated proxy vars if you want a clean test environment.
109
110
 
@@ -113,13 +114,13 @@ Examples:
113
114
  # Windows PowerShell
114
115
  $env:HTTP_PROXY = "http://proxy.company.com:8080"
115
116
  $env:HTTPS_PROXY = "http://proxy.company.com:8080"
116
- $env:NO_PROXY = "localhost,127.0.0.1,.corp.local"
117
+ $env:NO_PROXY = "localhost,127.0.0.1,.corp.local,192.168.1.1-192.168.1.100"
117
118
  dominds
118
119
 
119
120
  # macOS / Linux shell
120
121
  export HTTP_PROXY="http://proxy.company.com:8080"
121
122
  export HTTPS_PROXY="http://proxy.company.com:8080"
122
- export NO_PROXY="localhost,127.0.0.1,.corp.local"
123
+ export NO_PROXY="localhost,127.0.0.1,.corp.local,192.168.1.1-192.168.1.100"
123
124
  dominds
124
125
 
125
126
  # Disable Dominds env-proxy handling
package/README.zh.md CHANGED
@@ -57,7 +57,8 @@ Dominds 在 Windows、macOS、Linux 上都可以使用 Node 内建的环境变
57
57
  实践建议:
58
58
 
59
59
  - 若同一网络对 HTTP/HTTPS 都走同一代理,建议 `HTTP_PROXY` 和 `HTTPS_PROXY` 一起设置。小写变量名同样有效。
60
- - `NO_PROXY` 用于排除 localhost、回环地址和内网域名。
60
+ - `NO_PROXY` 用于排除不经过代理的主机。Node 内置支持包括精确主机名、后缀匹配(如 `.company.com`)、通配主机(如 `*.company.com`)、精确 IP、IP 范围(如 `192.168.1.1-192.168.1.100`)以及带端口的主机名。
61
+ - `NO_PROXY` 的语法在不同语言和客户端里并没有统一标准。除非目标运行时明确支持,不要把 CIDR 写法如 `192.168.0.0/16` 当成默认可用。
61
62
  - 代理值应使用标准 URL 形式,例如 `http://proxy.company.com:8080`。
62
63
  - 如果你的 shell 已经导出了代理变量,Dominds 也会读取它们;想要干净的测试环境时,请清掉无关的代理变量。
63
64
 
@@ -67,13 +68,13 @@ Dominds 在 Windows、macOS、Linux 上都可以使用 Node 内建的环境变
67
68
  # Windows PowerShell
68
69
  $env:HTTP_PROXY = "http://proxy.company.com:8080"
69
70
  $env:HTTPS_PROXY = "http://proxy.company.com:8080"
70
- $env:NO_PROXY = "localhost,127.0.0.1,.corp.local"
71
+ $env:NO_PROXY = "localhost,127.0.0.1,.corp.local,192.168.1.1-192.168.1.100"
71
72
  dominds
72
73
 
73
74
  # macOS / Linux shell
74
75
  export HTTP_PROXY="http://proxy.company.com:8080"
75
76
  export HTTPS_PROXY="http://proxy.company.com:8080"
76
- export NO_PROXY="localhost,127.0.0.1,.corp.local"
77
+ export NO_PROXY="localhost,127.0.0.1,.corp.local,192.168.1.1-192.168.1.100"
77
78
  dominds
78
79
 
79
80
  # 关闭 Dominds 的环境代理支持
package/dist/team.js CHANGED
@@ -586,11 +586,14 @@ exports.Team = Team;
586
586
  const resolved = [];
587
587
  const seen = new Set();
588
588
  const isAssignableToolset = (name) => (0, registry_1.getToolsetMeta)(name)?.assignable !== false;
589
+ const isWildcardAssignableToolset = (name) => (0, registry_1.getToolsetMeta)(name)?.wildcardAssignable !== false;
589
590
  for (const toolsetName of [...staticToolsets, ...dynamicToolsetNames]) {
590
591
  if (toolsetName.startsWith('!'))
591
592
  continue;
592
593
  const toolsetNames = toolsetName === '*'
593
- ? Object.keys((0, registry_1.listToolsets)()).filter((n) => !excludedToolsets.has(n) && isAssignableToolset(n))
594
+ ? Object.keys((0, registry_1.listToolsets)()).filter((n) => !excludedToolsets.has(n) &&
595
+ isAssignableToolset(n) &&
596
+ isWildcardAssignableToolset(n))
594
597
  : excludedToolsets.has(toolsetName)
595
598
  ? []
596
599
  : [toolsetName];
@@ -54,8 +54,12 @@ function manualSpecFor(toolsetId) {
54
54
  (0, registry_1.registerTool)(fs_1.moveDirTool);
55
55
  (0, registry_1.registerTool)(fs_1.readSymlinkTool);
56
56
  (0, registry_1.registerTool)(fs_1.createSymlinkTool);
57
+ (0, registry_1.registerTool)(fs_1.fsListDirTool);
58
+ (0, registry_1.registerTool)(fs_1.fsReadSymlinkTool);
57
59
  (0, registry_1.registerTool)(txt_1.readFileTool);
60
+ (0, registry_1.registerTool)(txt_1.fsReadFileTool);
58
61
  (0, registry_1.registerTool)(picture_1.readPictureTool);
62
+ (0, registry_1.registerTool)(picture_1.fsReadPictureTool);
59
63
  (0, registry_1.registerTool)(picture_1.writePictureTool);
60
64
  (0, registry_1.registerTool)(txt_1.createNewFileTool);
61
65
  (0, registry_1.registerTool)(txt_1.overwriteEntireFileTool);
@@ -71,6 +75,11 @@ function manualSpecFor(toolsetId) {
71
75
  (0, registry_1.registerTool)(ripgrep_1.ripgrepCountTool);
72
76
  (0, registry_1.registerTool)(ripgrep_1.ripgrepFixedTool);
73
77
  (0, registry_1.registerTool)(ripgrep_1.ripgrepSearchTool);
78
+ (0, registry_1.registerTool)(ripgrep_1.fsRipgrepFilesTool);
79
+ (0, registry_1.registerTool)(ripgrep_1.fsRipgrepSnippetsTool);
80
+ (0, registry_1.registerTool)(ripgrep_1.fsRipgrepCountTool);
81
+ (0, registry_1.registerTool)(ripgrep_1.fsRipgrepFixedTool);
82
+ (0, registry_1.registerTool)(ripgrep_1.fsRipgrepSearchTool);
74
83
  // OS tools
75
84
  (0, registry_1.registerTool)(os_1.shellCmdTool);
76
85
  (0, registry_1.registerTool)(os_1.readonlyShellTool);
@@ -252,6 +261,27 @@ for (const tool of team_mgmt_1.teamMgmtTools) {
252
261
  promptFilesI18n: promptFilesFor('ws_read'),
253
262
  manualSpec: manualSpecFor('ws_read'),
254
263
  });
264
+ (0, registry_1.registerToolset)('fs_read', [
265
+ fs_1.fsListDirTool,
266
+ fs_1.fsReadSymlinkTool,
267
+ txt_1.fsReadFileTool,
268
+ picture_1.fsReadPictureTool,
269
+ ripgrep_1.fsRipgrepFilesTool,
270
+ ripgrep_1.fsRipgrepSnippetsTool,
271
+ ripgrep_1.fsRipgrepCountTool,
272
+ ripgrep_1.fsRipgrepFixedTool,
273
+ ripgrep_1.fsRipgrepSearchTool,
274
+ ]);
275
+ (0, registry_1.setToolsetMeta)('fs_read', {
276
+ source: 'dominds',
277
+ wildcardAssignable: false,
278
+ descriptionI18n: {
279
+ en: 'Local filesystem read-only access without rtws path restriction: list directories, read text/images, and search files.',
280
+ zh: '本机文件系统只读访问,不限制路径必须位于 rtws 内:列目录、读文本/图片、检索文件。',
281
+ },
282
+ promptFilesI18n: promptFilesFor('fs_read'),
283
+ manualSpec: manualSpecFor('fs_read'),
284
+ });
255
285
  (0, registry_1.registerToolset)('ws_mod', [
256
286
  fs_1.listDirTool,
257
287
  fs_1.rmDirTool,
@@ -1,10 +1,12 @@
1
1
  import type { FuncTool } from '../tool';
2
2
  export declare const listDirTool: FuncTool;
3
+ export declare const fsListDirTool: FuncTool;
3
4
  export declare const rmDirTool: FuncTool;
4
5
  export declare const rmFileTool: FuncTool;
5
6
  export declare const mkDirTool: FuncTool;
6
7
  export declare const moveFileTool: FuncTool;
7
8
  export declare const moveDirTool: FuncTool;
8
9
  export declare const readSymlinkTool: FuncTool;
10
+ export declare const fsReadSymlinkTool: FuncTool;
9
11
  export declare const createSymlinkTool: FuncTool;
10
12
  export declare const rmSymlinkTool: FuncTool;
package/dist/tools/fs.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.rmSymlinkTool = exports.createSymlinkTool = exports.readSymlinkTool = exports.moveDirTool = exports.moveFileTool = exports.mkDirTool = exports.rmFileTool = exports.rmDirTool = exports.listDirTool = void 0;
6
+ exports.rmSymlinkTool = exports.createSymlinkTool = exports.fsReadSymlinkTool = exports.readSymlinkTool = exports.moveDirTool = exports.moveFileTool = exports.mkDirTool = exports.rmFileTool = exports.rmDirTool = exports.fsListDirTool = exports.listDirTool = void 0;
7
7
  /**
8
8
  * Module: tools/fs
9
9
  *
@@ -337,7 +337,7 @@ exports.listDirTool = {
337
337
  : entry.type === 'symlink'
338
338
  ? '🔗'
339
339
  : '❓';
340
- const sizeStr = entry.size ? formatSize(entry.size) : '-';
340
+ const sizeStr = entry.size === undefined ? '-' : formatSize(entry.size);
341
341
  const linesStr = entry.lines ? entry.lines.toString() : '-';
342
342
  const targetTypeStr = entry.type === 'symlink' && entry.symlinkResolvedType
343
343
  ? ` (${entry.symlinkResolvedType})`
@@ -369,6 +369,220 @@ exports.listDirTool = {
369
369
  }
370
370
  },
371
371
  };
372
+ exports.fsListDirTool = {
373
+ type: 'func',
374
+ name: 'fs_list_dir',
375
+ description: 'List local filesystem directory contents without restricting paths to rtws (runtime workspace).',
376
+ descriptionI18n: {
377
+ en: 'List local filesystem directory contents without restricting paths to rtws (runtime workspace).',
378
+ zh: '列出本机文件系统目录内容,不限制路径必须位于 rtws(运行时工作区)内。',
379
+ },
380
+ parameters: {
381
+ type: 'object',
382
+ additionalProperties: false,
383
+ properties: {
384
+ path: {
385
+ type: 'string',
386
+ description: "Directory path to read. Absolute paths are accepted; relative paths resolve from the current process cwd. Defaults to '.'.",
387
+ },
388
+ },
389
+ },
390
+ argsValidation: 'dominds',
391
+ call: async (_dlg, _caller, args) => {
392
+ const workLanguage = (0, work_language_1.getWorkLanguage)();
393
+ const labels = workLanguage === 'zh'
394
+ ? {
395
+ notFound: (p) => `❌ **未找到**\n\n目录 \`${p}\` 不存在。`,
396
+ notDir: (p) => `❌ **错误**\n\n路径 \`${p}\` 不是目录。`,
397
+ readDirFailed: (msg) => `❌ **错误**\n\n读取目录失败:${msg}`,
398
+ dirHeader: '📁 **目录:**',
399
+ symlinkPathNotice: (p, target) => target
400
+ ? `🔗 **说明:** \`${p}\` 是符号链接(→ \`${target}\`),已按目录跟随读取。`
401
+ : `🔗 **说明:** \`${p}\` 是符号链接,已按目录跟随读取。`,
402
+ emptyDir: '_此目录为空。_',
403
+ table: {
404
+ name: '名称',
405
+ type: '类型',
406
+ size: '大小',
407
+ lines: '行数',
408
+ target: '目标',
409
+ },
410
+ }
411
+ : {
412
+ notFound: (p) => `❌ **Not Found**\n\nDirectory \`${p}\` does not exist.`,
413
+ notDir: (p) => `❌ **Error**\n\nPath \`${p}\` is not a directory.`,
414
+ readDirFailed: (msg) => `❌ **Error**\n\nFailed to read directory: ${msg}`,
415
+ dirHeader: '📁 **Directory:**',
416
+ symlinkPathNotice: (p, target) => target
417
+ ? `🔗 **Note:** \`${p}\` is a symlink (→ \`${target}\`), and was followed as a directory.`
418
+ : `🔗 **Note:** \`${p}\` is a symlink and was followed as a directory.`,
419
+ emptyDir: '_This directory is empty._',
420
+ table: {
421
+ name: 'Name',
422
+ type: 'Type',
423
+ size: 'Size',
424
+ lines: 'Lines',
425
+ target: 'Target',
426
+ },
427
+ };
428
+ let requestedPath = '.';
429
+ const pathValue = args['path'];
430
+ if (typeof pathValue === 'string' && pathValue.trim() !== '') {
431
+ requestedPath = pathValue.trim();
432
+ }
433
+ const dir = path_1.default.resolve(process.cwd(), requestedPath);
434
+ const displayPath = path_1.default.isAbsolute(requestedPath) ? dir : requestedPath;
435
+ try {
436
+ let inputPathIsSymlink = false;
437
+ let inputPathSymlinkTarget;
438
+ try {
439
+ const statsInfo = await statWithSymlinkInfo(dir);
440
+ inputPathIsSymlink = statsInfo.isSymlink;
441
+ inputPathSymlinkTarget = statsInfo.symlinkTarget;
442
+ if (!statsInfo.followStat.isDirectory()) {
443
+ return fail(labels.notDir(displayPath));
444
+ }
445
+ }
446
+ catch (error) {
447
+ if (typeof error === 'object' &&
448
+ error !== null &&
449
+ 'code' in error &&
450
+ error.code === 'ENOENT') {
451
+ return fail(labels.notFound(displayPath));
452
+ }
453
+ const msg = error instanceof Error ? error.message : String(error);
454
+ return fail(labels.readDirFailed(msg));
455
+ }
456
+ const entries = await promises_1.default.readdir(dir, { withFileTypes: true });
457
+ const data = [];
458
+ for (const entry of entries) {
459
+ const entryPath = path_1.default.join(dir, entry.name);
460
+ const dirEntry = {
461
+ name: entry.name,
462
+ type: 'other',
463
+ };
464
+ try {
465
+ const stats = await promises_1.default.lstat(entryPath);
466
+ if (entry.isDirectory()) {
467
+ dirEntry.type = 'dir';
468
+ dirEntry.size = stats.size;
469
+ }
470
+ else if (entry.isFile()) {
471
+ dirEntry.type = 'file';
472
+ dirEntry.size = stats.size;
473
+ if (isTextFile(entry.name)) {
474
+ dirEntry.lines = await countLines(entryPath);
475
+ }
476
+ }
477
+ else if (entry.isSymbolicLink()) {
478
+ dirEntry.type = 'symlink';
479
+ dirEntry.size = stats.size;
480
+ try {
481
+ const target = await promises_1.default.readlink(entryPath);
482
+ dirEntry.target = target;
483
+ try {
484
+ const targetStats = await promises_1.default.stat(entryPath);
485
+ if (targetStats.isDirectory()) {
486
+ dirEntry.symlinkResolvedType = 'dir';
487
+ }
488
+ else if (targetStats.isFile()) {
489
+ dirEntry.symlinkResolvedType = 'file';
490
+ }
491
+ else {
492
+ dirEntry.symlinkResolvedType = 'other';
493
+ }
494
+ if (targetStats.isFile() && (isTextFile(entry.name) || isTextFile(target))) {
495
+ dirEntry.lines = await countLines(entryPath);
496
+ }
497
+ }
498
+ catch (err) {
499
+ log_1.log.warn(`Failed to stat symlink target ${entryPath}:`, err);
500
+ dirEntry.symlinkResolvedType = 'broken';
501
+ }
502
+ }
503
+ catch (err) {
504
+ log_1.log.warn(`Failed to read symlink ${entryPath}:`, err);
505
+ dirEntry.target = '<unreadable>';
506
+ dirEntry.symlinkResolvedType = 'other';
507
+ }
508
+ }
509
+ else {
510
+ dirEntry.type = 'other';
511
+ dirEntry.size = stats.size;
512
+ }
513
+ }
514
+ catch (_error) {
515
+ if (entry.isDirectory()) {
516
+ dirEntry.type = 'dir';
517
+ }
518
+ else if (entry.isFile()) {
519
+ dirEntry.type = 'file';
520
+ }
521
+ else if (entry.isSymbolicLink()) {
522
+ dirEntry.type = 'symlink';
523
+ dirEntry.target = '<error>';
524
+ }
525
+ }
526
+ data.push(dirEntry);
527
+ }
528
+ let markdown = `${labels.dirHeader} \`${displayPath}\`\n\n`;
529
+ if (inputPathIsSymlink) {
530
+ markdown += `${labels.symlinkPathNotice(displayPath, inputPathSymlinkTarget)}\n\n`;
531
+ }
532
+ if (data.length === 0) {
533
+ markdown += labels.emptyDir;
534
+ }
535
+ else {
536
+ const shownEntries = data.slice(0, LIST_DIR_MAX_RENDERED_ENTRIES);
537
+ const omittedEntries = Math.max(0, data.length - shownEntries.length);
538
+ if (omittedEntries > 0) {
539
+ markdown +=
540
+ workLanguage === 'zh'
541
+ ? `⚠️ **说明:** 目录项过多;为避免输出过长,仅展示前 ${shownEntries.length} 项,省略 ${omittedEntries} 项。\n\n`
542
+ : `⚠️ **Note:** Directory contains many entries; to keep the output bounded, showing the first ${shownEntries.length} entries and omitting ${omittedEntries}.\n\n`;
543
+ }
544
+ markdown += `| ${labels.table.name} | ${labels.table.type} | ${labels.table.size} | ${labels.table.lines} | ${labels.table.target} |\n`;
545
+ markdown += '|------|------|------|-------|--------|\n';
546
+ for (const entry of shownEntries) {
547
+ const typeIcon = entry.type === 'dir'
548
+ ? '📁'
549
+ : entry.type === 'file'
550
+ ? '📄'
551
+ : entry.type === 'symlink'
552
+ ? '🔗'
553
+ : '❓';
554
+ const sizeStr = entry.size === undefined ? '-' : formatSize(entry.size);
555
+ const linesStr = entry.lines ? entry.lines.toString() : '-';
556
+ const targetTypeStr = entry.type === 'symlink' && entry.symlinkResolvedType
557
+ ? ` (${entry.symlinkResolvedType})`
558
+ : '';
559
+ const renderedName = (0, output_limit_1.truncateInlineText)(entry.name, LIST_DIR_NAME_CHAR_LIMIT);
560
+ const targetStr = entry.target
561
+ ? (0, output_limit_1.truncateInlineText)(`→ ${entry.target}${targetTypeStr}`, LIST_DIR_TARGET_CHAR_LIMIT)
562
+ : '-';
563
+ markdown += `| ${typeIcon} \`${renderedName}\` | ${entry.type} | ${sizeStr} | ${linesStr} | ${targetStr} |\n`;
564
+ }
565
+ }
566
+ return ok(markdown);
567
+ }
568
+ catch (error) {
569
+ if (typeof error === 'object' &&
570
+ error !== null &&
571
+ 'code' in error &&
572
+ error.code === 'ENOENT') {
573
+ return fail(labels.notFound(displayPath));
574
+ }
575
+ if (typeof error === 'object' &&
576
+ error !== null &&
577
+ 'code' in error &&
578
+ error.code === 'ENOTDIR') {
579
+ return fail(labels.notDir(displayPath));
580
+ }
581
+ const msg = error instanceof Error ? error.message : String(error);
582
+ return fail(labels.readDirFailed(msg));
583
+ }
584
+ },
585
+ };
372
586
  exports.rmDirTool = {
373
587
  type: 'func',
374
588
  name: 'rm_dir',
@@ -1045,6 +1259,71 @@ exports.readSymlinkTool = {
1045
1259
  }
1046
1260
  },
1047
1261
  };
1262
+ exports.fsReadSymlinkTool = {
1263
+ type: 'func',
1264
+ name: 'fs_read_symlink',
1265
+ description: 'Read a local filesystem symlink target without following it, without restricting paths to rtws.',
1266
+ descriptionI18n: {
1267
+ en: 'Read a local filesystem symlink target without following it, without restricting paths to rtws.',
1268
+ zh: '读取本机文件系统符号链接目标(不跟随链接),不限制路径必须位于 rtws 内。',
1269
+ },
1270
+ parameters: {
1271
+ type: 'object',
1272
+ additionalProperties: false,
1273
+ required: ['path'],
1274
+ properties: {
1275
+ path: {
1276
+ type: 'string',
1277
+ description: 'Symlink path. Absolute paths are accepted; relative paths resolve from the current process cwd.',
1278
+ },
1279
+ },
1280
+ },
1281
+ argsValidation: 'dominds',
1282
+ call: async (_dlg, _caller, args) => {
1283
+ const pathValue = args['path'];
1284
+ const requestedPath = typeof pathValue === 'string' ? pathValue.trim() : '';
1285
+ if (!requestedPath) {
1286
+ return failYaml([
1287
+ `status: error`,
1288
+ `mode: fs_read_symlink`,
1289
+ `error: PATH_REQUIRED`,
1290
+ `summary: ${yamlQuote('Fs-read-symlink failed: path required.')}`,
1291
+ ].join('\n'));
1292
+ }
1293
+ const absPath = path_1.default.resolve(process.cwd(), requestedPath);
1294
+ const displayPath = path_1.default.isAbsolute(requestedPath) ? absPath : requestedPath;
1295
+ try {
1296
+ const pathStat = await promises_1.default.lstat(absPath);
1297
+ if (!pathStat.isSymbolicLink()) {
1298
+ return failYaml([
1299
+ `status: error`,
1300
+ `mode: fs_read_symlink`,
1301
+ `path: ${yamlQuote(displayPath)}`,
1302
+ `error: NOT_SYMLINK`,
1303
+ `summary: ${yamlQuote('Fs-read-symlink failed: path is not a symlink.')}`,
1304
+ ].join('\n'));
1305
+ }
1306
+ const target = await promises_1.default.readlink(absPath);
1307
+ return okYaml([
1308
+ `status: ok`,
1309
+ `mode: fs_read_symlink`,
1310
+ `path: ${yamlQuote(displayPath)}`,
1311
+ `target: ${yamlQuote(target)}`,
1312
+ `summary: ${yamlQuote(`Fs-read-symlink: ${displayPath} -> ${target}.`)}`,
1313
+ ].join('\n'));
1314
+ }
1315
+ catch (error) {
1316
+ const yaml = [
1317
+ `status: error`,
1318
+ `mode: fs_read_symlink`,
1319
+ `path: ${yamlQuote(displayPath)}`,
1320
+ `error: FAILED`,
1321
+ `summary: ${yamlQuote(error instanceof Error ? error.message : String(error))}`,
1322
+ ].join('\n');
1323
+ return failYaml(yaml);
1324
+ }
1325
+ },
1326
+ };
1048
1327
  exports.createSymlinkTool = {
1049
1328
  type: 'func',
1050
1329
  name: 'create_symlink',
@@ -6,8 +6,19 @@
6
6
  */
7
7
  import type { FuncTool, ReminderOwner } from '../tool';
8
8
  export declare function resetTrackedDaemonsForTests(): void;
9
+ type ShellSpawnSpec = Readonly<{
10
+ command: string;
11
+ args: string[];
12
+ shellLabel: string;
13
+ }>;
14
+ export declare function resolveShellCmdSpawnSpecForTests(command: string, shell: string | undefined, platform: NodeJS.Platform): ShellSpawnSpec;
15
+ export declare function resolveReadonlyShellSpawnSpecForTests(command: string, platform: NodeJS.Platform): Readonly<{
16
+ command: string;
17
+ args: string[];
18
+ }>;
9
19
  export declare const shellCmdReminderOwner: ReminderOwner;
10
20
  export declare const shellCmdTool: FuncTool;
11
21
  export declare const readonlyShellTool: FuncTool;
12
22
  export declare const stopDaemonTool: FuncTool;
13
23
  export declare const getDaemonOutputTool: FuncTool;
24
+ export {};
package/dist/tools/os.js CHANGED
@@ -11,6 +11,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getDaemonOutputTool = exports.stopDaemonTool = exports.readonlyShellTool = exports.shellCmdTool = exports.shellCmdReminderOwner = void 0;
13
13
  exports.resetTrackedDaemonsForTests = resetTrackedDaemonsForTests;
14
+ exports.resolveShellCmdSpawnSpecForTests = resolveShellCmdSpawnSpecForTests;
15
+ exports.resolveReadonlyShellSpawnSpecForTests = resolveReadonlyShellSpawnSpecForTests;
14
16
  const time_1 = require("@longrun-ai/kernel/utils/time");
15
17
  const child_process_1 = require("child_process");
16
18
  const crypto_1 = __importDefault(require("crypto"));
@@ -816,9 +818,12 @@ function parseGetDaemonOutputArgs(args) {
816
818
  }
817
819
  return { pid, stdout, stderr };
818
820
  }
819
- function resolveShellCmdSpawnSpec(command, shell) {
821
+ function encodePowerShellCommand(command) {
822
+ return Buffer.from(command, 'utf16le').toString('base64');
823
+ }
824
+ function resolveShellCmdSpawnSpec(command, shell, platform = process.platform) {
820
825
  const preferredShell = typeof shell === 'string' && shell.trim() !== '' ? shell.trim() : undefined;
821
- if (process.platform === 'win32') {
826
+ if (platform === 'win32') {
822
827
  if (preferredShell) {
823
828
  const base = path_1.default.basename(preferredShell).toLowerCase();
824
829
  if (base === 'powershell' ||
@@ -827,14 +832,14 @@ function resolveShellCmdSpawnSpec(command, shell) {
827
832
  base === 'pwsh.exe') {
828
833
  return {
829
834
  command: preferredShell,
830
- args: ['-NoLogo', '-NoProfile', '-Command', command],
835
+ args: ['-NoLogo', '-NoProfile', '-EncodedCommand', encodePowerShellCommand(command)],
831
836
  shellLabel: preferredShell,
832
837
  };
833
838
  }
834
839
  if (base === 'cmd' || base === 'cmd.exe') {
835
840
  return {
836
841
  command: preferredShell,
837
- args: ['/d', '/s', '/c', command],
842
+ args: ['/d', '/c', command],
838
843
  shellLabel: preferredShell,
839
844
  };
840
845
  }
@@ -846,7 +851,7 @@ function resolveShellCmdSpawnSpec(command, shell) {
846
851
  }
847
852
  return {
848
853
  command: 'cmd.exe',
849
- args: ['/d', '/s', '/c', command],
854
+ args: ['/d', '/c', command],
850
855
  shellLabel: 'cmd.exe',
851
856
  };
852
857
  }
@@ -857,12 +862,18 @@ function resolveShellCmdSpawnSpec(command, shell) {
857
862
  shellLabel: resolvedShell,
858
863
  };
859
864
  }
860
- function resolveReadonlyShellSpawnSpec(command) {
861
- if (process.platform === 'win32') {
862
- return { command: 'cmd.exe', args: ['/d', '/s', '/c', command] };
865
+ function resolveShellCmdSpawnSpecForTests(command, shell, platform) {
866
+ return resolveShellCmdSpawnSpec(command, shell, platform);
867
+ }
868
+ function resolveReadonlyShellSpawnSpec(command, platform = process.platform) {
869
+ if (platform === 'win32') {
870
+ return { command: 'cmd.exe', args: ['/d', '/c', command] };
863
871
  }
864
872
  return { command: 'bash', args: ['-c', command] };
865
873
  }
874
+ function resolveReadonlyShellSpawnSpecForTests(command, platform) {
875
+ return resolveReadonlyShellSpawnSpec(command, platform);
876
+ }
866
877
  function resolveCmdRunnerEntrypointAbs() {
867
878
  const distCandidate = path_1.default.resolve(__dirname, 'cmd-runner.js');
868
879
  if (fs_1.default.existsSync(distCandidate)) {
@@ -1105,7 +1116,7 @@ const shellCmdSchema = {
1105
1116
  },
1106
1117
  shell: {
1107
1118
  type: 'string',
1108
- description: 'Shell to use for execution (default: bash on Linux/macOS; cmd.exe on Windows)',
1119
+ description: 'Shell to use for execution (default: bash on Linux/macOS; cmd.exe on Windows). On Windows, powershell.exe/pwsh commands are passed via -EncodedCommand.',
1109
1120
  },
1110
1121
  scrollbackLines: {
1111
1122
  type: 'number',
@@ -1,3 +1,4 @@
1
1
  import type { FuncTool } from '../tool';
2
2
  export declare const readPictureTool: FuncTool;
3
+ export declare const fsReadPictureTool: FuncTool;
3
4
  export declare const writePictureTool: FuncTool;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writePictureTool = exports.readPictureTool = void 0;
6
+ exports.writePictureTool = exports.fsReadPictureTool = exports.readPictureTool = void 0;
7
7
  const crypto_1 = require("crypto");
8
8
  const promises_1 = __importDefault(require("fs/promises"));
9
9
  const path_1 = __importDefault(require("path"));
@@ -33,6 +33,12 @@ function ensureInsideWorkspace(rel) {
33
33
  }
34
34
  throw new Error('Path must be within rtws (runtime workspace)');
35
35
  }
36
+ function resolveLocalFilesystemPath(inputPath) {
37
+ return path_1.default.resolve(process.cwd(), inputPath);
38
+ }
39
+ function displayLocalFilesystemPath(inputPath, absPath) {
40
+ return path_1.default.isAbsolute(inputPath) ? absPath : inputPath;
41
+ }
36
42
  function requirePathArg(args) {
37
43
  const value = args['path'];
38
44
  if (typeof value !== 'string' || value.trim() === '') {
@@ -246,6 +252,63 @@ exports.readPictureTool = {
246
252
  }
247
253
  },
248
254
  };
255
+ exports.fsReadPictureTool = {
256
+ type: 'func',
257
+ name: 'fs_read_picture',
258
+ description: 'Read a PNG/JPEG/WebP/GIF image from the local filesystem without restricting paths to rtws, then attach it as an image content item for the next LLM context.',
259
+ descriptionI18n: {
260
+ en: 'Read a PNG/JPEG/WebP/GIF image from the local filesystem without restricting paths to rtws, then attach it as an image content item for the next LLM context.',
261
+ zh: '读取本机文件系统中的 PNG/JPEG/WebP/GIF 图片(不限制路径必须位于 rtws 内),并作为图片 content item 放入后续 LLM 上下文。',
262
+ },
263
+ parameters: {
264
+ type: 'object',
265
+ additionalProperties: false,
266
+ properties: {
267
+ path: {
268
+ type: 'string',
269
+ description: 'Image path to read. Absolute paths are accepted; relative paths resolve from the current process cwd. Supported extensions: .png, .jpg, .jpeg, .webp, .gif.',
270
+ },
271
+ },
272
+ required: ['path'],
273
+ },
274
+ argsValidation: 'dominds',
275
+ call: async (dlg, _caller, args) => {
276
+ try {
277
+ const requestedPath = requirePathArg(args);
278
+ const absPath = resolveLocalFilesystemPath(requestedPath);
279
+ const displayPath = displayLocalFilesystemPath(requestedPath, absPath);
280
+ const mimeType = extToMimeType(displayPath);
281
+ if (mimeType === null) {
282
+ return fail('Unsupported image extension. Supported extensions: .png, .jpg, .jpeg, .webp, .gif');
283
+ }
284
+ const stat = await promises_1.default.stat(absPath);
285
+ if (!stat.isFile())
286
+ return fail(`Path is not a file: ${displayPath}`);
287
+ if (stat.size <= 0 || stat.size > PICTURE_MAX_BYTES) {
288
+ return fail(`Image must be between 1 byte and ${String(PICTURE_MAX_BYTES)} bytes`);
289
+ }
290
+ const bytes = await promises_1.default.readFile(absPath);
291
+ validateImageBytesMatchMimeType(bytes, mimeType);
292
+ const item = await persistPictureArtifact({
293
+ dlg,
294
+ toolName: 'fs_read_picture',
295
+ mimeType,
296
+ bytes,
297
+ });
298
+ return ok(formatPictureResultYaml({
299
+ status: 'ok',
300
+ action: 'fs_read_picture',
301
+ path: displayPath,
302
+ mimeType,
303
+ byteLength: bytes.length,
304
+ artifactRelPath: item.artifact.relPath,
305
+ }), [item]);
306
+ }
307
+ catch (error) {
308
+ return fail(error instanceof Error ? error.message : String(error));
309
+ }
310
+ },
311
+ };
249
312
  exports.writePictureTool = {
250
313
  type: 'func',
251
314
  name: 'write_picture',
@@ -12,6 +12,11 @@ Typical uses:
12
12
  - read-only `git status` / `git diff` / `git log` / `git show`
13
13
  - version probes and simple filesystem inspection
14
14
 
15
+ Windows notes:
16
+
17
+ - Prefer no-space forward-slash paths such as `D:/path/to/file`
18
+ - Avoid nested `cmd /c "..."`
19
+
15
20
  Example:
16
21
 
17
22
  ```typescript
@@ -12,6 +12,11 @@
12
12
  - 只读 `git status` / `git diff` / `git log` / `git show`
13
13
  - 版本探针与简单文件系统检查
14
14
 
15
+ Windows 注意:
16
+
17
+ - 优先使用不带空格的正斜杠路径,如 `D:/path/to/file`
18
+ - 避免嵌套 `cmd /c "..."`
19
+
15
20
  示例:
16
21
 
17
22
  ```typescript