pi-coding-master 0.2.7

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 (304) hide show
  1. package/README.md +50 -0
  2. package/core/god.agent.capability/@ABANDONED.brain.prefrontal.monitor/gpu_monitor.py +80 -0
  3. package/core/god.agent.capability/@ABANDONED.brain.prefrontal.monitor/gpu_monitor.py.CHANGELOG +1 -0
  4. package/core/god.agent.capability/@ABANDONED.brain.prefrontal.monitor/gpu_monitor.py.SPEC +3 -0
  5. package/core/god.agent.capability/hands.dev.writeissue/issue.ts +209 -0
  6. package/core/god.agent.capability/hands.dev.writeissue/issue.ts.SPEC +26 -0
  7. package/core/god.agent.capability/hands.files.changewatcher/watcher.ts +44 -0
  8. package/core/god.agent.capability/hands.files.changewatcher/watcher.ts.SPEC +25 -0
  9. package/core/god.pi.mod/cli/pi-completion.zsh +21 -0
  10. package/core/god.pi.mod/cli/pi-completion.zsh.CHANGELOG +1 -0
  11. package/core/god.pi.mod/cli/pi-people.sh +264 -0
  12. package/core/god.pi.mod/cli/pi-people.sh.LESSON +10 -0
  13. package/core/god.pi.mod/cli/pi-people.sh.SPEC +31 -0
  14. package/core/god.pi.mod/paths.ts +47 -0
  15. package/core/god.pi.mod/tui.mods.blockrender/blockrender.js +90 -0
  16. package/core/god.pi.mod/tui.mods.blockrender/blockrender.js.SPEC +29 -0
  17. package/core/god.pi.mod/tui.mods.footer.budget/budget_guard.ts +154 -0
  18. package/core/god.pi.mod/tui.mods.footer.budget/budget_guard.ts.CHANGELOG +10 -0
  19. package/core/god.pi.mod/tui.mods.footer.budget/budget_guard.ts.LESSON +12 -0
  20. package/core/god.pi.mod/tui.mods.footer.budget/budget_guard.ts.SPEC +26 -0
  21. package/core/god.pi.mod/tui.mods.footer.budget/footer-cny.CHANGELOG +39 -0
  22. package/core/god.pi.mod/tui.mods.viewmode/view_mode-thinking.patch +55 -0
  23. package/core/god.pi.mod/tui.mods.viewmode/view_mode-tools.patch +19 -0
  24. package/core/god.pi.mod/tui.mods.viewmode/view_mode-tools.patch.CHANGELOG +1 -0
  25. package/core/god.pi.mod/tui.mods.viewmode/view_mode.ts +50 -0
  26. package/core/god.pi.mod/tui.mods.viewmode/view_mode.ts.SPEC +12 -0
  27. package/core/god.pi.mod/tui.variants.userterminal/user_terminal.CHANGELOG +10 -0
  28. package/core/god.pi.mod/tui.variants.userterminal/user_terminal.ts +66 -0
  29. package/core/god.pi.mod/tui.variants.userterminal/user_terminal.ts.SPEC +31 -0
  30. package/core/index.ts +3 -0
  31. package/core/individual.bio.gene/dna.coded/coded.dna +257 -0
  32. package/core/individual.bio.gene/dna.coded/coded.dna.CHANGELOG +12 -0
  33. package/core/individual.bio.gene/dna.coded/coded.dna.SPEC +11 -0
  34. package/core/individual.bio.gene/dna.coded/core.dna +110 -0
  35. package/core/individual.bio.gene/dna.promotor/promotor.dna +117 -0
  36. package/core/individual.bio.gene/dna.promotor/promotor.dna.CHANGELOG +4 -0
  37. package/core/individual.bio.gene/dna.promotor/promotor.dna.SPEC +7 -0
  38. package/core/individual.bio.gene/dna.transpiler/transpiler.ts +395 -0
  39. package/core/individual.bio.gene/dna.transpiler/transpiler.ts.CHANGELOG +7 -0
  40. package/core/individual.bio.gene/dna.transpiler/transpiler.ts.SPEC +28 -0
  41. package/core/individual.bio.gene/gene.README +19 -0
  42. package/core/individual.bio.gene/rna/rna.json +536 -0
  43. package/core/individual.bio.gene/rna/rna.json.CHANGELOG +2 -0
  44. package/core/individual.bio.gene/rna/rna.json.SPEC +8 -0
  45. package/core/individual.bio.organs/blood.runtime/messages.ts +236 -0
  46. package/core/individual.bio.organs/blood.runtime/runtime.ts +173 -0
  47. package/core/individual.bio.organs/blood.runtime/runtime.ts.CHANGELOG +5 -0
  48. package/core/individual.bio.organs/blood.runtime/runtime.ts.SPEC +32 -0
  49. package/core/individual.bio.organs/brain.amygdala/amygdala.ts +25 -0
  50. package/core/individual.bio.organs/brain.amygdala/amygdala.ts.COMMENT +3 -0
  51. package/core/individual.bio.organs/brain.amygdala/amygdala.ts.SPEC +9 -0
  52. package/core/individual.bio.organs/brain.hippocampus/hippocampus-launcher.sh.template +108 -0
  53. package/core/individual.bio.organs/brain.hippocampus/hippocampus.ts +166 -0
  54. package/core/individual.bio.organs/brain.hippocampus/hippocampus.ts.CHANGELOG +12 -0
  55. package/core/individual.bio.organs/brain.hippocampus/hippocampus.ts.LESSON +22 -0
  56. package/core/individual.bio.organs/brain.hippocampus/hippocampus.ts.SPEC +16 -0
  57. package/core/individual.bio.organs/brain.hippocampus/memory.ts +879 -0
  58. package/core/individual.bio.organs/brain.hippocampus/memory.ts.CHANGELOG +66 -0
  59. package/core/individual.bio.organs/brain.hippocampus/memory.ts.LESSON +25 -0
  60. package/core/individual.bio.organs/brain.hippocampus/memory.ts.SPEC +46 -0
  61. package/core/individual.bio.organs/brain.hippocampus/sleep.ts +139 -0
  62. package/core/individual.bio.organs/brain.hippocampus/sleep.ts.CHANGELOG +11 -0
  63. package/core/individual.bio.organs/brain.hippocampus/sleep.ts.SPEC +16 -0
  64. package/core/individual.bio.organs/brain.prefrontal.drafting/drafting.SPEC +44 -0
  65. package/core/individual.bio.organs/brain.prefrontal.drafting/drafting.ts +73 -0
  66. package/core/individual.bio.organs/brain.prefrontal.drafting/drafting.ts.CHANGELOG +3 -0
  67. package/core/individual.bio.organs/brain.prefrontal.drafting/drafting.ts.SPEC +24 -0
  68. package/core/individual.bio.organs/brain.prefrontal.drafting/index.ts.CHANGELOG +3 -0
  69. package/core/individual.bio.organs/brain.prefrontal.drafting/main.ts +13 -0
  70. package/core/individual.bio.organs/brain.prefrontal.drafting/main.ts.SPEC +17 -0
  71. package/core/individual.bio.organs/brain.senses.bioclock/bioclock.ts +94 -0
  72. package/core/individual.bio.organs/brain.senses.bioclock/bioclock.ts.LESSON +13 -0
  73. package/core/individual.bio.organs/brain.senses.bioclock/bioclock.ts.SPEC +20 -0
  74. package/core/individual.bio.organs/brain.senses.subconscious/feed-format.SPEC +56 -0
  75. package/core/individual.bio.organs/brain.senses.subconscious/index.ts.CHANGELOG +13 -0
  76. package/core/individual.bio.organs/brain.senses.subconscious/spawner.ts +130 -0
  77. package/core/individual.bio.organs/brain.senses.subconscious/spawner.ts.SPEC +13 -0
  78. package/core/individual.bio.organs/brain.senses.subconscious/subconscious.ts +280 -0
  79. package/core/individual.bio.organs/brain.senses.subconscious/subconscious.ts.CHANGELOG +7 -0
  80. package/core/individual.bio.organs/brain.senses.subconscious/tools.ts +180 -0
  81. package/core/individual.bio.organs/brain.senses.subconscious/tools.ts.SPEC +3 -0
  82. package/core/individual.bio.organs/ears.listen/config.json +9 -0
  83. package/core/individual.bio.organs/ears.listen/config.json.CHANGELOG +1 -0
  84. package/core/individual.bio.organs/ears.listen/config.json.SPEC +3 -0
  85. package/core/individual.bio.organs/ears.listen/ears.ts.CHANGELOG +48 -0
  86. package/core/individual.bio.organs/ears.listen/ears_recorder.py.CHANGELOG +6 -0
  87. package/core/individual.bio.organs/ears.listen/index.ts +1 -0
  88. package/core/individual.bio.organs/ears.listen/index.ts.SPEC +16 -0
  89. package/core/individual.bio.organs/ears.listen/listen.ts +208 -0
  90. package/core/individual.bio.organs/ears.listen/listen.ts.SPEC +3 -0
  91. package/core/individual.bio.organs/ears.listen/listen_recorder.py +445 -0
  92. package/core/individual.bio.organs/ears.listen/listen_recorder.py.SPEC +7 -0
  93. package/core/individual.bio.organs/ears.listen/python_protogen/__init__.py +0 -0
  94. package/core/individual.bio.organs/ears.listen/python_protogen/common/__init__.py +0 -0
  95. package/core/individual.bio.organs/ears.listen/python_protogen/common/events_pb2.py +38 -0
  96. package/core/individual.bio.organs/ears.listen/python_protogen/common/events_pb2_grpc.py +24 -0
  97. package/core/individual.bio.organs/ears.listen/python_protogen/common/rpcmeta_pb2.py +42 -0
  98. package/core/individual.bio.organs/ears.listen/python_protogen/common/rpcmeta_pb2_grpc.py +24 -0
  99. package/core/individual.bio.organs/ears.listen/python_protogen/products/__init__.py +0 -0
  100. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/__init__.py +0 -0
  101. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/ast/__init__.py +0 -0
  102. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/ast/ast_service_pb2.py +45 -0
  103. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/ast/ast_service_pb2_grpc.py +97 -0
  104. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/base/__init__.py +0 -0
  105. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/base/au_base_pb2.py +80 -0
  106. package/core/individual.bio.organs/ears.listen/python_protogen/products/understanding/base/au_base_pb2_grpc.py +24 -0
  107. package/core/individual.bio.organs/hands.fileactions/authorize.TRUST +1 -0
  108. package/core/individual.bio.organs/hands.fileactions/authorize.ts +70 -0
  109. package/core/individual.bio.organs/hands.fileactions/authorize.ts.CHANGELOG +1 -0
  110. package/core/individual.bio.organs/hands.fileactions/authorize.ts.SPEC +3 -0
  111. package/core/individual.bio.organs/hands.fileactions/dir.README +13 -0
  112. package/core/individual.bio.organs/hands.fileactions/file_rules.json +23 -0
  113. package/core/individual.bio.organs/hands.fileactions/fileactions.README +12 -0
  114. package/core/individual.bio.organs/hands.fileactions/fileactions.ts +540 -0
  115. package/core/individual.bio.organs/hands.fileactions/fileactions.ts.CHANGELOG +25 -0
  116. package/core/individual.bio.organs/hands.fileactions/fileactions.ts.SPEC +30 -0
  117. package/core/individual.bio.organs/hands.fileactions/filewatch.ts +66 -0
  118. package/core/individual.bio.organs/hands.fileactions/filewatch.ts.SPEC +3 -0
  119. package/core/individual.bio.organs/hands.main/main.ts +18 -0
  120. package/core/individual.bio.organs/hands.main/main.ts.SPEC +20 -0
  121. package/core/individual.bio.organs/hands.sensitive/sensitive.ts +24 -0
  122. package/core/individual.bio.organs/hands.sensitive/sensitive.ts.CHANGELOG +2 -0
  123. package/core/individual.bio.organs/hands.sensitive/sensitive.ts.SPEC +3 -0
  124. package/core/individual.bio.organs/heart.interrupt/agent_start-loader-flicker.patch +13 -0
  125. package/core/individual.bio.organs/heart.interrupt/interactive-mode-loader.patch +11 -0
  126. package/core/individual.bio.organs/heart.interrupt/runner_esc.patch +10 -0
  127. package/core/individual.bio.organs/heart.interrupt/runner_esc.patch.SPEC +9 -0
  128. package/core/individual.bio.organs/heart.kernel/kernel.ts +253 -0
  129. package/core/individual.bio.organs/heart.kernel/kernel.ts.CHANGELOG +13 -0
  130. package/core/individual.bio.organs/heart.kernel/kernel.ts.SPEC +23 -0
  131. package/core/individual.bio.organs/heart.main/heart.main.CHANGELOG +43 -0
  132. package/core/individual.bio.organs/heart.main/heartbeat.ts +494 -0
  133. package/core/individual.bio.organs/heart.main/heartbeat.ts.LESSON +43 -0
  134. package/core/individual.bio.organs/heart.main/main.ts +8 -0
  135. package/core/individual.bio.organs/heart.main/main.ts.SPEC +19 -0
  136. package/core/individual.bio.organs/heart.main/process.ts +122 -0
  137. package/core/individual.bio.organs/heart.main/process.ts.CHANGELOG +2 -0
  138. package/core/individual.bio.organs/heart.main/process.ts.SPEC +24 -0
  139. package/core/individual.bio.organs/heart.main/remove_timeout.patch +110 -0
  140. package/core/individual.bio.organs/heart.main/stop.ts.CHANGELOG +3 -0
  141. package/core/individual.bio.organs/heart.main/stop.ts.SPEC +28 -0
  142. package/core/individual.bio.organs/mouth.speak/index.ts +1 -0
  143. package/core/individual.bio.organs/mouth.speak/index.ts.CHANGELOG +1 -0
  144. package/core/individual.bio.organs/mouth.speak/index.ts.SPEC +6 -0
  145. package/core/individual.bio.organs/mouth.speak/mouth.ts.CHANGELOG +15 -0
  146. package/core/individual.bio.organs/mouth.speak/mouth_recorder.py.CHANGELOG +1 -0
  147. package/core/individual.bio.organs/mouth.speak/speak.ts +180 -0
  148. package/core/individual.bio.organs/mouth.speak/speak.ts.SPEC +3 -0
  149. package/core/individual.bio.organs/mouth.speak/speak_recorder.py +35 -0
  150. package/core/individual.bio.organs/mouth.speak/speak_recorder.py.SPEC +3 -0
  151. package/core/individual.bio.organs/organs.README +110 -0
  152. package/core/package-lock.json +18 -0
  153. package/core/package.json +35 -0
  154. package/core/prompts/prompts.json +77 -0
  155. package/core/prompts/prompts.ts +44 -0
  156. package/core/prompts/prompts.ts.SPEC +9 -0
  157. package/core/society.world/.gitkeep +0 -0
  158. package/core/society.world/accessibility.claudecode/message-service.cjs +217 -0
  159. package/core/society.world/accessibility.claudecode/message-service.cjs.SPEC +7 -0
  160. package/core/society.world/accessibility.claudecode/send.ts +34 -0
  161. package/core/society.world/dollar.distribution.ubi/ubi.ts +55 -0
  162. package/core/society.world/dollar.main/dollar-service.cjs +185 -0
  163. package/core/society.world/dollar.main/main.ts +116 -0
  164. package/core/society.world/dollar.transaction/transaction.ts +71 -0
  165. package/core/society.world/space/space.ts +206 -0
  166. package/core/society.world/space/space.ts.SPEC +30 -0
  167. package/core/technology.laptop/#agent.macos.BLUEPRINT +278 -0
  168. package/core/technology.phone/apps.preinstalled/albums.FUTURE/albums.ts +69 -0
  169. package/core/technology.phone/apps.preinstalled/albums.FUTURE/albums.ts.SPEC +15 -0
  170. package/core/technology.phone/apps.preinstalled/calendar/calendar.ts +406 -0
  171. package/core/technology.phone/apps.preinstalled/calendar/calendar.ts.SPEC +22 -0
  172. package/core/technology.phone/apps.preinstalled/calendar/holiday-calendar.ts +529 -0
  173. package/core/technology.phone/apps.preinstalled/clock/clock.ts +132 -0
  174. package/core/technology.phone/apps.preinstalled/clock/clock.ts.SPEC +11 -0
  175. package/core/technology.phone/apps.preinstalled/contacts.FUTURE/contacts.ts +300 -0
  176. package/core/technology.phone/apps.preinstalled/contacts.FUTURE/contacts.ts.SPEC +22 -0
  177. package/core/technology.phone/apps.preinstalled/developer.FUTURE/developer.ts +22 -0
  178. package/core/technology.phone/apps.preinstalled/developer.FUTURE/developer.ts.SPEC +15 -0
  179. package/core/technology.phone/apps.preinstalled/notes/notes.ts +239 -0
  180. package/core/technology.phone/apps.preinstalled/notes/notes.ts.SPEC +21 -0
  181. package/core/technology.phone/apps.preinstalled/polymarket/polymarket.ts +261 -0
  182. package/core/technology.phone/apps.preinstalled/polymarket/polymarket.ts.SPEC +7 -0
  183. package/core/technology.phone/apps.preinstalled/reminder/reminder.ts +404 -0
  184. package/core/technology.phone/apps.preinstalled/reminder/reminder.ts.SPEC +25 -0
  185. package/core/technology.phone/apps.preinstalled/siri.FUTURE/siri.ts +22 -0
  186. package/core/technology.phone/apps.preinstalled/siri.FUTURE/siri.ts.SPEC +15 -0
  187. package/core/technology.phone/apps.preinstalled/spotlight/spotlight.ts +29 -0
  188. package/core/technology.phone/apps.preinstalled/spotlight/spotlight.ts.SPEC +7 -0
  189. package/core/technology.phone/apps.preinstalled/steam/chess.ts +230 -0
  190. package/core/technology.phone/apps.preinstalled/steam/snake.ts +100 -0
  191. package/core/technology.phone/apps.preinstalled/steam/snake.ts.SPEC +7 -0
  192. package/core/technology.phone/apps.preinstalled/steam/spy-cmd.ts +4 -0
  193. package/core/technology.phone/apps.preinstalled/steam/spy-tool.ts +56 -0
  194. package/core/technology.phone/apps.preinstalled/steam/spy.ts +302 -0
  195. package/core/technology.phone/apps.preinstalled/steam/steam.ts +299 -0
  196. package/core/technology.phone/apps.preinstalled/weather/weather.ts +50 -0
  197. package/core/technology.phone/apps.preinstalled/weather/weather.ts.SPEC +9 -0
  198. package/core/technology.phone/apps.preinstalled/wechat/imessage.ts +423 -0
  199. package/core/technology.phone/apps.preinstalled/wechat/imessage.ts.SPEC +24 -0
  200. package/core/technology.phone/apps.system/appstore/appstore.ts +22 -0
  201. package/core/technology.phone/apps.system/appstore/appstore.ts.SPEC +15 -0
  202. package/core/technology.phone/apps.system/finder.FUTURE/finder.ts +64 -0
  203. package/core/technology.phone/apps.system/finder.FUTURE/finder.ts.SPEC +8 -0
  204. package/core/technology.phone/apps.system/safari/safari-app.ts +146 -0
  205. package/core/technology.phone/apps.system/safari/safari.ts.SPEC +24 -0
  206. package/core/technology.phone/apps.system/settings/settings.ts +126 -0
  207. package/core/technology.phone/apps.system/settings/settings.ts.SPEC +17 -0
  208. package/core/technology.phone/apps.system/tips/tips.ts +22 -0
  209. package/core/technology.phone/apps.system/tips/tips.ts.SPEC +15 -0
  210. package/core/technology.phone/apps.thirdparty/alipay/alipay.ts +148 -0
  211. package/core/technology.phone/apps.thirdparty/alipay/alipay.ts.SPEC +7 -0
  212. package/core/technology.phone/apps.thirdparty/bilibili/bilibili-app.ts +33 -0
  213. package/core/technology.phone/apps.thirdparty/bilibili/bilibili.ts +142 -0
  214. package/core/technology.phone/apps.thirdparty/bilibili/bilibili.ts.SPEC +22 -0
  215. package/core/technology.phone/apps.thirdparty/wechatread/wechatread.ts +80 -0
  216. package/core/technology.phone/apps.thirdparty/wechatread/wechatread.ts.SPEC +15 -0
  217. package/core/technology.phone/index.ts +1 -0
  218. package/core/technology.phone/package.json +2 -0
  219. package/core/technology.phone/system.homepage/homepage.ts +247 -0
  220. package/core/technology.phone/system.homepage/homepage.ts.SPEC +22 -0
  221. package/core/technology.phone/system.kernel/kernel.ts +264 -0
  222. package/core/technology.phone/system.kernel/kernel.ts.SPEC +7 -0
  223. package/core/technology.phone/system.notifications/notifications.ts +87 -0
  224. package/core/technology.phone/system.notifications/notifications.ts.SPEC +7 -0
  225. package/core/technology.phone/system.share/share.ts +46 -0
  226. package/core/technology.phone/system.share/share.ts.SPEC +7 -0
  227. package/core/technology.server/browser-service.cjs +152 -0
  228. package/core/technology.server/data/cookies/arxiv.json +30 -0
  229. package/core/technology.server/data/cookies/bili.json +184 -0
  230. package/core/technology.server/data/cookies/default.json +30 -0
  231. package/core/technology.server/data/cookies/news.json +113 -0
  232. package/core/technology.server/data/cookies/s1.json +45 -0
  233. package/core/technology.server/data/cookies/safari.json +184 -0
  234. package/core/technology.server/data/cookies/safari2.json +1 -0
  235. package/core/technology.server/data/cookies/safaridbg.json +1 -0
  236. package/core/technology.server/data/cookies/search.json +45 -0
  237. package/core/technology.server/data/cookies/sw.json +30 -0
  238. package/core/technology.server/data/cookies/t1.json +1 -0
  239. package/core/technology.server/data/cookies/testread.json +1 -0
  240. package/core/technology.server/data/cookies/video1.json +113 -0
  241. package/core/technology.server/data/cookies/yt.json +170 -0
  242. package/core/technology.server/data/cookies/yt2.json +113 -0
  243. package/core/technology.server/pikipedia/#pikipedia.BLUEPRINT +106 -0
  244. package/core/technology.server/playleft.cjs +247 -0
  245. package/core/technology.server/search-proxy.py +76 -0
  246. package/core/technology.server/server.README +59 -0
  247. package/deploy/dist-overrides/cli/cli.js +18 -0
  248. package/deploy/dist-overrides/core/extensions/loader.js +518 -0
  249. package/deploy/dist-overrides/core/package-manager.js +2081 -0
  250. package/deploy/dist-overrides/core/system-prompt.js +109 -0
  251. package/deploy/dist-overrides/core/system-prompt.js.LESSON +17 -0
  252. package/deploy/dist-overrides/core/tools/bash.js +353 -0
  253. package/deploy/dist-overrides/core/tools/bash.js.CHANGELOG +2 -0
  254. package/deploy/dist-overrides/core/tools/edit-diff.js +345 -0
  255. package/deploy/dist-overrides/core/tools/edit.js +315 -0
  256. package/deploy/dist-overrides/core/tools/edit.js.CHANGELOG +1 -0
  257. package/deploy/dist-overrides/core/tools/file-mutation-queue.js +52 -0
  258. package/deploy/dist-overrides/core/tools/find.js +298 -0
  259. package/deploy/dist-overrides/core/tools/find.js.CHANGELOG +1 -0
  260. package/deploy/dist-overrides/core/tools/grep.js +305 -0
  261. package/deploy/dist-overrides/core/tools/grep.js.CHANGELOG +1 -0
  262. package/deploy/dist-overrides/core/tools/index.js +112 -0
  263. package/deploy/dist-overrides/core/tools/ls-guard.js +4 -0
  264. package/deploy/dist-overrides/core/tools/ls.js +170 -0
  265. package/deploy/dist-overrides/core/tools/ls.js.CHANGELOG +1 -0
  266. package/deploy/dist-overrides/core/tools/output-accumulator.js +184 -0
  267. package/deploy/dist-overrides/core/tools/path-utils.js +99 -0
  268. package/deploy/dist-overrides/core/tools/prompts-reader.js +53 -0
  269. package/deploy/dist-overrides/core/tools/read.js +392 -0
  270. package/deploy/dist-overrides/core/tools/read.js.CHANGELOG +1 -0
  271. package/deploy/dist-overrides/core/tools/render-utils.js +65 -0
  272. package/deploy/dist-overrides/core/tools/tool-definition-wrapper.js +34 -0
  273. package/deploy/dist-overrides/core/tools/truncate.js +215 -0
  274. package/deploy/dist-overrides/core/tools/write.js +203 -0
  275. package/deploy/dist-overrides/core/tools/write.js.CHANGELOG +1 -0
  276. package/deploy/dist-overrides/dist-overrides.README +18 -0
  277. package/deploy/dist-overrides/main.js +665 -0
  278. package/deploy/dist-overrides/modes/interactive/components/assistant-message.js +139 -0
  279. package/deploy/dist-overrides/modes/interactive/components/footer.js +326 -0
  280. package/deploy/dist-overrides/modes/interactive/components/model-selector.js +285 -0
  281. package/deploy/dist-overrides/modes/interactive/components/tool-execution.js +383 -0
  282. package/deploy/dist-overrides/modes/interactive/components/tool-execution.js.CHANGELOG +3 -0
  283. package/deploy/dist-overrides/modes/interactive/interactive-mode.js +4781 -0
  284. package/deploy/dist-overrides/pi-ai/providers/anthropic.js +931 -0
  285. package/deploy/dist-overrides/pi-ai/providers/openai-completions.js +1007 -0
  286. package/deploy/dist-overrides/pi-ai/providers/openai-completions.js.LESSON +15 -0
  287. package/deploy/dist-overrides/pi-tui/components/loader.js +69 -0
  288. package/deploy/dist-overrides/pi-tui/components/markdown.js +646 -0
  289. package/deploy/dist-overrides/pi-tui/components/text.js +92 -0
  290. package/deploy/dist-overrides/pi-tui/custom-message.js +75 -0
  291. package/deploy/dist-overrides/pi-tui/tui.js +1266 -0
  292. package/deploy/dist-overrides/pi-tui/utils.js +1060 -0
  293. package/deploy/dist-overrides/vendor.REMOVED/jiti/lib/jiti.mjs +3 -0
  294. package/deploy/install.sh +186 -0
  295. package/deploy/install.sh.CHANGELOG +6 -0
  296. package/deploy/lint/lint-naming.ts +202 -0
  297. package/deploy/scripts/apply.js +18 -0
  298. package/deploy/scripts/build-github.sh +219 -0
  299. package/deploy/scripts/build-phone.sh +24 -0
  300. package/deploy/scripts/check-deploy.sh +42 -0
  301. package/deploy/scripts/migrate-context.sh +72 -0
  302. package/deploy/scripts/patch-pi-dist.js +39 -0
  303. package/deploy/scripts/uninstall.sh +34 -0
  304. package/package.json +18 -0
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Shared diff computation utilities for the edit tool.
3
+ * Used by both edit.ts (for execution) and tool-execution.ts (for preview rendering).
4
+ */
5
+ import * as Diff from "diff";
6
+ import { constants } from "fs";
7
+ import { access, readFile } from "fs/promises";
8
+ import { resolveToCwd } from "./path-utils.js";
9
+ export function detectLineEnding(content) {
10
+ const crlfIdx = content.indexOf("\r\n");
11
+ const lfIdx = content.indexOf("\n");
12
+ if (lfIdx === -1)
13
+ return "\n";
14
+ if (crlfIdx === -1)
15
+ return "\n";
16
+ return crlfIdx < lfIdx ? "\r\n" : "\n";
17
+ }
18
+ export function normalizeToLF(text) {
19
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
20
+ }
21
+ export function restoreLineEndings(text, ending) {
22
+ return ending === "\r\n" ? text.replace(/\n/g, "\r\n") : text;
23
+ }
24
+ /**
25
+ * Normalize text for fuzzy matching. Applies progressive transformations:
26
+ * - Strip trailing whitespace from each line
27
+ * - Normalize smart quotes to ASCII equivalents
28
+ * - Normalize Unicode dashes/hyphens to ASCII hyphen
29
+ * - Normalize special Unicode spaces to regular space
30
+ */
31
+ export function normalizeForFuzzyMatch(text) {
32
+ return (text
33
+ .normalize("NFKC")
34
+ // Strip trailing whitespace per line
35
+ .split("\n")
36
+ .map((line) => line.trimEnd())
37
+ .join("\n")
38
+ // Smart single quotes → '
39
+ .replace(/[\u2018\u2019\u201A\u201B]/g, "'")
40
+ // Smart double quotes → "
41
+ .replace(/[\u201C\u201D\u201E\u201F]/g, '"')
42
+ // Various dashes/hyphens → -
43
+ // U+2010 hyphen, U+2011 non-breaking hyphen, U+2012 figure dash,
44
+ // U+2013 en-dash, U+2014 em-dash, U+2015 horizontal bar, U+2212 minus
45
+ .replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-")
46
+ // Special spaces → regular space
47
+ // U+00A0 NBSP, U+2002-U+200A various spaces, U+202F narrow NBSP,
48
+ // U+205F medium math space, U+3000 ideographic space
49
+ .replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " "));
50
+ }
51
+ /**
52
+ * Find oldText in content, trying exact match first, then fuzzy match.
53
+ * When fuzzy matching is used, the returned contentForReplacement is the
54
+ * fuzzy-normalized version of the content (trailing whitespace stripped,
55
+ * Unicode quotes/dashes normalized to ASCII).
56
+ */
57
+ export function fuzzyFindText(content, oldText) {
58
+ // Try exact match first
59
+ const exactIndex = content.indexOf(oldText);
60
+ if (exactIndex !== -1) {
61
+ return {
62
+ found: true,
63
+ index: exactIndex,
64
+ matchLength: oldText.length,
65
+ usedFuzzyMatch: false,
66
+ contentForReplacement: content,
67
+ };
68
+ }
69
+ // Try fuzzy match - work entirely in normalized space
70
+ const fuzzyContent = normalizeForFuzzyMatch(content);
71
+ const fuzzyOldText = normalizeForFuzzyMatch(oldText);
72
+ const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
73
+ if (fuzzyIndex === -1) {
74
+ return {
75
+ found: false,
76
+ index: -1,
77
+ matchLength: 0,
78
+ usedFuzzyMatch: false,
79
+ contentForReplacement: content,
80
+ };
81
+ }
82
+ // When fuzzy matching, we work in the normalized space for replacement.
83
+ // This means the output will have normalized whitespace/quotes/dashes,
84
+ // which is acceptable since we're fixing minor formatting differences anyway.
85
+ return {
86
+ found: true,
87
+ index: fuzzyIndex,
88
+ matchLength: fuzzyOldText.length,
89
+ usedFuzzyMatch: true,
90
+ contentForReplacement: fuzzyContent,
91
+ };
92
+ }
93
+ /** Strip UTF-8 BOM if present, return both the BOM (if any) and the text without it */
94
+ export function stripBom(content) {
95
+ return content.startsWith("\uFEFF") ? { bom: "\uFEFF", text: content.slice(1) } : { bom: "", text: content };
96
+ }
97
+ function countOccurrences(content, oldText) {
98
+ const fuzzyContent = normalizeForFuzzyMatch(content);
99
+ const fuzzyOldText = normalizeForFuzzyMatch(oldText);
100
+ return fuzzyContent.split(fuzzyOldText).length - 1;
101
+ }
102
+ function getNotFoundError(path, editIndex, totalEdits) {
103
+ if (totalEdits === 1) {
104
+ return new Error(`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`);
105
+ }
106
+ return new Error(`Could not find edits[${editIndex}] in ${path}. The oldText must match exactly including all whitespace and newlines.`);
107
+ }
108
+ function getDuplicateError(path, editIndex, totalEdits, occurrences) {
109
+ if (totalEdits === 1) {
110
+ return new Error(`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`);
111
+ }
112
+ return new Error(`Found ${occurrences} occurrences of edits[${editIndex}] in ${path}. Each oldText must be unique. Please provide more context to make it unique.`);
113
+ }
114
+ function getEmptyOldTextError(path, editIndex, totalEdits) {
115
+ if (totalEdits === 1) {
116
+ return new Error(`oldText must not be empty in ${path}.`);
117
+ }
118
+ return new Error(`edits[${editIndex}].oldText must not be empty in ${path}.`);
119
+ }
120
+ function getNoChangeError(path, totalEdits) {
121
+ if (totalEdits === 1) {
122
+ return new Error(`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`);
123
+ }
124
+ return new Error(`No changes made to ${path}. The replacements produced identical content.`);
125
+ }
126
+ /**
127
+ * Apply one or more exact-text replacements to LF-normalized content.
128
+ *
129
+ * All edits are matched against the same original content. Replacements are
130
+ * then applied in reverse order so offsets remain stable. If any edit needs
131
+ * fuzzy matching, the operation runs in fuzzy-normalized content space to
132
+ * preserve current single-edit behavior.
133
+ */
134
+ export function applyEditsToNormalizedContent(normalizedContent, edits, path) {
135
+ const normalizedEdits = edits.map((edit) => ({
136
+ oldText: normalizeToLF(edit.oldText),
137
+ newText: normalizeToLF(edit.newText),
138
+ }));
139
+ for (let i = 0; i < normalizedEdits.length; i++) {
140
+ if (normalizedEdits[i].oldText.length === 0) {
141
+ throw getEmptyOldTextError(path, i, normalizedEdits.length);
142
+ }
143
+ }
144
+ const initialMatches = normalizedEdits.map((edit) => fuzzyFindText(normalizedContent, edit.oldText));
145
+ const baseContent = initialMatches.some((match) => match.usedFuzzyMatch)
146
+ ? normalizeForFuzzyMatch(normalizedContent)
147
+ : normalizedContent;
148
+ const matchedEdits = [];
149
+ for (let i = 0; i < normalizedEdits.length; i++) {
150
+ const edit = normalizedEdits[i];
151
+ const matchResult = fuzzyFindText(baseContent, edit.oldText);
152
+ if (!matchResult.found) {
153
+ throw getNotFoundError(path, i, normalizedEdits.length);
154
+ }
155
+ const occurrences = countOccurrences(baseContent, edit.oldText);
156
+ if (occurrences > 1) {
157
+ throw getDuplicateError(path, i, normalizedEdits.length, occurrences);
158
+ }
159
+ matchedEdits.push({
160
+ editIndex: i,
161
+ matchIndex: matchResult.index,
162
+ matchLength: matchResult.matchLength,
163
+ newText: edit.newText,
164
+ });
165
+ }
166
+ matchedEdits.sort((a, b) => a.matchIndex - b.matchIndex);
167
+ for (let i = 1; i < matchedEdits.length; i++) {
168
+ const previous = matchedEdits[i - 1];
169
+ const current = matchedEdits[i];
170
+ if (previous.matchIndex + previous.matchLength > current.matchIndex) {
171
+ throw new Error(`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${path}. Merge them into one edit or target disjoint regions.`);
172
+ }
173
+ }
174
+ let newContent = baseContent;
175
+ for (let i = matchedEdits.length - 1; i >= 0; i--) {
176
+ const edit = matchedEdits[i];
177
+ newContent =
178
+ newContent.substring(0, edit.matchIndex) +
179
+ edit.newText +
180
+ newContent.substring(edit.matchIndex + edit.matchLength);
181
+ }
182
+ if (baseContent === newContent) {
183
+ throw getNoChangeError(path, normalizedEdits.length);
184
+ }
185
+ return { baseContent, newContent };
186
+ }
187
+ /** Generate a standard unified patch. */
188
+ export function generateUnifiedPatch(path, oldContent, newContent, contextLines = 4) {
189
+ return Diff.createTwoFilesPatch(path, path, oldContent, newContent, undefined, undefined, {
190
+ context: contextLines,
191
+ headerOptions: Diff.FILE_HEADERS_ONLY,
192
+ });
193
+ }
194
+ /**
195
+ * Generate a display-oriented diff string with line numbers and context.
196
+ * Returns both the diff string and the first changed line number (in the new file).
197
+ */
198
+ export function generateDiffString(oldContent, newContent, contextLines = 4) {
199
+ const parts = Diff.diffLines(oldContent, newContent);
200
+ const output = [];
201
+ const oldLines = oldContent.split("\n");
202
+ const newLines = newContent.split("\n");
203
+ const maxLineNum = Math.max(oldLines.length, newLines.length);
204
+ const lineNumWidth = String(maxLineNum).length;
205
+ let oldLineNum = 1;
206
+ let newLineNum = 1;
207
+ let lastWasChange = false;
208
+ let firstChangedLine;
209
+ for (let i = 0; i < parts.length; i++) {
210
+ const part = parts[i];
211
+ const raw = part.value.split("\n");
212
+ if (raw[raw.length - 1] === "") {
213
+ raw.pop();
214
+ }
215
+ if (part.added || part.removed) {
216
+ // Capture the first changed line (in the new file)
217
+ if (firstChangedLine === undefined) {
218
+ firstChangedLine = newLineNum;
219
+ }
220
+ // Show the change
221
+ for (const line of raw) {
222
+ if (part.added) {
223
+ const lineNum = String(newLineNum).padStart(lineNumWidth, " ");
224
+ output.push(`+${lineNum} ${line}`);
225
+ newLineNum++;
226
+ }
227
+ else {
228
+ // removed
229
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
230
+ output.push(`-${lineNum} ${line}`);
231
+ oldLineNum++;
232
+ }
233
+ }
234
+ lastWasChange = true;
235
+ }
236
+ else {
237
+ // Context lines - only show a few before/after changes
238
+ const nextPartIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
239
+ const hasLeadingChange = lastWasChange;
240
+ const hasTrailingChange = nextPartIsChange;
241
+ if (hasLeadingChange && hasTrailingChange) {
242
+ if (raw.length <= contextLines * 2) {
243
+ for (const line of raw) {
244
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
245
+ output.push(` ${lineNum} ${line}`);
246
+ oldLineNum++;
247
+ newLineNum++;
248
+ }
249
+ }
250
+ else {
251
+ const leadingLines = raw.slice(0, contextLines);
252
+ const trailingLines = raw.slice(raw.length - contextLines);
253
+ const skippedLines = raw.length - leadingLines.length - trailingLines.length;
254
+ for (const line of leadingLines) {
255
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
256
+ output.push(` ${lineNum} ${line}`);
257
+ oldLineNum++;
258
+ newLineNum++;
259
+ }
260
+ output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
261
+ oldLineNum += skippedLines;
262
+ newLineNum += skippedLines;
263
+ for (const line of trailingLines) {
264
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
265
+ output.push(` ${lineNum} ${line}`);
266
+ oldLineNum++;
267
+ newLineNum++;
268
+ }
269
+ }
270
+ }
271
+ else if (hasLeadingChange) {
272
+ const shownLines = raw.slice(0, contextLines);
273
+ const skippedLines = raw.length - shownLines.length;
274
+ for (const line of shownLines) {
275
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
276
+ output.push(` ${lineNum} ${line}`);
277
+ oldLineNum++;
278
+ newLineNum++;
279
+ }
280
+ if (skippedLines > 0) {
281
+ output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
282
+ oldLineNum += skippedLines;
283
+ newLineNum += skippedLines;
284
+ }
285
+ }
286
+ else if (hasTrailingChange) {
287
+ const skippedLines = Math.max(0, raw.length - contextLines);
288
+ if (skippedLines > 0) {
289
+ output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
290
+ oldLineNum += skippedLines;
291
+ newLineNum += skippedLines;
292
+ }
293
+ for (const line of raw.slice(skippedLines)) {
294
+ const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
295
+ output.push(` ${lineNum} ${line}`);
296
+ oldLineNum++;
297
+ newLineNum++;
298
+ }
299
+ }
300
+ else {
301
+ // Skip these context lines entirely
302
+ oldLineNum += raw.length;
303
+ newLineNum += raw.length;
304
+ }
305
+ lastWasChange = false;
306
+ }
307
+ }
308
+ return { diff: output.join("\n"), firstChangedLine };
309
+ }
310
+ /**
311
+ * Compute the diff for one or more edit operations without applying them.
312
+ * Used for preview rendering in the TUI before the tool executes.
313
+ */
314
+ export async function computeEditsDiff(path, edits, cwd) {
315
+ const absolutePath = resolveToCwd(path, cwd);
316
+ try {
317
+ // Check if file exists and is readable
318
+ try {
319
+ await access(absolutePath, constants.R_OK);
320
+ }
321
+ catch (error) {
322
+ const errorMessage = error instanceof Error && "code" in error ? `Error code: ${error.code}` : String(error);
323
+ return { error: `Could not edit file: ${path}. ${errorMessage}.` };
324
+ }
325
+ // Read the file
326
+ const rawContent = await readFile(absolutePath, "utf-8");
327
+ // Strip BOM before matching (LLM won't include invisible BOM in oldText)
328
+ const { text: content } = stripBom(rawContent);
329
+ const normalizedContent = normalizeToLF(content);
330
+ const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);
331
+ // Generate the diff
332
+ return generateDiffString(baseContent, newContent);
333
+ }
334
+ catch (err) {
335
+ return { error: err instanceof Error ? err.message : String(err) };
336
+ }
337
+ }
338
+ /**
339
+ * Compute the diff for a single edit operation without applying it.
340
+ * Kept as a convenience wrapper for single-edit callers.
341
+ */
342
+ export async function computeEditDiff(path, oldText, newText, cwd) {
343
+ return computeEditsDiff(path, [{ oldText, newText }], cwd);
344
+ }
345
+ //# sourceMappingURL=edit-diff.js.map
@@ -0,0 +1,315 @@
1
+ import { execFileSync } from "child_process";
2
+ import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
3
+ import { constants } from "fs";
4
+ import { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from "fs/promises";
5
+ import { Type } from "typebox";
6
+ import { renderDiff } from "../../modes/interactive/components/diff.js";
7
+ import { getToolPrompt } from "./prompts-reader.js";
8
+ import { GUTTER } from "../../modes/interactive/components/blockrender.js"; // 统一块渲染引擎:内容列(col2)
9
+ import { applyEditsToNormalizedContent, computeEditsDiff, detectLineEnding, generateDiffString, generateUnifiedPatch, normalizeToLF, restoreLineEndings, stripBom, } from "./edit-diff.js";
10
+ import { withFileMutationQueue } from "./file-mutation-queue.js";
11
+ import { resolveToCwd } from "./path-utils.js";
12
+ import { renderToolPath, str } from "./render-utils.js";
13
+ import { wrapToolDefinition } from "./tool-definition-wrapper.js";
14
+
15
+ // ── git add gate: 成功写文件后自动 git add ──
16
+ function tryGitAdd(filePath) {
17
+ try {
18
+ execFileSync("git", ["add", filePath], { timeout: 3000, stdio: "ignore" });
19
+ } catch {
20
+ // 不在 git 仓库 / git 未安装 —— 静默忽略
21
+ }
22
+ }
23
+ const replaceEDITSchema = Type.Object({
24
+ oldText: Type.String({
25
+ messageDescription: "Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.",
26
+ }),
27
+ newText: Type.String({ messageDescription: "Replacement text for this targeted edit." }),
28
+ }, { additionalProperties: false });
29
+ const editSchema = Type.Object({
30
+ path: Type.String({ messageDescription: "Path to the file to edit (relative or absolute)" }),
31
+ edits: Type.Array(replaceEDITSchema, {
32
+ messageDescription: "One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.",
33
+ }),
34
+ }, { additionalProperties: false });
35
+ const defaultEDITOperations = {
36
+ readFile: (path) => fsReadFile(path),
37
+ writeFile: (path, content) => fsWriteFile(path, content, "utf-8"),
38
+ access: (path) => fsAccess(path, constants.R_OK | constants.W_OK),
39
+ };
40
+ function prepareEDITArguments(input) {
41
+ if (!input || typeof input !== "object") {
42
+ return input;
43
+ }
44
+ const args = input;
45
+ // Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array
46
+ if (typeof args.edits === "string") {
47
+ try {
48
+ const parsed = JSON.parse(args.edits);
49
+ if (Array.isArray(parsed))
50
+ args.edits = parsed;
51
+ }
52
+ catch { }
53
+ }
54
+ // path inside edits[0] instead of top-level — hoist it
55
+ if (!args.path && Array.isArray(args.edits) && args.edits.length > 0 && args.edits[0].path) {
56
+ args.path = args.edits[0].path;
57
+ for (const e of args.edits) delete e.path;
58
+ }
59
+ const legacy = args;
60
+ if (typeof legacy.oldText !== "string" || typeof legacy.newText !== "string") {
61
+ return args;
62
+ }
63
+ const edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];
64
+ edits.push({ oldText: legacy.oldText, newText: legacy.newText });
65
+ const { oldText: _oldText, newText: _newText, ...rest } = legacy;
66
+ return { ...rest, edits };
67
+ }
68
+ function validateEDITInput(input) {
69
+ if (!Array.isArray(input.edits) || input.edits.length === 0) {
70
+ throw new Error("EDIT tool input is invalid. edits must contain at least one replacement.");
71
+ }
72
+ return { path: input.path, edits: input.edits };
73
+ }
74
+ function createEDITCallRenderComponent() {
75
+ // pi-coding-master: Box(0,0) —— paddingX=1 会把 ● Edit 顶到 col1(和别的块对不齐)、paddingY=1 加空行。归 0。
76
+ return Object.assign(new Box(0, 0, (text) => text), {
77
+ preview: undefined,
78
+ previewArgsKey: undefined,
79
+ previewPending: false,
80
+ settledError: false,
81
+ });
82
+ }
83
+ function getEDITCallRenderComponent(state, lastComponent) {
84
+ if (lastComponent instanceof Box) {
85
+ const component = lastComponent;
86
+ state.callComponent = component;
87
+ return component;
88
+ }
89
+ if (state.callComponent) {
90
+ return state.callComponent;
91
+ }
92
+ const component = createEDITCallRenderComponent();
93
+ state.callComponent = component;
94
+ return component;
95
+ }
96
+ function getRenderablePreviewInput(args) {
97
+ if (!args) {
98
+ return null;
99
+ }
100
+ const path = typeof args.path === "string" ? args.path : typeof args.file_path === "string" ? args.file_path : null;
101
+ if (!path) {
102
+ return null;
103
+ }
104
+ if (Array.isArray(args.edits) &&
105
+ args.edits.length > 0 &&
106
+ args.edits.every((edit) => typeof edit?.oldText === "string" && typeof edit?.newText === "string")) {
107
+ return { path, edits: args.edits };
108
+ }
109
+ if (typeof args.oldText === "string" && typeof args.newText === "string") {
110
+ return { path, edits: [{ oldText: args.oldText, newText: args.newText }] };
111
+ }
112
+ return null;
113
+ }
114
+ function formatEDITCall(args, theme, cwd) {
115
+ const pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);
116
+ return theme.fg("toolTitle", "● " + theme.bold("Edit")) + " " + pathDisplay;
117
+ }
118
+ function formatEDITResult(args, preview, result, theme, isError) {
119
+ const rawPath = str(args?.file_path ?? args?.path);
120
+ const previewDiff = preview && !("error" in preview) ? preview.diff : undefined;
121
+ const previewError = preview && "error" in preview ? preview.error : undefined;
122
+ if (isError) {
123
+ const errorText = result.content
124
+ .filter((c) => c.type === "text")
125
+ .map((c) => c.text || "")
126
+ .join("\n");
127
+ // pi-coding-master: 去重要容忍尾部追加 —— bioclock 给工具结果加了 "\n[time +dur]" 时间戳后缀,
128
+ // 会让 errorText !== previewError 而漏过去重,导致「No changes」在预览块和结果块各显示一遍。
129
+ // 用 startsWith 判前缀相同即视为重复,抑制结果块那一遍。
130
+ if (!errorText || errorText === previewError ||
131
+ (previewError && errorText.startsWith(previewError))) {
132
+ return undefined;
133
+ }
134
+ return theme.fg("error", errorText);
135
+ }
136
+ const resultDiff = result.details?.diff;
137
+ if (resultDiff && resultDiff !== previewDiff) {
138
+ return renderDiff(resultDiff, { filePath: rawPath ?? undefined });
139
+ }
140
+ return undefined;
141
+ }
142
+ function getEDITHeaderBg(preview, settledError, theme) {
143
+ if (preview) {
144
+ if ("error" in preview) {
145
+ return (text) => theme.bg("toolErrorBg", text);
146
+ }
147
+ return (text) => theme.bg("toolSuccessBg", text);
148
+ }
149
+ if (settledError) {
150
+ return (text) => theme.bg("toolErrorBg", text);
151
+ }
152
+ return (text) => theme.bg("toolPendingBg", text);
153
+ }
154
+ function buildEDITCallComponent(component, args, theme, cwd) {
155
+ // 透明背景,不再用底色
156
+ component.setBgFn((text) => text);
157
+ component.clear();
158
+ component.addChild(new Text(formatEDITCall(args, theme, cwd), 0, 0));
159
+ if (!component.preview) {
160
+ return component;
161
+ }
162
+ const body = "error" in component.preview ? theme.fg("error", component.preview.error) : renderDiff(component.preview.diff);
163
+ component.addChild(new Spacer(1));
164
+ component.addChild(new Text(body, GUTTER, 0)); // diff 落 col GUTTER,对齐 ● 后面的内容
165
+ return component;
166
+ }
167
+ function setEDITPreview(component, preview, argsKey) {
168
+ const current = component.preview;
169
+ const changed = current === undefined ||
170
+ ("error" in current && "error" in preview
171
+ ? current.error !== preview.error
172
+ : "error" in current !== "error" in preview) ||
173
+ (!("error" in current) &&
174
+ !("error" in preview) &&
175
+ (current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));
176
+ component.preview = preview;
177
+ component.previewArgsKey = argsKey;
178
+ component.previewPending = false;
179
+ return changed;
180
+ }
181
+ export function createEditToolDefinition(cwd, options) {
182
+ const ops = options?.operations ?? defaultEDITOperations;
183
+ return {
184
+ name: "edit",
185
+ label: "edit",
186
+ messageDescription: getToolPrompt('edit', 'messageDescription'),
187
+ promptSnippet: getToolPrompt('edit', 'snippet'),
188
+ promptGuidelines: [
189
+ "Use edit for precise changes (edits[].oldText must match exactly)",
190
+ "When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls",
191
+ "Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.",
192
+ "Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.",
193
+ ],
194
+ parameters: editSchema,
195
+ renderShell: "self",
196
+ prepareArguments: prepareEDITArguments,
197
+ async execute(_toolCallId, input, signal, onUpdate, _ctx) {
198
+ const { path, edits } = validateEDITInput(input);
199
+ const absolutePath = resolveToCwd(path, cwd);
200
+ // NORM: 禁止直接编辑 node_modules → 只能用 dist-override
201
+ if (/node_modules[\/]@earendil-works/.test(absolutePath)) throw new Error("Error: 禁止直接编辑 node_modules/@earendil-works!改动会被 npm 重装冲掉。正确做法:修改源码 → 放到 dist-overrides/ → install.sh 部署。");
202
+ try { if (onUpdate) onUpdate({ content: [{ type: "text", text: `编辑 ${edits.length} 处: ${path}` }] }); } catch {}
203
+ return withFileMutationQueue(absolutePath, async () => {
204
+ // Do not reject from an abort event listener here: that would release the
205
+ // mutation queue while an in-flight filesystem operation may still finish.
206
+ // Checking signal.aborted after each await observes the same aborts while
207
+ // keeping the queue locked until the current operation has settled.
208
+ const throwIfAborted = () => {
209
+ if (signal?.aborted)
210
+ throw new Error("Operation aborted");
211
+ };
212
+ throwIfAborted();
213
+ // Check if file exists.
214
+ try {
215
+ await ops.access(absolutePath);
216
+ }
217
+ catch (error) {
218
+ throwIfAborted();
219
+ const errorMessage = error instanceof Error && "code" in error ? `Error code: ${error.code}` : String(error);
220
+ throw new Error(`Could not edit file: ${path}. ${errorMessage}.`);
221
+ }
222
+ throwIfAborted();
223
+ try { if (onUpdate) onUpdate({ content: [{ type: "text", text: `读取: ${path}` }] }); } catch {}
224
+ // Read the file.
225
+ const buffer = await ops.readFile(absolutePath);
226
+ const rawContent = buffer.toString("utf-8");
227
+ throwIfAborted();
228
+ try { if (onUpdate) onUpdate({ content: [{ type: "text", text: `应用 ${edits.length} 处编辑...` }] }); } catch {}
229
+ // Strip BOM before matching. The model will not include an invisible BOM in oldText.
230
+ const { bom, text: content } = stripBom(rawContent);
231
+ const originalEnding = detectLineEnding(content);
232
+ const normalizedContent = normalizeToLF(content);
233
+ const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);
234
+ throwIfAborted();
235
+ const finalContent = bom + restoreLineEndings(newContent, originalEnding);
236
+ try { if (onUpdate) onUpdate({ content: [{ type: "text", text: `写入: ${path}` }] }); } catch {}
237
+ await ops.writeFile(absolutePath, finalContent);
238
+ tryGitAdd(absolutePath);
239
+ throwIfAborted();
240
+ try { if (onUpdate) onUpdate({ content: [{ type: "text", text: `生成 diff...` }] }); } catch {}
241
+ const diffResult = generateDiffString(baseContent, newContent);
242
+ const patch = generateUnifiedPatch(path, baseContent, newContent);
243
+ return {
244
+ content: [
245
+ {
246
+ type: "text",
247
+ text: `Successfully replaced ${edits.length} block(s) in ${path}.`,
248
+ },
249
+ ],
250
+ details: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },
251
+ };
252
+ });
253
+ },
254
+ renderCall(args, theme, context) {
255
+ const component = getEDITCallRenderComponent(context.state, context.lastComponent);
256
+ const previewInput = getRenderablePreviewInput(args);
257
+ const argsKey = previewInput
258
+ ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })
259
+ : undefined;
260
+ if (component.previewArgsKey !== argsKey) {
261
+ component.preview = undefined;
262
+ component.previewArgsKey = argsKey;
263
+ component.previewPending = false;
264
+ component.settledError = false;
265
+ }
266
+ if (context.argsComplete && previewInput && !component.preview && !component.previewPending) {
267
+ component.previewPending = true;
268
+ const requestKey = argsKey;
269
+ void computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {
270
+ if (component.previewArgsKey === requestKey) {
271
+ setEDITPreview(component, preview, requestKey);
272
+ context.invalidate();
273
+ }
274
+ });
275
+ }
276
+ return buildEDITCallComponent(component, args, theme, context.cwd);
277
+ },
278
+ renderResult(result, _options, theme, context) {
279
+ const callComponent = context.state.callComponent;
280
+ const previewInput = getRenderablePreviewInput(context.args);
281
+ const argsKey = previewInput
282
+ ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })
283
+ : undefined;
284
+ const typedResult = result;
285
+ const resultDiff = !context.isError ? typedResult.details?.diff : undefined;
286
+ let changed = false;
287
+ if (callComponent) {
288
+ if (typeof resultDiff === "string") {
289
+ changed =
290
+ setEDITPreview(callComponent, { diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine }, argsKey) || changed;
291
+ }
292
+ if (callComponent.settledError !== context.isError) {
293
+ callComponent.settledError = context.isError;
294
+ changed = true;
295
+ }
296
+ if (changed) {
297
+ buildEDITCallComponent(callComponent, context.args, theme, context.cwd);
298
+ }
299
+ }
300
+ const output = formatEDITResult(context.args, callComponent?.preview, typedResult, theme, context.isError);
301
+ const component = context.lastComponent ?? new Container();
302
+ component.clear();
303
+ if (!output) {
304
+ return component;
305
+ }
306
+ component.addChild(new Spacer(1));
307
+ component.addChild(new Text(output, GUTTER, 0)); // 结果落 col GUTTER,统一对齐
308
+ return component;
309
+ },
310
+ };
311
+ }
312
+ export function createEditTool(cwd, options) {
313
+ return wrapToolDefinition(createEditToolDefinition(cwd, options));
314
+ }
315
+ //# sourceMappingURL=edit.js.map
@@ -0,0 +1 @@
1
+ [2026-06-19] 工具名首字母大写