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,264 @@
1
+ #!/bin/bash
2
+ # pi — person-based launcher
3
+ MEMORY_DIR="$HOME/.pi/memory"
4
+ PLIST="$MEMORY_DIR/plist.json"
5
+ mkdir -p "$MEMORY_DIR"
6
+
7
+ # ── 单一真相源:把 DEEPSEEK_API_KEY 强制对齐到 models.json 里配的字面量 key ──
8
+ # 否则 pi 会先读环境变量(auth-storage 里 env 优先于 models.json),shell 里残留的旧 key 会盖过来 → 402。
9
+ # 这样无论 ~/.zshrc / 终端环境是什么,pi 进程(以及它 spawn 的 hc/sc/sl 小号)都用 models.json 的 key。
10
+ __DSK=$(node --input-type=commonjs -e 'try{const j=JSON.parse(require("fs").readFileSync(process.env.HOME+"/.pi/agent/models.json","utf8"));const k=j.providers&&j.providers.deepseek&&j.providers.deepseek.apiKey;if(typeof k==="string"&&!k.startsWith("$")&&k.trim())process.stdout.write(k.trim());}catch(e){}' 2>/dev/null)
11
+ [ -n "$__DSK" ] && export DEEPSEEK_API_KEY="$__DSK"
12
+ [ -f "$PLIST" ] || echo '[]' > "$PLIST"
13
+
14
+ COUNT=$(node --input-type=commonjs -e "console.log(JSON.parse(require('fs').readFileSync('$PLIST','utf8')).length)")
15
+
16
+ # Parse flags —— 认【任意位置】的模式 flag,不只开头。
17
+ # 这样 `pi --archive 18` 和 `pi 18 --archive` 都对;而且带了模式 flag 就绝不会再掉进"创建新人"
18
+ # (旧逻辑只看 $1:`pi nn --archive 18` 里 --archive 在名字后面没被认出来 → 误判成创建 nn)。
19
+ # 非模式的 --flag(如 pi 自带的 --session-dir resume 提示)→ 原样转发给真 pi。
20
+ MODE=""
21
+ ORIG=("$@")
22
+ POS=()
23
+ while [ $# -gt 0 ]; do
24
+ case "$1" in
25
+ # --msg) MODE="msg"; shift;; # message parked in v0.1-stable(代码保留,见 Readme.md.GITHUB)
26
+ --sc) MODE="sc"; shift;;
27
+ --think) MODE="think"; shift;; # 双 pane:上面对话,下面 thinking 流
28
+ --archive) MODE="archive"; shift;; # 归档一个人(从列表隐藏,不删)
29
+ --unarchive) MODE="unarchive"; shift;; # 恢复
30
+ --archived) MODE="archived"; shift;; # 看已归档的
31
+ --dev) export PI_DEV=1; shift;; # 开发模式:暴露 editcontext/issues 等调试工具
32
+ --*) exec /opt/homebrew/bin/pi "${ORIG[@]}";; # 未知 --flag → 原样转发真 pi
33
+ *) POS+=("$1"); shift;; # 位置参数(名字/序号)收集起来
34
+ esac
35
+ done
36
+ set -- "${POS[@]+"${POS[@]}"}" # 还原位置参数(空数组在 bash3.2 也安全)
37
+
38
+ NAME="$1"
39
+ shift 2>/dev/null
40
+
41
+ # ── archive 管理:归档=从列表隐藏,不删除(有意没有 delete;也不杀进程)──
42
+ if [ "$MODE" = "archived" ]; then
43
+ node --input-type=commonjs -e "
44
+ const fs=require('fs'),{execSync}=require('child_process');
45
+ let a=JSON.parse(fs.readFileSync('$PLIST','utf8')).filter(p=>p.archived);
46
+ if(!a.length){console.log('没有已归档的人。');process.exit(0);}
47
+ const now=Date.now();let ps='';try{ps=execSync('ps aux',{encoding:'utf8'});}catch{}
48
+ for(const p of a){p._active=ps.includes(p.id+'/sessions');p._ago=Math.round((now-new Date(p.lastSeen).getTime())/60000);}
49
+ a.sort((x,y)=>(y._active?1:0)-(x._active?1:0)||x._ago-y._ago); // 和恢复时的序号一致
50
+ console.log('已归档(不在主列表;pi --unarchive <序号|名字> 恢复):');
51
+ a.forEach((p,i)=>console.log(' '+String(i+1).padStart(2)+'. '+p.name+' '+p.id));
52
+ "
53
+ exit 0
54
+ fi
55
+ if [ "$MODE" = "archive" ] || [ "$MODE" = "unarchive" ]; then
56
+ if [ -z "$NAME" ]; then echo "用法: pi --$MODE <名字|序号> [更多...](可批量,序号/名字混着给都行)"; exit 1; fi
57
+ node --input-type=commonjs -e "(async()=>{
58
+ const fs=require('fs'),{execSync}=require('child_process');
59
+ const list=JSON.parse(fs.readFileSync('$PLIST','utf8'));
60
+ const mode=process.argv[1];
61
+ const targets=process.argv.slice(2); // 批量:所有位置参数都是目标(序号或名字)
62
+ const now=Date.now();let ps='';try{ps=execSync('ps aux',{encoding:'utf8'});}catch{}
63
+ // 序号必须和【你看到的列表】同一个排序(active优先+最近优先),否则归档错人(见过 nn-researcher 被误归档)。
64
+ // archive 的序号 = 主列表(非归档)里的序号;unarchive 的序号 = 'pi --archived' 里的序号。
65
+ function sorted(filterFn){
66
+ const a=list.filter(filterFn);
67
+ for(const p of a){p._active=ps.includes(p.id+'/sessions');p._ago=Math.round((now-new Date(p.lastSeen).getTime())/60000);}
68
+ a.sort((x,y)=>(y._active?1:0)-(x._active?1:0)||x._ago-y._ago);
69
+ return a;
70
+ }
71
+ // 关键:先按【同一份快照】把所有目标解析成人对象,再统一改 ——
72
+ // 否则边归档边重排,序号会错位(pi --archive 2 4 5 6 会越归档越错)。
73
+ const pool=sorted(mode==='archive' ? (x=>!x.archived) : (x=>x.archived));
74
+ const picked=new Set(); const errs=[];
75
+ for(const arg of targets){
76
+ let p=null;
77
+ if(/^[0-9]+\$/.test(arg)){ p=pool[parseInt(arg)-1]; if(!p){errs.push('序号 '+arg+' 超出'+(mode==='archive'?'当前列表':'已归档列表')+'范围');continue;} }
78
+ else { p=list.find(x=>x.name===arg); if(!p){errs.push('没找到 \"'+arg+'\"');continue;} }
79
+ picked.add(p);
80
+ }
81
+ if(!picked.size){ console.error(errs.join(';')||'没有可处理的目标。'); process.exit(1); }
82
+ const names=[...picked].map(p=>p.name).join(', ');
83
+ process.stdout.write((mode==='archive'?'归档':'恢复')+' '+names+'? [Y/n] ');
84
+ const rl=require('readline').createInterface({input:process.stdin});
85
+ const ans=await new Promise(r=>{rl.question('',a=>{rl.close();r(a)})});
86
+ if(ans&&/^n/i.test(ans)){console.log('cancelled');process.exit(0);}
87
+ for(const p of picked) p.archived=(mode==='archive');
88
+ fs.writeFileSync('$PLIST', JSON.stringify(list,null,2));
89
+ console.log((mode==='archive'?'已归档 ':'OK 已恢复 ')+[...picked].map(p=>p.name).join('、'));
90
+ if(errs.length) console.error('WARN: 跳过:'+errs.join(';'));
91
+ })();" "$MODE" "$NAME" "$@" || exit 1
92
+ exit 0
93
+ fi
94
+
95
+ if [ -z "$NAME" ] && [ -z "$MODE" ]; then
96
+ if [ "$COUNT" = "0" ]; then
97
+ echo "No people. Usage: pi <name>"
98
+ else
99
+ node --input-type=commonjs -e "
100
+ const fs = require('fs');
101
+ const Y = '\x1b[33m', G = '\x1b[32m', D = '\x1b[90m', R = '\x1b[0m';
102
+ function vw(s){let w=0;for(const c of [...s])w+=(c.codePointAt(0)>0x2E7F?2:1);return w;}
103
+ function pad(s,n){return s+' '.repeat(Math.max(0,n-vw(s)));}
104
+ const list = JSON.parse(fs.readFileSync('$PLIST','utf8')).filter(p=>!p.archived); // 归档的不显示
105
+ const now = Date.now();
106
+ const { execSync } = require('child_process');
107
+ let psOut = '';
108
+ try { psOut = execSync('ps aux', { encoding: 'utf8' }); } catch {}
109
+ for (const p of list) {
110
+ p._active = psOut.includes(p.id + '/sessions');
111
+ p._ago = Math.round((now - new Date(p.lastSeen).getTime()) / 60000);
112
+ }
113
+ list.sort((a,b) => (b._active?1:0) - (a._active?1:0) || a._ago - b._ago);
114
+ const nw = Math.max(6, ...list.map(p=>vw(p.name))) + 2;
115
+ console.log(' ' + ' ' + pad('NAME',nw) + pad('ID',12) + 'STATUS');
116
+ console.log(' ' + '─'.repeat(nw+12+20));
117
+ for (let i = 0; i < list.length; i++) {
118
+ const p = list[i];
119
+ const time = p._ago < 60 ? p._ago+'m ago' : p._ago < 1440 ? Math.round(p._ago/60)+'h ago' : Math.round(p._ago/1440)+'d ago';
120
+ const status = p._active ? G+'Active'+R : time;
121
+ const num = Y + String(i+1).padStart(2) + '.' + R;
122
+ console.log(' '+num+' '+pad(p.name,nw)+D+pad(p.id,12)+R+status);
123
+ }
124
+ console.log(D+' pi <序号|名字> 进入 · pi --archive <名字> 归档(隐藏不删) · pi --archived 看归档的'+R);
125
+ "
126
+ fi
127
+ exit 0
128
+ fi
129
+
130
+ if [ -z "$NAME" ]; then
131
+ echo "Usage: pi [--sc] <name>"
132
+ exit 1
133
+ fi
134
+
135
+ # Resolve by index or name
136
+ ENTRY=$(node --input-type=commonjs -e "
137
+ const fs = require('fs'), { execSync } = require('child_process');
138
+ const list = JSON.parse(fs.readFileSync('$PLIST','utf8')).filter(p=>!p.archived); // 归档的不参与序号/进入解析
139
+ const now = Date.now();
140
+ let psOut = '';
141
+ try { psOut = execSync('ps aux', { encoding: 'utf8' }); } catch {}
142
+ for (const p of list) {
143
+ p._active = psOut.includes(p.id + '/sessions');
144
+ p._ago = Math.round((now - new Date(p.lastSeen).getTime()) / 60000);
145
+ }
146
+ list.sort((a,b) => (b._active?1:0) - (a._active?1:0) || a._ago - b._ago);
147
+ const arg = '$NAME';
148
+ let e;
149
+ if (/^\d+$/.test(arg)) {
150
+ const i = parseInt(arg) - 1;
151
+ e = list[i];
152
+ } else {
153
+ e = list.find(p => p.name === arg);
154
+ }
155
+ if (e) console.log(JSON.stringify(e));
156
+ ")
157
+
158
+ if [ -z "$ENTRY" ]; then
159
+ if [[ "$NAME" =~ ^[0-9]+$ ]]; then
160
+ echo "序号 $NAME 不存在。运行 pi 查看列表。"
161
+ exit 1
162
+ fi
163
+ if [ -n "$MODE" ]; then
164
+ echo "\"$NAME\" not found."
165
+ exit 1
166
+ fi
167
+ if [ "$COUNT" != "0" ]; then
168
+ read -p "Create \"$NAME\"? [Y/n] " CONFIRM
169
+ case "$CONFIRM" in n|N) exit 0;; esac
170
+ fi
171
+ ID=$(node --input-type=commonjs -e "console.log(require('crypto').randomBytes(4).toString('hex'))")
172
+ mkdir -p "$MEMORY_DIR/$ID/sessions" "$MEMORY_DIR/$ID/.data"
173
+ node --input-type=commonjs -e "
174
+ const fs = require('fs');
175
+ const list = JSON.parse(fs.readFileSync('$PLIST','utf8'));
176
+ list.push({id:'$ID',name:'$NAME',created:new Date().toISOString(),lastSeen:new Date().toISOString(),note:'',model:''});
177
+ fs.writeFileSync('$PLIST',JSON.stringify(list,null,2));
178
+ "
179
+ else
180
+ ID=$(echo "$ENTRY" | node --input-type=commonjs -e "process.stdin.on('data',d=>{console.log(JSON.parse(d).id)})")
181
+ NAME=$(echo "$ENTRY" | node --input-type=commonjs -e "process.stdin.on('data',d=>{console.log(JSON.parse(d).name)})")
182
+ node --input-type=commonjs -e "
183
+ const fs = require('fs');
184
+ const list = JSON.parse(fs.readFileSync('$PLIST','utf8'));
185
+ const p = list.find(x=>x.id==='$ID');
186
+ if(p)p.lastSeen=new Date().toISOString();
187
+ fs.writeFileSync('$PLIST',JSON.stringify(list,null,2));
188
+ "
189
+ fi
190
+
191
+ DATA_DIR="$MEMORY_DIR/$ID/.data"
192
+ mkdir -p "$DATA_DIR"
193
+
194
+ case "$MODE" in
195
+ # msg) # message parked in v0.1-stable(代码保留,见 Readme.md.GITHUB)
196
+ # exec node ~/.pi/agent/extensions/message/chat.mjs "$NAME"
197
+ # ;;
198
+ sc)
199
+ TMUX_NAME="sc-$ID"
200
+ if ! tmux has-session -t "$TMUX_NAME" 2>/dev/null; then
201
+ echo "潜意识没有在运行。先用 pi $NAME 启动主 session。"
202
+ exit 0
203
+ fi
204
+ exec tmux attach -t "$TMUX_NAME" -r
205
+ ;;
206
+ think)
207
+ # dual-pane: upper=pi conversation, lower=thinking stream
208
+ THINK_LOG="$DATA_DIR/thinking.stream"
209
+ : > "$THINK_LOG"
210
+ TMUX_THINK="think-$ID"
211
+ tmux kill-session -t "$TMUX_THINK" 2>/dev/null || true
212
+ WAKEFILE="$DATA_DIR/.wake-restart"
213
+ LAST_NONCE=$(cat "$WAKEFILE" 2>/dev/null)
214
+ UPPER_SCRIPT="$DATA_DIR/.think-upper.sh"
215
+ cat > "$UPPER_SCRIPT" << 'UPPER_EOF'
216
+ #!/bin/bash
217
+ WOKE=""
218
+ while true; do
219
+ PI_ALIVE_RESTART_LOOP=1 PI_ALIVE_WOKE="$WOKE" /opt/homebrew/bin/pi --session-dir "$SESSION_DIR" "$@"
220
+ NONCE=$(cat "$WAKEFILE" 2>/dev/null)
221
+ if [ -n "$NONCE" ] && [ "$NONCE" != "$LAST_NONCE" ]; then
222
+ LAST_NONCE="$NONCE"; WOKE=1; continue
223
+ fi
224
+ break
225
+ done
226
+ UPPER_EOF
227
+ chmod +x "$UPPER_SCRIPT"
228
+ tmux new-session -d -s "$TMUX_THINK" -x "$(tput cols)" -y "$(tput lines)" \
229
+ "SESSION_DIR='$MEMORY_DIR/$ID/sessions' WAKEFILE='$WAKEFILE' LAST_NONCE='$LAST_NONCE' bash '$UPPER_SCRIPT'"
230
+ tmux split-window -t "$TMUX_THINK" -v -l 30% \
231
+ "echo 'Thinking Stream'; tail -f '$THINK_LOG' 2>/dev/null"
232
+ tmux select-pane -t "$TMUX_THINK:0.0"
233
+ exec tmux attach -t "$TMUX_THINK"
234
+ ;;
235
+ *)
236
+ # wake-restart loop (Issues.DEV/010) + mutex PID lock
237
+ PIDFILE="$DATA_DIR/.pi-main.pid"
238
+ if [ -f "$PIDFILE" ]; then
239
+ OLD_PID=$(cat "$PIDFILE" 2>/dev/null)
240
+ if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
241
+ echo "WARN: $NAME 已有主意识在跑 (PID $OLD_PID)。不能同时开两个。"
242
+ exit 1
243
+ fi
244
+ fi
245
+ echo $$ > "$PIDFILE"
246
+ trap 'rm -f "$PIDFILE"' EXIT
247
+ WAKEFILE="$DATA_DIR/.wake-restart"
248
+ LAST_NONCE=$(cat "$WAKEFILE" 2>/dev/null) # 吃掉历史残留的 nonce,避免首启误判为"睡醒"
249
+ WOKE=""
250
+ BLACKBOX="$HOME/smart-pi/pi-coding-master.DEV/Codebase/debug/god.pi.blackbox/blackbox.sh"
251
+ while true; do
252
+ if [ -x "$BLACKBOX" ]; then
253
+ PI_ALIVE_RESTART_LOOP=1 PI_ALIVE_WOKE="$WOKE" "$BLACKBOX" "$ID" "${NAME:-unknown}" "main" -- /opt/homebrew/bin/pi --session-dir "$MEMORY_DIR/$ID/sessions" "$@"
254
+ else
255
+ PI_ALIVE_RESTART_LOOP=1 PI_ALIVE_WOKE="$WOKE" /opt/homebrew/bin/pi --session-dir "$MEMORY_DIR/$ID/sessions" "$@"
256
+ fi
257
+ NONCE=$(cat "$WAKEFILE" 2>/dev/null)
258
+ if [ -n "$NONCE" ] && [ "$NONCE" != "$LAST_NONCE" ]; then
259
+ LAST_NONCE="$NONCE"; WOKE=1; continue # 睡醒重启:重新拉起,并告诉新实例"你是睡醒的"
260
+ fi
261
+ break
262
+ done
263
+ ;;
264
+ esac
@@ -0,0 +1,10 @@
1
+ # pi-people.sh — LESSONS
2
+
3
+ ## 2026-06-16 改了 deepseek key 却一直 402——环境变量优先于 models.json
4
+ **症状**:把 ~/.pi/agent/models.json 的 deepseek apiKey 换成新 key,余额闸还显示新 key 的 ¥49.99,但模型调用一直 402 "Insufficient Balance"。改 models.json、改 settings、重启、杀干净老进程,全没用。查了好几个小时、烧了好几次。
5
+
6
+ **根因**:pi 解析 key 的顺序是 `authStorage.getApiKey(provider) ?? models.json.apiKey`,而 authStorage 会先读环境变量 `DEEPSEEK_API_KEY`(auth-storage.js:427-429,env key 在 includeFallback 判断之前就 return 了)。也就是说——**环境变量里的 key 永远盖过 models.json 里配的 key。** shell(~/.zshrc)里残留的旧 key(那个负余额账号)就这么一直被用 → 402。改 models.json 是白改;连"余额闸显示新 key 余额、模型调用却 402"这种矛盾,都是因为余额闸读 models.json、模型调用走 env。
7
+
8
+ **修复**:launcher(pi-people.sh)在启动 pi 前,从 models.json 读出 deepseek 的字面量 key,强制 `export DEEPSEEK_API_KEY=<它>`。这样 pi 进程(及它 spawn 的 hc/sc/sl 小号)永远用 models.json 的 key,不依赖飘忽的 shell 环境。单一真相源 = models.json。
9
+
10
+ **教训 / 下次怎么避免**:排查"配置改了不生效"时,**先问"这个值实际从哪取、谁的优先级最高"——环境变量、凭证库(authStorage/keychain)通常优先于 config 文件里的 apiKey。** 别一头扎进 config 文件反复改、反复重启。先用一条命令把"实际用的是哪个值"打出来(如分别测两个 key),矛盾立刻现形。这次就是只盯 models.json、忘了 env 优先,白烧好几小时。
@@ -0,0 +1,31 @@
1
+ source: pi-people.sh @ 212c23d1
2
+
3
+ # pi-people.sh — Shell script for pi people management
4
+
5
+ ## 职责
6
+ pi-coding-master 的 person-based launcher:管理"人"列表(创建/列表/进入/归档/恢复),
7
+ 解析序号或名字定位人,然后以对应人的 session 目录启动真正的 pi agent 进程。
8
+
9
+ ## 接口 (CLI)
10
+ - `pi` — 列出所有人(按 active 优先 + 最近优先排序)
11
+ - `pi <名字|序号>` — 进入/创建人
12
+ - `pi --archive <名字|序号> [更多...]` — 批量归档(隐藏不删)
13
+ - `pi --unarchive <名字|序号> [更多...]` — 批量恢复
14
+ - `pi --archived` — 查看已归档列表
15
+ - `pi --sc <名字|序号>` — 只读 attach 潜意识 tmux (sc-{id})
16
+ - `pi --dev` — 设置 PI_DEV=1 开发模式
17
+ - 未知 `--flag` → 透传给 `/opt/homebrew/bin/pi`
18
+
19
+ ## 依赖
20
+ - `~/.pi/memory/plist.json` — 人列表的单一真相源
21
+ - `/opt/homebrew/bin/pi` — 底层 pi agent 二进制
22
+ - `node` (JSON 操作、crypto 生成 ID)
23
+ - `tmux` (潜意识 attach、终端会话)
24
+
25
+ ## 行为要点
26
+ - 启动前从 `models.json` 提取 DEEPSEEK_API_KEY 覆盖环境变量,防 shell 残留旧 key → 402
27
+ - 模式 flag 可在任意位置(`pi --archive 18` 和 `pi 18 --archive` 等价)
28
+ - 排序: active(ps aux 检测) 优先 → lastSeen 近的优先;序号与显示顺序一致
29
+ - 归档批量操作先在同一快照上解析所有目标再改,避免边改边重排序号错位
30
+ - 主进程有 wake-restart 循环:pi 退出后若 `.wake-restart` nonce 变化则自动重启
31
+ - PI_ALIVE_RESTART_LOOP=1 + PI_ALIVE_WOKE 环境变量控制重启闸和"睡醒"状态
@@ -0,0 +1,47 @@
1
+ // paths.ts — 全局路径常量(唯一真相源)
2
+ // 目录结构变了只改这里,其他文件全部 import { DIRS } from "#paths"
3
+
4
+ import { resolve, dirname, join } from "node:path";
5
+ import { homedir } from "node:os";
6
+
7
+ const CORE = resolve(dirname(new URL(import.meta.url).pathname), "..");
8
+ const ROOT = resolve(CORE, "../..");
9
+
10
+ export const DIRS = {
11
+ root: ROOT,
12
+ core: CORE,
13
+
14
+ organs: resolve(CORE, "individual.bio.organs"),
15
+ gene: resolve(CORE, "individual.bio.gene"),
16
+
17
+ docs: resolve(ROOT, "Docs"),
18
+ devIssues: resolve(ROOT, "Docs/Dev/Issues"),
19
+ devLessons: resolve(ROOT, "Docs/Dev/Lessons"),
20
+ devNorms: resolve(ROOT, "Docs/Dev/Norms"),
21
+
22
+ deploy: resolve(ROOT, "Codebase/deploy"),
23
+ server: resolve(CORE, "technology.server"),
24
+ browserService: process.env.PI_BROWSER || "http://localhost:9222",
25
+ } as const;
26
+
27
+ // ── person 目录解析(统一入口,不要各文件自己写)──
28
+ // personDir = ~/.pi/memory/<id>(不含 .data)
29
+ // personDataDir = ~/.pi/memory/<id>/.data
30
+ const PEOPLE_DIR = join(homedir(), ".pi/memory");
31
+
32
+ export function personDir(sessionFile: string | null | undefined): string | null {
33
+ if (!sessionFile) return null;
34
+ const m = sessionFile.match(/\.pi\/memory\/([a-f0-9]+)\//);
35
+ return m ? join(PEOPLE_DIR, m[1]) : null;
36
+ }
37
+
38
+ export function personDataDir(sessionFile: string | null | undefined): string | null {
39
+ const pd = personDir(sessionFile);
40
+ return pd ? join(pd, ".data") : null;
41
+ }
42
+
43
+ export function personId(sessionFile: string | null | undefined): string | null {
44
+ if (!sessionFile) return null;
45
+ const m = sessionFile.match(/\.pi\/memory\/([a-f0-9]+)\//);
46
+ return m ? m[1] : null;
47
+ }
@@ -0,0 +1,90 @@
1
+ // god.pi.mod/tui.mods.blockrender/blockrender.js
2
+ // ── pi-coding-master 统一块渲染引擎 (the one engine) ───────────────────────────────
3
+ // 所有「● 块」—— assistant 文字 / 思考 / 工具命令 / 工具结果 —— 统一走这里,保证:
4
+ // 1) bullet(●/○)顶格在 col 0
5
+ // 2) 内容落在 col GUTTER(=2),跨块对齐(说话、思考、命令同列)
6
+ // 3) 折行后续行也缩进到 col GUTTER(挂起缩进 / hanging indent)
7
+ //
8
+ // 谁用它(都是 import,绝不各自重写):
9
+ // - modes/interactive/components/assistant-message.js → markdownBullet(文字/思考)
10
+ // - modes/interactive/components/tool-execution.js → dot(状态点)
11
+ // - @earendil-works/pi-tui/dist/tui.js → wrapHanging(最终折行)
12
+ //
13
+ // 部署:install.sh 把本文件 cp 进 dist 两处(pi 组件目录 + pi-tui 根),
14
+ // 各处用相对 import `./blockrender.js`。源码只此一份,绝不手改 live。
15
+
16
+ export const GUTTER = 2; // 内容列:bullet "● " 占 2 列,内容从第 2 列起
17
+
18
+ // 状态点(工具用):进行=○(accent) / 错=●(error) / 成功=●(success)。统一在这里,别各处各写。
19
+ export function dot(theme, opts) {
20
+ const o = opts || {};
21
+ if (o.partial) return theme.fg("accent", "○"); // ○
22
+ if (o.error) return theme.fg("error", "●"); // ●
23
+ return theme.fg("success", "●"); // ●
24
+ }
25
+
26
+ // 把一行开头的 GUTTER 个「前导可见空格」换成 "<dot> "(dot 落 col0,内容仍在 col GUTTER)。
27
+ // 行首可能带 ANSI(颜色/背景);只动可见的前导空格,不碰样式。
28
+ export function swapLeadingPad(line, dotStr) {
29
+ const s = String(line);
30
+ const m = s.match(new RegExp("^((?:" + String.fromCharCode(27) + "\\[[0-9;]*m)*)( +)"));
31
+ if (!m || m[2].length < GUTTER) return dotStr + " " + s; // 没有足够前导空格 → 直接前置
32
+ const ansi = m[1];
33
+ const rest = s.slice(ansi.length + GUTTER); // 砍掉 GUTTER 个空格
34
+ return ansi + dotStr + " " + rest; // dot + 1 空格 = GUTTER 宽
35
+ }
36
+
37
+ // 渲染一个 markdown 块为「挂起 bullet」的行:
38
+ // md 必须是用 paddingX=GUTTER 构造好的 Markdown 实例(这样全部行——含折行——都在 col GUTTER),
39
+ // 再把首行前导空格换成 dot。→ 首行 "● 内容"、续行 " 内容",天然挂起对齐。
40
+ export function markdownBullet(md, dotStr, width) {
41
+ const lines = [...md.render(width)]; // copy: 不修改 Markdown 缓存(否则每帧重绘都会再叠加 dot)
42
+ if (lines.length > 0) lines[0] = swapLeadingPad(lines[0], dotStr);
43
+ return lines;
44
+ }
45
+
46
+ // 给【Text 组件】用的挂起折行:基于 wrapTextWithAnsi(Text 本来就用它)。
47
+ // 若行首有前缀(空白 + 可选 ●/○ bullet 及其后空格),把整行按 (width-前缀宽) 折,续行补前缀宽空格 →
48
+ // 续行和「● 后面的字」同列。无前缀则退回普通 wrapTextWithAnsi,行为不变(不影响别的 Text 用途)。
49
+ export function hangWrapText(text, width, h) {
50
+ const { visibleWidth, wrapTextWithAnsi } = h;
51
+ const stripped = String(text).replace(new RegExp(String.fromCharCode(27) + "\\[[0-9;]*m", "g"), "");
52
+ const pm = stripped.match(/^(\s*(?:[●○◌•▪]\s+)?)/);
53
+ const indW = (pm && pm[1]) ? visibleWidth(pm[1]) : 0;
54
+ if (indW <= 0 || indW >= width) return wrapTextWithAnsi(text, width);
55
+ const wrapped = wrapTextWithAnsi(text, Math.max(1, width - indW));
56
+ if (wrapped.length <= 1) return wrapped;
57
+ const indent = " ".repeat(indW);
58
+ return wrapped.map((ln, i) => (i === 0 ? ln : indent + ln));
59
+ }
60
+
61
+ // 挂起缩进折行:超宽行折行时,续行缩进到「行首前缀」之后。
62
+ // 前缀 = 行首空白 + 可选的 ●/○ bullet 及其后空格 → 续行和「● 后面的字」同列。
63
+ // pi-tui 的宽度/切片 helper 跨包不同,由调用方注入 h = {visibleWidth, sliceWithWidth, sliceByColumn, isImageLine}。
64
+ export function wrapHanging(lines, width, h) {
65
+ if (!Array.isArray(lines) || width <= 0) return lines;
66
+ const { visibleWidth, sliceWithWidth, sliceByColumn, isImageLine } = h;
67
+ let need = false;
68
+ for (const l of lines) {
69
+ if (typeof l === "string" && !isImageLine(l) && visibleWidth(l) > width) { need = true; break; }
70
+ }
71
+ if (!need) return lines;
72
+ const out = [];
73
+ for (const line of lines) {
74
+ if (typeof line !== "string" || isImageLine(line) || visibleWidth(line) <= width) { out.push(line); continue; }
75
+ const stripped = line.replace(new RegExp(String.fromCharCode(27) + "\\[[0-9;]*m", "g"), "");
76
+ const pm = stripped.match(/^(\s*(?:[●○◌•▪]\s+)?)/);
77
+ const indW = pm && pm[1] ? visibleWidth(pm[1]) : 0;
78
+ const indent = (indW > 0 && indW < width) ? " ".repeat(indW) : "";
79
+ let col = 0; const total = visibleWidth(line); let first = true;
80
+ while (col < total) {
81
+ const avail = first ? width : Math.max(1, width - indent.length);
82
+ const seg = sliceWithWidth(line, col, avail, true);
83
+ if (!seg || seg.width <= 0) { out.push((first ? "" : indent) + sliceByColumn(line, col, avail, true)); break; }
84
+ out.push((first ? "" : indent) + seg.text);
85
+ col += seg.width;
86
+ first = false;
87
+ }
88
+ }
89
+ return out;
90
+ }
@@ -0,0 +1,29 @@
1
+ source: blockrender.js
2
+
3
+ # blockrender.js — pi-coding-master 统一块渲染引擎
4
+
5
+ ## 职责
6
+ 所有「● 块」—— assistant 文字/思考/工具命令/工具结果 —— 的统一渲染引擎。
7
+ 保证 bullet 顶格 col 0、内容落 col GUTTER(=2)、折行挂起缩进到内容列。
8
+
9
+ ## 导出
10
+ - `GUTTER = 2` — 内容列偏移量
11
+ - `dot(theme, opts)` — 状态点:进行=○(accent) / 错=●(error) / 成功=●(success)
12
+ - `swapLeadingPad(line, dotStr)` — 把行首 GUTTER 个空格换成 "dot "
13
+ - `markdownBullet(md, dotStr, width)` — Markdown 块渲染为挂起 bullet
14
+ - `hangWrapText(text, width, h)` — Text 组件挂起折行
15
+ - `wrapHanging(lines, width, h)` — 超宽行挂起缩进折行
16
+
17
+ ## 依赖
18
+ - 调用方注入 `h = {visibleWidth, sliceWithWidth, sliceByColumn, isImageLine}`(跨包共享,不硬依赖)
19
+
20
+ ## 部署
21
+ 源码只此一份(god 域),install.sh cp 到两处:
22
+ 1. `pi-dist/modes/interactive/components/blockrender.js`(组件目录)
23
+ 2. `pi-tui-dist/blockrender.js`(pi-tui 根)
24
+ 各处用相对 import `./blockrender.js`。绝不手改 live。
25
+
26
+ ## 行为要点
27
+ - ANSI 剥离统一用 `String.fromCharCode(27)`,不用字面 ESC 字节
28
+ - `wrapHanging` 只有 `visibleWidth(line) > width` 时才折行,否则原样返回
29
+ - 行首前缀检测:空白 + 可选 ●/○ 及其后空格,折行续行缩进到前缀宽
@@ -0,0 +1,154 @@
1
+ // tui.mods.footer.budget/budget_guard.ts
2
+ // ── 余额硬闸(代码强制,不靠模型自觉)─────────────────────────────────────────
3
+ // 盯 deepseek 的【真实余额】(api.deepseek.com/user/balance) 当地面真值——它免疫我们的
4
+ // mid-stream abort 补丁(pi 内部 usage 会把 abort 的流记成 0,系统性少算),也覆盖所有实例。
5
+ //
6
+ // 两道线:
7
+ // 1) 余额地板线 FLOOR:余额 ≤ FLOOR → 停(保证永远不会无声烧到 0)。
8
+ // 2) 速率线 RATE:两次轮询间烧钱速率 > RATE(¥/min) → 停(专抓"一下子 100 块"那种尖峰)。
9
+ // 触发后:连所有小号(pi-coding-master:hippocampus/subconscious/sleep)一起杀 + 显眼告警 + 拦住后续 turn。
10
+ // 解除只能人工:/budget resume(充值后)。模型没有任何工具能绕过。
11
+ //
12
+ // 余额轮询结果写到 ~/.pi/agent/.pi-coding-master-balance.json,footer 读它显示"花费 + 真实余额"。
13
+
14
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
15
+ import { execSync } from "node:child_process";
16
+ import { writeFileSync, readFileSync } from "node:fs";
17
+ import { homedir } from "node:os";
18
+ import { join } from "node:path";
19
+ import * as rt from "#runtime";
20
+
21
+ const BAL_URL = "https://api.deepseek.com/user/balance";
22
+ const BAL_FILE = join(homedir(), ".pi/agent/.pi-coding-master-balance.json");
23
+
24
+ // 可配(env 覆盖),默认值保守
25
+ const FLOOR = Number(process.env.PI_ALIVE_BALANCE_FLOOR ?? 5); // 余额地板线 CNY
26
+ const RATE_LIMIT = Number(process.env.PI_ALIVE_RATE_CNY_PER_MIN ?? 10); // 速率上限 CNY/min
27
+ const POLL_MS = Number(process.env.PI_ALIVE_BALANCE_POLL_MS ?? 45000); // 轮询间隔
28
+
29
+ // deepseek 的 key 从 models.json 取(支持 $ENV 或字面量)——换 key 只改 models.json 一处,余额闸自动跟上。
30
+ function deepseekKey(): string | null {
31
+ try {
32
+ const cfg = JSON.parse(readFileSync(join(homedir(), ".pi/agent/models.json"), "utf8"));
33
+ let k = cfg?.providers?.deepseek?.apiKey;
34
+ if (typeof k === "string" && k.startsWith("$")) k = process.env[k.slice(1)] ?? "";
35
+ if (typeof k === "string" && k.trim()) return k.trim();
36
+ } catch {}
37
+ return process.env.DEEPSEEK_API_KEY || null;
38
+ }
39
+
40
+ // 同步取真实余额(curl);key 经 env 注入子进程(不写进命令字符串,ps 看不到)。
41
+ function fetchBalanceCNY(): number | null {
42
+ const key = deepseekKey();
43
+ if (!key) return null;
44
+ try {
45
+ const out = execSync(
46
+ `curl -s --max-time 15 ${BAL_URL} -H "Authorization: Bearer $DSK"`,
47
+ { encoding: "utf8", env: { ...process.env, DSK: key }, stdio: ["ignore", "pipe", "ignore"] },
48
+ );
49
+ const j = JSON.parse(out);
50
+ const b = (j?.balance_infos ?? []).find((x: any) => x.currency === "CNY") ?? j?.balance_infos?.[0];
51
+ return b ? Number(b.total_balance) : null;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ export function installBudgetGuard(pi: ExtensionAPI) {
58
+ let balance: number | null = null;
59
+ let balanceTs = 0;
60
+ let ratePerMin = 0;
61
+ let tripped: string | null = null; // null=正常;否则=触发原因
62
+ let personDataDir: string | null = null; // 本人 .data 目录,写 cost-<role>.json 用
63
+ // 当前模型的 provider —— 只有 "deepseek" 直连才受这个 deepseek 余额闸约束。
64
+ // 换到 siliconflow / zhipu 等:这个 deepseek 余额跟它们的钱包无关,不拦。
65
+ let activeProvider: string | null = null;
66
+ const readProvider = (ctx: any): string | null => {
67
+ try {
68
+ return ctx?.getModel?.()?.provider
69
+ ?? ctx?.sessionManager?.getModel?.()?.provider
70
+ ?? ctx?.settingsManager?.getDefaultProvider?.()
71
+ ?? null;
72
+ } catch { return null; }
73
+ };
74
+
75
+ function killWorkers() {
76
+ for (const role of ["hippocampus", "subconscious", "sleep"]) {
77
+ try { execSync(`pkill -f "pi-coding-master:${role}:"`, { stdio: "ignore" }); } catch {}
78
+ }
79
+ // tmux 兜底(连 bash 自愈循环一起杀)
80
+ try {
81
+ execSync(`tmux ls 2>/dev/null | grep -oE '^(hc|sc|sl)-[a-z0-9]+' | while read s; do tmux kill-session -t "$s" 2>/dev/null; done`, { stdio: "ignore" });
82
+ } catch {}
83
+ }
84
+
85
+ function trip(reason: string) {
86
+ if (tripped) return;
87
+ tripped = reason;
88
+ if (rt.getSessionRole() === "main") killWorkers(); // 只让 main 去杀小号,避免多实例乱杀
89
+ try {
90
+ // 缓存铁律:这条含会变的余额数字。绝不能用 steer/插到消息流前面 ——
91
+ // 开局即触发(poll 启动即查)时它会垫在【90万 token 快照】前面,前缀一变 → 整份快照每次重启全 cache miss。
92
+ // 改用 nextTurn 垫到尾部(像 continuous-date 那样),快照永远是稳定的第一条消息。即时可见性由 before_agent_start 的 setWorkingMessage 负责。
93
+ pi.sendMessage(
94
+ { messageType: "budget-trip", content: `余额硬闸触发:${reason}。已连后台小号一起停。充值后 /budget resume 解除。`, display: true },
95
+ { deliverAs: "nextTurn", isTriggerNewTurn: false },
96
+ );
97
+ } catch {}
98
+ }
99
+
100
+ function poll(): void {
101
+ const b = fetchBalanceCNY();
102
+ if (b === null) return;
103
+ const now = Date.now();
104
+ if (balance !== null && balanceTs > 0) {
105
+ const dtMin = (now - balanceTs) / 60000;
106
+ if (dtMin >= 0.1) ratePerMin = Math.max(0, (balance - b) / dtMin); // 掉了多少 ¥/min
107
+ }
108
+ balance = b;
109
+ balanceTs = now;
110
+ try { writeFileSync(BAL_FILE, JSON.stringify({ balance: b, ratePerMin: +ratePerMin.toFixed(2), tripped, ts: now })); } catch {}
111
+ // 只在「快烧穿」时硬停(防烧穿)。速率只测量+显示,【不拦】——他们本来就烧得快,不该限制工作。
112
+ // 只有当前在用 deepseek 直连时才拦;换了 siliconflow/zhipu 等,这个 deepseek 余额与之无关 → 绝不拦。
113
+ if (activeProvider === "deepseek" && b <= FLOOR) trip(`余额 ¥${b.toFixed(2)} ≤ 地板 ¥${FLOOR}(防烧穿)`);
114
+ }
115
+
116
+ // ── turn 前硬拦 ─────────────────────────────────────────────
117
+ pi.on("before_agent_start", async (_event, ctx) => {
118
+ activeProvider = readProvider(ctx) ?? activeProvider;
119
+ // 换到非 deepseek(siliconflow/zhipu…)→ 自动解除 deepseek 余额闸:它跟别家钱包无关,不该拦。
120
+ if (tripped && activeProvider !== "deepseek") tripped = null;
121
+ if (tripped) { // 到这只剩「在用 deepseek 且确实触发」
122
+ try { (ctx as any)?.abort?.(); } catch {}
123
+ try { ctx.ui?.setWorkingMessage?.(`余额闸已停:${tripped}(充值后 /budget resume)`); } catch {}
124
+ return; // 不继续、不注入
125
+ }
126
+ if (activeProvider === "deepseek" && Date.now() - balanceTs > POLL_MS) poll(); // 只有 deepseek 才需要补查余额
127
+ });
128
+
129
+ // 定时轮询 + 启动即查
130
+ const timer = setInterval(poll, POLL_MS);
131
+ if ((timer as any).unref) (timer as any).unref();
132
+ pi.on("session_start", async (_e, ctx) => {
133
+ const id = (ctx as any).sessionManager?.getSessionFile?.()?.match(/\.pi\/memory\/([a-f0-9]+)\//)?.[1];
134
+ personDataDir = id ? join(homedir(), ".pi/memory", id, ".data") : null;
135
+ activeProvider = readProvider(ctx) ?? activeProvider;
136
+ poll(); // 只有当前是 deepseek 时 poll 内才会 trip(见上面的 provider 判断)
137
+ });
138
+ pi.on("session_shutdown", async () => { clearInterval(timer); });
139
+
140
+ // ── 各实例把自己这一 session 的累计花费写到本人 .data/cost-<role>.json ───────
141
+ // 主进程 footer 读 main/hc/sc 三份【分别显示】(不累加)。注意:这是 pi 自己算的花费,
142
+ // 因 abort 流不计而偏低,只作各实例相对参考;账户真实总额看余额接口。
143
+ pi.on("turn_end", async (_e, ctx) => {
144
+ if (!personDataDir) return;
145
+ let cost = 0;
146
+ try {
147
+ const entries = (ctx as any).sessionManager?.getEntries?.() ?? (ctx as any).sessionManager?.getBranch?.() ?? [];
148
+ for (const e of entries) { const u = (e?.message ?? e)?.usage; if (u?.cost?.total) cost += u.cost.total; }
149
+ } catch {}
150
+ const role = rt.getSessionRole();
151
+ try { writeFileSync(join(personDataDir, `cost-${role}.json`), JSON.stringify({ role, cost: +cost.toFixed(4), ts: Date.now() })); } catch {}
152
+ });
153
+
154
+ }
@@ -0,0 +1,10 @@
1
+ [2026-06-15] created, by Claude Code
2
+ - 新增余额硬闸(代码强制):盯 deepseek 真实余额(地面真值,免疫 mid-stream abort 导致的 pi 内部少算);
3
+ 余额 ≤ FLOOR 或 烧钱速率 > RATE → 连小号(按 title pkill)一起停 + 显眼告警 + turn 前拦截;/budget 查看、resume 解除。
4
+ - 轮询写 ~/.pi/agent/.pi-coding-master-balance.json 供 footer 显示真实余额。详见 budget-guard.ts.SPEC。
5
+
6
+ [2026-06-15 续] 改成"只防烧穿"+ 各实例写花费
7
+ - 撤掉速率线 trip:用户明确"不能限制他们认真干活"。现在【只在余额 ≤ FLOOR 时硬停】(防烧穿);
8
+ 速率(ratePerMin)只测量+写文件+/budget 显示,【不再拦】。
9
+ - turn_end 各实例把自己 session 的累计花费写本人 .data/cost-<role>.json(main/hc/sc 分别)。
10
+ ⚠️ 这是 pi 自己算的,因 abort 流不计而偏低,只作相对参考;账户真实总额/速率看余额接口。