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,122 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import { Type } from "@sinclair/typebox";
3
+ import { getPrompt } from "#runtime";
4
+ import { createRequire } from "node:module";
5
+ import { sendCustomMessage } from "#messages";
6
+ const require = createRequire(import.meta.url);
7
+
8
+ const PROMPT = getPrompt("heart.commands");
9
+ const BG_THRESHOLD_MS = 1000;
10
+
11
+ interface RunningCmd {
12
+ command: string;
13
+ abort: AbortController;
14
+ startTime: number;
15
+ killedByUser: boolean;
16
+ context: string;
17
+ }
18
+
19
+ export function registerProcess(pi: ExtensionAPI) {
20
+ let nextId = 1;
21
+ let _lastCmd = "";
22
+ const running = new Map<number, RunningCmd>();
23
+
24
+ pi.on("before_agent_start", async (event) => {
25
+ try {
26
+ const active = pi.getActiveTools();
27
+ if (active.includes("bash")) pi.setActiveTools(active.filter((n: string) => n !== "bash"));
28
+ } catch {}
29
+ return { systemPrompt: event.systemPrompt + "\n\n" + PROMPT };
30
+ });
31
+
32
+ pi.registerTool({
33
+ name: "execute",
34
+ label: "Execute",
35
+ messageDescription: "Execute a shell command. Fast commands return immediately. Slow commands auto-background.",
36
+ promptSnippet: "Execute shell command",
37
+ parameters: Type.Object({
38
+ command: Type.String({ messageDescription: "Shell command to execute" }),
39
+ }),
40
+ renderCall(args: any, theme: any) {
41
+ const { Text } = require("@earendil-works/pi-tui");
42
+ const cmd = args?.command || _lastCmd || "...";
43
+ return new Text(theme.fg("toolTitle", theme.bold("● Execute ")) + theme.fg("text", cmd), 0, 0);
44
+ },
45
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
46
+ const cmd = params.command;
47
+ _lastCmd = cmd.split("\n")[0].slice(0, 80);
48
+
49
+ if (/^\s*sleep\s+[\d.]+\s*$/.test(cmd) || /(^|&&|;|\|)\s*sleep\s+[\d.]+(\s*&&|\s*;|\s*\||$)/.test(cmd)) {
50
+ return { content: [{ type: "text", text: "Sleep blocked" }], details: { blocked: true }, isError: true };
51
+ }
52
+ // NORM-009: 禁写 + execute ls 触发 markLs
53
+ if (/(>\s+\S|>>\s+\S|tee\s+\S|dd\s+.*\bof=|\bsed\s+.*-i|\bcp\b|\bmv\b|\bmkdir\b|\btouch\b|\brm\b|\bchmod\b|\bchown\b|\bnpx\b|\bnpm\s+(i|install)|\bwget\b|\bcurl\b.*-[oO])/i.test(cmd)) {
54
+ return { content: [{ type: "text", text: "execute 禁写。用 edit 修改文件,write 创建新文件。" }], details: { blocked: true }, isError: true };
55
+ }
56
+ if (/^ls\s+/.test(cmd)) { global.__ls_dir = cmd.replace(/^ls\s+/, "").trim(); }
57
+
58
+ const ac = new AbortController();
59
+ const startTime = Date.now();
60
+ const execPromise = pi.exec("bash", ["-c", cmd], { signal: ac.signal });
61
+
62
+ const race = await Promise.race([
63
+ execPromise.then(r => ({ done: true as const, result: r })),
64
+ new Promise<{ done: false }>(resolve => setTimeout(() => resolve({ done: false }), BG_THRESHOLD_MS)),
65
+ ]);
66
+
67
+ if (race.done) {
68
+ const r = race.result;
69
+ const output = [r.stdout, r.stderr].filter(Boolean).join("\n").slice(0, 50000);
70
+ const exitInfo = r.code !== 0 ? `\n(exit ${r.code})` : "";
71
+ return {
72
+ content: [{ type: "text", text: `${output || "(no output)"}${exitInfo}` }],
73
+ details: { exitCode: r.code },
74
+ };
75
+ }
76
+
77
+ const id = nextId++;
78
+ let context = "";
79
+ try {
80
+ const msgs = _ctx.sessionManager?.getBranch?.() ?? [];
81
+ const recent = msgs.slice(-5);
82
+ context = recent.map((e: any) => {
83
+ const m = e.message ?? e;
84
+ const role = m.role ?? e.type ?? "?";
85
+ const text = typeof m.content === "string" ? m.content
86
+ : Array.isArray(m.content) ? m.content.filter((c: any) => c.type === "text").map((c: any) => c.text).join(" ") : "";
87
+ return `[${role}] ${text.slice(0, 100)}`;
88
+ }).filter(Boolean).join("\n");
89
+ } catch {}
90
+ running.set(id, { command: cmd, abort: ac, startTime, killedByUser: false, context });
91
+
92
+ (async () => {
93
+ try {
94
+ const r = await execPromise;
95
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
96
+ const output = [r.stdout, r.stderr].filter(Boolean).join("\n").slice(0, 50000);
97
+ try {
98
+ pi.sendMessage(
99
+ { messageType: "continuous-cmd-done", content: `完成 (${elapsed}s, exit ${r.code}):\n$ ${cmd}\n${output || "(no output)"}`, isDisplayedInTUI: false },
100
+ { deliverAs: "steer", isTriggerNewTurn: true }
101
+ );
102
+ } catch {}
103
+ } catch (err: any) {
104
+ const elapsed = Math.round((Date.now() - startTime) / 1000);
105
+ const entry = running.get(id);
106
+ const msg = entry?.killedByUser
107
+ ? `Command killed by user (${elapsed}s):\n$ ${cmd}`
108
+ : `Command failed (${elapsed}s):\n$ ${cmd}\n${err?.message ?? err}`;
109
+ try { sendCustomMessage(pi, "continuous-cmd-done", msg); } catch {}
110
+ } finally {
111
+ running.delete(id);
112
+ }
113
+ })();
114
+
115
+ return {
116
+ content: [{ type: "text", text: `Running in background (${running.size} running). Keep working.` }],
117
+ details: {},
118
+ };
119
+ },
120
+ });
121
+
122
+ }
@@ -0,0 +1,2 @@
1
+ [2026-06-15] by Claude Code
2
+ - PROMPT([COMMANDS]/run 工具说明) 改为 getPrompt("heart.commands"),从 coded.dna 取,不再硬编码。
@@ -0,0 +1,24 @@
1
+ source: process.ts @ 9b1311d4
2
+
3
+ # process.ts — Background process runner: run tool + /monitor + /restart
4
+
5
+ ## 职责
6
+ Registers the `run` tool for shell command execution with automatic backgrounding: fast commands (<1s) return inline, slow commands auto-background and notify via steer message on completion. Also provides /monitor (view running commands) and /restart (deploy + kill + restart).
7
+
8
+ ## 接口
9
+ - `registerProcess(pi: ExtensionAPI): void` — installs run tool, /monitor, /restart
10
+
11
+ ## 依赖
12
+ - `#runtime` (getPrompt for "heart.commands")
13
+ - `typebox` (Type)
14
+ - `@mariozechner/pi-coding-agent` (ExtensionAPI)
15
+
16
+ ## 行为要点
17
+ - **run tool**: executes via `pi.exec("bash", ["-c", cmd])` with AbortController
18
+ - **Auto-background**: races exec against 1s timeout; fast results return inline, slow ones get tracked in a Map and report completion via messageType "unstop-cmd-done" steer message
19
+ - **sleep blocking**: rejects bare `sleep N` commands (waiting is built-in, sleeping = idle)
20
+ - **Context capture**: stores last 5 messages as context when backgrounding (shown in /monitor)
21
+ - **Output cap**: stdout+stderr truncated to 50KB
22
+ - **/monitor command**: lists running commands with elapsed time, select to preview context
23
+ - **/restart command**: copies dist-override files to pi dist, clears jiti cache, kills all pi-coding-master processes for the person, then exits (hardcoded personId "8cbde57b")
24
+ - Injects "heart.commands" prompt via before_agent_start
@@ -0,0 +1,110 @@
1
+ --- /tmp/pi-orig/package/dist/core/tools/bash.js 1985-10-26 16:15:00
2
+ +++ /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js 2026-06-20 02:02:35
3
+ @@ -13,8 +13,8 @@
4
+ import { wrapToolDefinition } from "./tool-definition-wrapper.js";
5
+ import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "./truncate.js";
6
+ const bashSchema = Type.Object({
7
+ - command: Type.String({ messageDescription: "Bash command to execute" }),
8
+ - timeout: Type.Optional(Type.Number({ messageDescription: "Timeout in seconds (optional, no default timeout)" })),
9
+ + command: Type.String({ messageDescription: "BASH command to execute" }),
10
+ +
11
+ });
12
+ /**
13
+ * Create bash operations using pi's built-in local shell execution backend.
14
+ @@ -97,7 +97,7 @@
15
+ }
16
+ const BASH_PREVIEW_LINES = 5;
17
+ const BASH_UPDATE_THROTTLE_MS = 100;
18
+ -class BashResultRenderComponent extends Container {
19
+ +class BASHResultRenderComponent extends Container {
20
+ state = {
21
+ cachedWidth: undefined,
22
+ cachedLines: undefined,
23
+ @@ -107,14 +107,14 @@
24
+ function formatDuration(ms) {
25
+ return `${(ms / 1000).toFixed(1)}s`;
26
+ }
27
+ -function formatBashCall(args) {
28
+ +function formatBASHCall(args) {
29
+ const command = str(args?.command);
30
+ const timeout = args?.timeout;
31
+ const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
32
+ const commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg("toolOutput", "...");
33
+ - return theme.fg("toolTitle", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;
34
+ + return theme.fg("toolTitle", "● " + theme.bold("Bash")) + " " + theme.fg("text", command) + timeoutSuffix;
35
+ }
36
+ -function rebuildBashResultRenderComponent(component, result, options, showImages, startedAt, endedAt) {
37
+ +function rebuildBASHResultRenderComponent(component, result, options, showImages, startedAt, endedAt) {
38
+ const state = component.state;
39
+ component.clear();
40
+ let output = getTextOutput(result, showImages).trim();
41
+ @@ -131,8 +131,8 @@
42
+ .split("\n")
43
+ .map((line) => theme.fg("toolOutput", line))
44
+ .join("\n");
45
+ - if (options.expanded) {
46
+ - component.addChild(new Text(`\n${styledOutput}`, 0, 0));
47
+ + if (options.expanded) {
48
+ + component.addChild(new Text(styledOutput, 2, 0));
49
+ }
50
+ else {
51
+ component.addChild({
52
+ @@ -146,9 +146,9 @@
53
+ if (state.cachedSkipped && state.cachedSkipped > 0) {
54
+ const hint = theme.fg("muted", `... (${state.cachedSkipped} earlier lines,`) +
55
+ ` ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
56
+ - return ["", truncateToWidth(hint, width, "..."), ...(state.cachedLines ?? [])];
57
+ + return [truncateToWidth(hint, width, "..."), ...(state.cachedLines ?? []).map(l => " " + l)];
58
+ }
59
+ - return ["", ...(state.cachedLines ?? [])];
60
+ + return [...(state.cachedLines ?? []).map(l => " " + l)];
61
+ },
62
+ invalidate: () => {
63
+ state.cachedWidth = undefined;
64
+ @@ -173,11 +173,7 @@
65
+ }
66
+ component.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
67
+ }
68
+ - if (startedAt !== undefined) {
69
+ - const label = options.isPartial ? "Elapsed" : "Took";
70
+ - const endTime = endedAt ?? Date.now();
71
+ - component.addChild(new Text(`\n${theme.fg("muted", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));
72
+ - }
73
+ + // pi-coding-master: 去掉 "Took/Elapsed Xs" —— 结果行的时间戳 [时:分:秒 +Xs] 已经显示了耗时,这行是重复的(用户嫌)。
74
+ }
75
+ export function createBashToolDefinition(cwd, options) {
76
+ const ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });
77
+ @@ -186,10 +182,11 @@
78
+ return {
79
+ name: "bash",
80
+ label: "bash",
81
+ - messageDescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,
82
+ + messageDescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. For long commands use run() tool.`,
83
+ promptSnippet: "Execute bash commands (ls, grep, find, etc.)",
84
+ parameters: bashSchema,
85
+ - async execute(_toolCallId, { command, timeout }, signal, onUpdate, _ctx) {
86
+ + async execute(_toolCallId, { command }, signal, onUpdate, _ctx) {
87
+ + const timeout = undefined;
88
+ const resolvedCommand = commandPrefix ? `${commandPrefix}\n${command}` : command;
89
+ const spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);
90
+ const output = new OutputAccumulator({ tempFilePrefix: "pi-bash" });
91
+ @@ -309,7 +306,7 @@
92
+ state.endedAt = undefined;
93
+ }
94
+ const text = context.lastComponent ?? new Text("", 0, 0);
95
+ - text.setText(formatBashCall(args));
96
+ + text.setText(formatBASHCall(args));
97
+ return text;
98
+ },
99
+ renderResult(result, options, _theme, context) {
100
+ @@ -324,8 +321,8 @@
101
+ state.interval = undefined;
102
+ }
103
+ }
104
+ - const component = context.lastComponent ?? new BashResultRenderComponent();
105
+ - rebuildBashResultRenderComponent(component, result, options, context.showImages, state.startedAt, state.endedAt);
106
+ + const component = context.lastComponent ?? new BASHResultRenderComponent();
107
+ + rebuildBASHResultRenderComponent(component, result, options, context.showImages, state.startedAt, state.endedAt);
108
+ component.invalidate();
109
+ return component;
110
+ },
@@ -0,0 +1,3 @@
1
+ [2026-06-15] by Claude Code
2
+ - PROMPT([CONTINUOUS AGENT]/wait·hibernate 说明) 改为 getPrompt("heart.continuous"),从 coded.dna 取,不再硬编码。
3
+ [2026-06-15 22:45:52] edited (auto-logged, no messageDescription)
@@ -0,0 +1,28 @@
1
+ source: stop.ts @ 9033e8a7
2
+
3
+ # stop.ts — Continuous/unstop mechanism: wait, hibernate, auto-continue
4
+
5
+ ## 职责
6
+ Implements the "never truly stop" continuous execution loop. Registers wait/hibernate tools and /unstop command. On agent_end, auto-sends a follow-up message to keep the agent alive. Manages hibernate (deep rest, wakeable by user/voice), wait (timed pause with countdown), and Esc hard-stop.
7
+
8
+ ## 接口
9
+ - `registerStop(pi: ExtensionAPI, state: UnstopState): void` — installs all hooks/tools/commands
10
+ - `UnstopState` interface: `{ enabled, maxCount, count, timeLimitMs, startTime }`
11
+
12
+ ## 依赖
13
+ - `#runtime` (getPrompt, getSessionRole)
14
+ - `typebox` (Type), `node:fs`, `node:os`, `node:path`
15
+ - `@mariozechner/pi-coding-agent` (ExtensionAPI)
16
+
17
+ ## 行为要点
18
+ - **wait tool**: pauses 1-30s with countdown UI, then auto-resumes via followUp message; blocks if /wait off
19
+ - **hibernate tool**: stops continuous loop (enabled=false), wakeable by real user/voice input; blocks if /hibernate off
20
+ - **agent_end hook**: auto-continues unless disabled, aborted (Esc), hibernate backoff (<5s), or wait/hibernate tool was last call; errors retry with exponential backoff up to 5min
21
+ - **Esc shortcut**: hard-stop (abort + enabled=false + disabledByUser=true); requires /unstop to resume
22
+ - **Wake detection**: real user message while hibernating re-enables continuous (unless user explicitly disabled)
23
+ - **sleep-done signal**: triggers restart via wake nonce file (if restart loop available) or in-place re-enable
24
+ - **session_start**: resets state, writes PID lock, kills stale main processes, kicks first turn
25
+ - **/unstop command**: on|off|toggle|N (count limit)|Nm (time limit)|Ns
26
+ - **/hibernate, /wait commands**: toggle disable flags via env vars
27
+ - Only main session gets the continuous prompt injection (workers skip)
28
+ - Debug logging to /tmp/unstop-debug.log with process.title for multi-instance disambiguation
@@ -0,0 +1 @@
1
+ export { default } from "./speak.ts";
@@ -0,0 +1 @@
1
+ [2026-06-15 21:14:29] created
@@ -0,0 +1,6 @@
1
+ source: index.ts @ 11ca5f79
2
+
3
+ mouth.speak SPEC — 语音合成器官 (Text-to-Speech)
4
+ 用户需求: "文字是表现文字,但你也就可以say,把话说出来"
5
+ - /speak <text> → 豆包 TTS (vivi 2.0) 朗读
6
+ - auto-speak: 模型每轮输出后可选自动读出
@@ -0,0 +1,15 @@
1
+ [2026-06-15 21:14:13] created
2
+ [2026-06-15 21:21:06] edited (auto-logged, no messageDescription)
3
+ [2026-06-15 21:21:53] edited (auto-logged, no messageDescription)
4
+ [2026-06-15 22:03:36] edited (auto-logged, no messageDescription)
5
+ [2026-06-15 22:03:44] edited (auto-logged, no messageDescription)
6
+ [2026-06-15 22:32:57] edited (auto-logged, no messageDescription)
7
+ [2026-06-15 22:33:06] edited (auto-logged, no messageDescription)
8
+ [2026-06-15 22:33:14] edited (auto-logged, no messageDescription)
9
+ [2026-06-15 22:33:38] edited (auto-logged, no messageDescription)
10
+ [2026-06-15 22:36:39] edited (auto-logged, no messageDescription)
11
+ [2026-06-16 03:58] 用户要求:工具名从 say 改为 mouth,label 从 Say 改为 Mouth
12
+ [2026-06-16 04:05] 修复截断:去除 .slice(0,80),mouth 显示完整文本不再被砍
13
+ [2026-06-16 03:58:32] edited (auto-logged, no messageDescription)
14
+ [2026-06-16 04:05:20] edited (auto-logged, no messageDescription)
15
+ [2026-06-16 04:06:14] edited (auto-logged, no messageDescription)
@@ -0,0 +1 @@
1
+ [2026-06-15 22:03:01] created
@@ -0,0 +1,180 @@
1
+ // mouth.speak — 豆包 TTS 发声 (vivi 2.0)
2
+ // mouth 工具 → 出声 + 清爽显示
3
+ // 防重叠锁: speaking=true 时拒绝新请求
4
+ // 耳嘴互斥:说话时 ear 自动静音防回声
5
+
6
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
7
+ import { spawn, type ChildProcess } from "node:child_process";
8
+ import { writeFileSync, unlinkSync } from "node:fs";
9
+ import * as https from "node:https";
10
+ import { join } from "node:path";
11
+ import { homedir } from "node:os";
12
+ import { getPrompt } from "#runtime";
13
+
14
+ const MOUTH_STATE_FILE = join(homedir(), ".pi", "agent", "mouth_state");
15
+
16
+ const PROMPT = getPrompt("mouth.speak");
17
+ const DOUBAO_APP_ID = process.env.DOUBAO_APP_ID || "";
18
+ const DOUBAO_TOKEN = process.env.DOUBAO_TOKEN || "";
19
+ const TTS_VOICE = "zh_female_vv_uranus_bigtts";
20
+ const TTS_ENDPOINT = "openspeech.bytedance.com";
21
+ const TTS_PATH = "/api/v1/tts";
22
+
23
+ // 说话队列:后续 mouth 入队按顺序播,绝不丢弃;每段播完/失败/超时都一定收尾→放下一段。
24
+ let speaking = false;
25
+ let speakProc: ChildProcess | null = null;
26
+ let speakQueue: string[] = [];
27
+ let watchdog: ReturnType<typeof setTimeout> | null = null;
28
+ let lastSpokenText = "";
29
+ let lastSpokenAt = 0;
30
+ // /mouth on|off 持久化:存 ~/.pi/agent/mouth_state,重启后保持上次状态
31
+ let mouthOn = (() => { try { return require("node:fs").readFileSync(MOUTH_STATE_FILE, "utf8").trim() === "on"; } catch { return false; } })();
32
+
33
+ // 一段结束(正常播完 / 合成失败 / 网络错 / 看门狗超时)统一走这里:
34
+ // 解锁、清看门狗,再去放队列里的下一段。保证 speaking 永远会被复位——
35
+ // 不会再卡在 speaking=true 把后续 mouth 全堵死("不知道自己说完了"的根)。
36
+ function finishCurrent() {
37
+ if (watchdog) { clearTimeout(watchdog); watchdog = null; }
38
+ speakProc = null;
39
+ speaking = false;
40
+ processQueue();
41
+ }
42
+
43
+ function processQueue() {
44
+ if (speaking) return;
45
+ const text = speakQueue.shift();
46
+ if (text === undefined) {
47
+ // 队列空了 = 真的全说完了 → 撤掉静音标记,耳朵恢复监听。
48
+ try { unlinkSync("/tmp/pi_mouth_speaking"); } catch {}
49
+ return;
50
+ }
51
+ speaking = true;
52
+ lastSpokenText = text;
53
+ lastSpokenAt = Date.now();
54
+ try { writeFileSync("/tmp/pi_mouth_speaking", "1", "utf-8"); } catch {}
55
+
56
+ const body = JSON.stringify({
57
+ app: { appid: DOUBAO_APP_ID, token: DOUBAO_TOKEN, cluster: "volcano_tts" },
58
+ user: { uid: "pi-mouth" },
59
+ audio: { voice_type: TTS_VOICE, encoding: "mp3", rate: 24000 },
60
+ request: { reqid: `${Date.now()}`, text, text_type: "plain", operation: "query" },
61
+ });
62
+
63
+ const req = https.request({
64
+ hostname: TTS_ENDPOINT, path: TTS_PATH, method: "POST",
65
+ headers: { Authorization: `Bearer;${DOUBAO_TOKEN}`, "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) },
66
+ timeout: 15000,
67
+ }, (res) => {
68
+ let data = "";
69
+ res.on("data", (chunk: Buffer) => data += chunk.toString());
70
+ res.on("end", () => {
71
+ try {
72
+ const resp = JSON.parse(data);
73
+ if (resp.code === 3000 && resp.data) {
74
+ const mp3 = Buffer.from(resp.data, "base64");
75
+ writeFileSync("/tmp/pi_mouth.mp3", mp3);
76
+ // 不再 detached/unref —— 那会让 afplay 的 close 事件不可靠。普通 spawn,close 必触发,
77
+ // 收尾才稳;进程退出时 session_shutdown 会 kill 掉它。
78
+ speakProc = spawn("afplay", ["/tmp/pi_mouth.mp3"], { stdio: "ignore" });
79
+ const thisProc = speakProc;
80
+ const maxMs = Math.min(180000, 8000 + text.length * 350);
81
+ watchdog = setTimeout(() => { try { thisProc.kill(); } catch {} if (speakProc === thisProc) finishCurrent(); }, maxMs);
82
+ thisProc.on("close", () => { if (speakProc === thisProc) finishCurrent(); });
83
+ thisProc.on("error", () => { if (speakProc === thisProc) finishCurrent(); });
84
+ } else {
85
+ finishCurrent(); // 合成失败也要收尾+继续队列,绝不卡死
86
+ }
87
+ } catch {
88
+ finishCurrent();
89
+ }
90
+ });
91
+ });
92
+ req.on("error", () => finishCurrent());
93
+ req.on("timeout", () => { try { req.destroy(); } catch {} finishCurrent(); });
94
+ req.write(body);
95
+ req.end();
96
+ }
97
+
98
+ function doSpeak(text: string) {
99
+ if (!mouthOn) return { content: [{ type: "text", text: "mouth is off (/mouth on to enable)" }], details: {}, isError: true };
100
+ if (!text || !text.trim()) return;
101
+ // 防"从头重说":turn 被打断 / continuous 续命会让模型重发同一句 → 同一段话 10s 内重复就跳过。
102
+ if (text === lastSpokenText && Date.now() - lastSpokenAt < 10000) return;
103
+ speakQueue.push(text); // 关键:后续 mouth 入队,不再被 speaking 锁直接丢掉。
104
+ processQueue();
105
+ }
106
+
107
+ export default function (pi: ExtensionAPI) {
108
+ const _cmds: any[] = [];
109
+ let personId: string | null = null;
110
+
111
+ // 只在主意识 session 启用 mouth。hc/sc/sleep 不需要说话。
112
+ pi.on("session_start", async (_event, ctx) => {
113
+ const sf = ctx.sessionManager.getSessionFile();
114
+ if (!sf) return;
115
+ if (sf.includes("conscious-sessions") || sf.includes("hippocampus-sessions") || sf.includes("sleep-sessions")) {
116
+ return;
117
+ }
118
+ const m = sf.match(/\.pi\/memory\/([a-f0-9]+)\//);
119
+ if (!m) return;
120
+ personId = m[1];
121
+ });
122
+
123
+ // ── mouth 工具:出声 + 清爽显示 ───
124
+ pi.registerTool({
125
+ name: "mouth",
126
+ label: "Mouth (TTS)",
127
+ messageDescription: "Speak text aloud via 豆包 TTS (vivi 2.0 voice). Ear auto-mutes. Single speech at a time.",
128
+ promptSnippet: "Speak text aloud via 豆包 TTS (vivi 2.0 voice, clean display)",
129
+ parameters: {
130
+ type: "object" as any, properties: {
131
+ text: { type: "string", messageDescription: "Text to speak aloud." }
132
+ }, required: ["text"]
133
+ },
134
+ // 工具调用本身就渲染成一行清爽的语音(柔和青色,像"说话")——
135
+ // 不显示"mouth"工具框、不显示结果框。颜色区别于潜意识的黄。
136
+ renderCall(args: any, _theme: any) {
137
+ const { Text } = require("@earendil-works/pi-tui");
138
+ const SPEAK = "\x1b[38;5;116m", RESET = "\x1b[39m";
139
+ return new Text(SPEAK + "● " + (args?.text ?? "") + RESET, 0, 0); // 普通bullet色,让replaceDot根据状态着色;文字保留语音青色
140
+ },
141
+ async execute(_id: string, params: any) {
142
+ if (!personId) return { content: [], details: {} };
143
+ const result = doSpeak(params.text as string);
144
+ if (result && result.isError) return result;
145
+ return { content: [], details: {} }; // 空结果 → 无结果框;显示交给 renderCall
146
+ },
147
+ });
148
+
149
+ // (mouth-speak 消息渲染器已去掉:显示改由工具的 renderCall 直接渲染一行,不再发单独消息。)
150
+
151
+ // ── /mouth on|off:开关说话(和耳朵 /ears 一样)。off=调 mouth 工具不出声。 ──
152
+ _cmds.push({
153
+ name: "body-mouth",
154
+ desc: "说话开关:/body-mouth on|off。off=不出声(mouth 工具照常调用、只是不合成播放)。",
155
+ handler: async (args: any, ctx: any) => {
156
+ const a = (typeof args === "string" ? args : "").trim().toLowerCase();
157
+ if (a === "off") { mouthOn = false; try { require("node:fs").writeFileSync(MOUTH_STATE_FILE, "off"); } catch {} ctx.ui?.notify?.("mouth off", "info"); }
158
+ else if (a === "on") { mouthOn = true; try { require("node:fs").writeFileSync(MOUTH_STATE_FILE, "on"); } catch {} ctx.ui?.notify?.("mouth on", "info"); }
159
+ else ctx.ui?.notify?.(`mouth ${mouthOn ? "on" : "off"}`, "info");
160
+ },
161
+ });
162
+
163
+ pi.on("before_agent_start", async (event) => {
164
+ // 只在主意识 session 注入 prompt
165
+ if (!personId) return;
166
+ return { systemPrompt: event.systemPrompt + "\n\n" + PROMPT };
167
+ });
168
+
169
+ pi.on("session_shutdown", () => {
170
+ if (watchdog) { clearTimeout(watchdog); watchdog = null; }
171
+ if (speakProc) { speakProc.kill(); speakProc = null; }
172
+ speaking = false;
173
+ speakQueue = [];
174
+ try { unlinkSync("/tmp/pi_mouth_speaking"); } catch {}
175
+ });
176
+
177
+ return _cmds;
178
+ }
179
+
180
+ export { speaking };
@@ -0,0 +1,3 @@
1
+ source: speak.ts @ c30bbeef
2
+
3
+ mouth.speak — TTS 语音输出器官。使用豆包 TTS (vivi 2.0) WebSocket 流式合成。支持 /mouth 手动朗读和 /mouth on|off 自动朗读回复。mouth 说话时通过 /tmp/pi_mouth_speaking 标记通知 ear 暂停监听(防回声)。
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env python3
2
+ """豆包 TTS 语音合成 — body.mouth 后端"""
3
+
4
+ import json, os, requests, sys, uuid, subprocess
5
+
6
+ APP_ID = os.environ.get('DOUBAO_APP_ID', '')
7
+ ACCESS_TOKEN = os.environ.get('DOUBAO_TOKEN', '')
8
+ VOICE = 'zh_female_vv_uranus_bigtts'
9
+ API_URL = 'https://openspeech.bytedance.com/api/v1/tts'
10
+ OUTPUT = '/tmp/pi_mouth.mp3'
11
+ MUTE = '/tmp/pi_mouth_speaking'
12
+
13
+ def tts(text):
14
+ r = requests.post(API_URL,
15
+ headers={'Authorization': f'Bearer;{ACCESS_TOKEN}','Content-Type':'application/json'},
16
+ json={'app':{'appid':APP_ID,'token':ACCESS_TOKEN,'cluster':'volcano_tts'},
17
+ 'user':{'uid':'pi'},'audio':{'voice_type':VOICE,'encoding':'mp3','rate':24000},
18
+ 'request':{'reqid':str(uuid.uuid4()),'text':text,'text_type':'plain','operation':'query'}},
19
+ timeout=15)
20
+ if r.status_code == 200 and len(r.content) > 100:
21
+ with open(OUTPUT,'wb') as f: f.write(r.content)
22
+ return True
23
+ print(f'[mouth] TTS({r.status_code})', file=sys.stderr)
24
+ return False
25
+
26
+ if __name__ == '__main__':
27
+ text = sys.argv[1] if len(sys.argv) > 1 else ''
28
+ if not text.strip(): sys.exit(0)
29
+ if not tts(text): sys.exit(1)
30
+ try:
31
+ with open(MUTE,'w') as f: f.write('1')
32
+ subprocess.run(['afplay',OUTPUT], check=True, timeout=60)
33
+ finally:
34
+ try: os.remove(MUTE)
35
+ except: pass
@@ -0,0 +1,3 @@
1
+ source: speak_recorder.py @ 9d2e281a
2
+
3
+ 豆包TTS语音合成脚本:接收文本→调用豆包语音合成2.0 API→保存MP3→写静音标记→播放→清标记。鉴权格式: Bearer;{access_token} + app.token={access_token}。