@bolloon/bolloon-agent 0.4.28 → 0.4.29

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 (435) hide show
  1. package/bin/bolloon.cjs +18 -148
  2. package/bin/bolloon.cmd +6 -3
  3. package/dist/agents/pi-sdk-tools.js +3 -1
  4. package/dist/agents/pi-sdk.js +4 -1
  5. package/dist/cli/update-commands.js +349 -0
  6. package/dist/cli-entry.js +41 -55
  7. package/dist/electron-build/agents/agent-gateway.js +169 -0
  8. package/dist/electron-build/agents/agent-gateway.js.map +1 -0
  9. package/dist/electron-build/agents/agent-identity-store.js +212 -0
  10. package/dist/electron-build/agents/agent-identity-store.js.map +1 -0
  11. package/dist/electron-build/agents/agent-identity.js +196 -0
  12. package/dist/electron-build/agents/agent-identity.js.map +1 -0
  13. package/dist/electron-build/agents/agent-manifest-protocol.js +151 -0
  14. package/dist/electron-build/agents/agent-manifest-protocol.js.map +1 -0
  15. package/dist/electron-build/agents/agent-registry.js +217 -0
  16. package/dist/electron-build/agents/agent-registry.js.map +1 -0
  17. package/dist/electron-build/agents/agent-reputation.js +60 -0
  18. package/dist/electron-build/agents/agent-reputation.js.map +1 -0
  19. package/dist/electron-build/agents/agent-service-client.js +186 -0
  20. package/dist/electron-build/agents/agent-service-client.js.map +1 -0
  21. package/dist/electron-build/agents/browser-cdp.js +765 -0
  22. package/dist/electron-build/agents/browser-cdp.js.map +1 -0
  23. package/dist/electron-build/agents/computer-use.js +341 -0
  24. package/dist/electron-build/agents/computer-use.js.map +1 -0
  25. package/dist/electron-build/agents/constraint-layer.js +210 -0
  26. package/dist/electron-build/agents/constraint-layer.js.map +1 -0
  27. package/dist/electron-build/agents/decision-store.js +292 -0
  28. package/dist/electron-build/agents/decision-store.js.map +1 -0
  29. package/dist/electron-build/agents/deny-pipeline.js +125 -0
  30. package/dist/electron-build/agents/deny-pipeline.js.map +1 -0
  31. package/dist/electron-build/agents/economic-policy.js +172 -0
  32. package/dist/electron-build/agents/economic-policy.js.map +1 -0
  33. package/dist/electron-build/agents/error-classifier.js +125 -0
  34. package/dist/electron-build/agents/error-classifier.js.map +1 -0
  35. package/dist/electron-build/agents/execution-supervisor.js +539 -0
  36. package/dist/electron-build/agents/execution-supervisor.js.map +1 -0
  37. package/dist/electron-build/agents/external-events.js +171 -0
  38. package/dist/electron-build/agents/external-events.js.map +1 -0
  39. package/dist/electron-build/agents/gateway-join.js +315 -0
  40. package/dist/electron-build/agents/gateway-join.js.map +1 -0
  41. package/dist/electron-build/agents/gateway-network.js +505 -0
  42. package/dist/electron-build/agents/gateway-network.js.map +1 -0
  43. package/dist/electron-build/agents/goal-criteria.js +133 -0
  44. package/dist/electron-build/agents/goal-criteria.js.map +1 -0
  45. package/dist/electron-build/agents/goal-resume.js +364 -0
  46. package/dist/electron-build/agents/goal-resume.js.map +1 -0
  47. package/dist/electron-build/agents/goal-store.js +587 -0
  48. package/dist/electron-build/agents/goal-store.js.map +1 -0
  49. package/dist/electron-build/agents/intent-classifier.js +104 -0
  50. package/dist/electron-build/agents/intent-classifier.js.map +1 -0
  51. package/dist/electron-build/agents/iroh-secret.js +70 -0
  52. package/dist/electron-build/agents/iroh-secret.js.map +1 -0
  53. package/dist/electron-build/agents/loop-review.js +101 -0
  54. package/dist/electron-build/agents/loop-review.js.map +1 -0
  55. package/dist/electron-build/agents/memory-recall.js +154 -0
  56. package/dist/electron-build/agents/memory-recall.js.map +1 -0
  57. package/dist/electron-build/agents/p2p-document-tools.js +328 -0
  58. package/dist/electron-build/agents/p2p-document-tools.js.map +1 -0
  59. package/dist/electron-build/agents/parse-tool-call.js +564 -0
  60. package/dist/electron-build/agents/parse-tool-call.js.map +1 -0
  61. package/dist/electron-build/agents/patch-tool.js +205 -0
  62. package/dist/electron-build/agents/patch-tool.js.map +1 -0
  63. package/dist/electron-build/agents/payment-approval.js +183 -0
  64. package/dist/electron-build/agents/payment-approval.js.map +1 -0
  65. package/dist/electron-build/agents/payment-gate.js +139 -0
  66. package/dist/electron-build/agents/payment-gate.js.map +1 -0
  67. package/dist/electron-build/agents/permission-mode.js +124 -0
  68. package/dist/electron-build/agents/permission-mode.js.map +1 -0
  69. package/dist/electron-build/agents/pi-harness.js +268 -0
  70. package/dist/electron-build/agents/pi-harness.js.map +1 -0
  71. package/dist/electron-build/agents/pi-sdk-session-factory.js +117 -0
  72. package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -0
  73. package/dist/electron-build/agents/pi-sdk-session-manager.js +335 -0
  74. package/dist/electron-build/agents/pi-sdk-session-manager.js.map +1 -0
  75. package/dist/electron-build/agents/pi-sdk-tools.js +4042 -0
  76. package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -0
  77. package/dist/electron-build/agents/pi-sdk-types.js +17 -0
  78. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -0
  79. package/dist/electron-build/agents/pi-sdk.js +3325 -0
  80. package/dist/electron-build/agents/pi-sdk.js.map +1 -0
  81. package/dist/electron-build/agents/plan-store.js +212 -0
  82. package/dist/electron-build/agents/plan-store.js.map +1 -0
  83. package/dist/electron-build/agents/pre-tool-validator.js +200 -0
  84. package/dist/electron-build/agents/pre-tool-validator.js.map +1 -0
  85. package/dist/electron-build/agents/process-runner.js +148 -0
  86. package/dist/electron-build/agents/process-runner.js.map +1 -0
  87. package/dist/electron-build/agents/react-loop.js +131 -0
  88. package/dist/electron-build/agents/react-loop.js.map +1 -0
  89. package/dist/electron-build/agents/resource-store.js +180 -0
  90. package/dist/electron-build/agents/resource-store.js.map +1 -0
  91. package/dist/electron-build/agents/resource-token.js +118 -0
  92. package/dist/electron-build/agents/resource-token.js.map +1 -0
  93. package/dist/electron-build/agents/resource-wallet.js +84 -0
  94. package/dist/electron-build/agents/resource-wallet.js.map +1 -0
  95. package/dist/electron-build/agents/run-store.js +854 -0
  96. package/dist/electron-build/agents/run-store.js.map +1 -0
  97. package/dist/electron-build/agents/runner-resolver.js +267 -0
  98. package/dist/electron-build/agents/runner-resolver.js.map +1 -0
  99. package/dist/electron-build/agents/session-store.js +294 -0
  100. package/dist/electron-build/agents/session-store.js.map +1 -0
  101. package/dist/electron-build/agents/shell-guard.js +465 -0
  102. package/dist/electron-build/agents/shell-guard.js.map +1 -0
  103. package/dist/electron-build/agents/shell-tool.js +102 -0
  104. package/dist/electron-build/agents/shell-tool.js.map +1 -0
  105. package/dist/electron-build/agents/skill-loader.js +216 -0
  106. package/dist/electron-build/agents/skill-loader.js.map +1 -0
  107. package/dist/electron-build/agents/skill-readiness.js +174 -0
  108. package/dist/electron-build/agents/skill-readiness.js.map +1 -0
  109. package/dist/electron-build/agents/skill-share.js +394 -0
  110. package/dist/electron-build/agents/skill-share.js.map +1 -0
  111. package/dist/electron-build/agents/skill-supervisor-link.js +75 -0
  112. package/dist/electron-build/agents/skill-supervisor-link.js.map +1 -0
  113. package/dist/electron-build/agents/skill-writer.js +347 -0
  114. package/dist/electron-build/agents/skill-writer.js.map +1 -0
  115. package/dist/electron-build/agents/skills-manager.js +763 -0
  116. package/dist/electron-build/agents/skills-manager.js.map +1 -0
  117. package/dist/electron-build/agents/supervisor-host.js +294 -0
  118. package/dist/electron-build/agents/supervisor-host.js.map +1 -0
  119. package/dist/electron-build/agents/task/local-seller.js +188 -0
  120. package/dist/electron-build/agents/task/local-seller.js.map +1 -0
  121. package/dist/electron-build/agents/task/report-card.js +152 -0
  122. package/dist/electron-build/agents/task/report-card.js.map +1 -0
  123. package/dist/electron-build/agents/task/resource-advisor.js +222 -0
  124. package/dist/electron-build/agents/task/resource-advisor.js.map +1 -0
  125. package/dist/electron-build/agents/task/task-budget.js +111 -0
  126. package/dist/electron-build/agents/task/task-budget.js.map +1 -0
  127. package/dist/electron-build/agents/task/task-runner.js +670 -0
  128. package/dist/electron-build/agents/task/task-runner.js.map +1 -0
  129. package/dist/electron-build/agents/task-state.js +266 -0
  130. package/dist/electron-build/agents/task-state.js.map +1 -0
  131. package/dist/electron-build/agents/tool-registry.js +141 -0
  132. package/dist/electron-build/agents/tool-registry.js.map +1 -0
  133. package/dist/electron-build/agents/treasury-bridge.js +165 -0
  134. package/dist/electron-build/agents/treasury-bridge.js.map +1 -0
  135. package/dist/electron-build/agents/user-questions.js +223 -0
  136. package/dist/electron-build/agents/user-questions.js.map +1 -0
  137. package/dist/electron-build/agents/verify-recipe.js +90 -0
  138. package/dist/electron-build/agents/verify-recipe.js.map +1 -0
  139. package/dist/electron-build/agents/workflow-engine.js +222 -0
  140. package/dist/electron-build/agents/workflow-engine.js.map +1 -0
  141. package/dist/electron-build/agents/workflow-pivot-loop.js +988 -0
  142. package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -0
  143. package/dist/electron-build/agents/write-staging.js +133 -0
  144. package/dist/electron-build/agents/write-staging.js.map +1 -0
  145. package/dist/electron-build/agents/x402/goal-run-bridge.js +115 -0
  146. package/dist/electron-build/agents/x402/goal-run-bridge.js.map +1 -0
  147. package/dist/electron-build/agents/x402/milestone-settlement.js +163 -0
  148. package/dist/electron-build/agents/x402/milestone-settlement.js.map +1 -0
  149. package/dist/electron-build/agents/x402/paid-info-protocol.js +274 -0
  150. package/dist/electron-build/agents/x402/paid-info-protocol.js.map +1 -0
  151. package/dist/electron-build/agents/x402/paid-info-store.js +409 -0
  152. package/dist/electron-build/agents/x402/paid-info-store.js.map +1 -0
  153. package/dist/electron-build/agents/x402/paid-info-tools.js +346 -0
  154. package/dist/electron-build/agents/x402/paid-info-tools.js.map +1 -0
  155. package/dist/electron-build/agents/x402/payment-recovery.js +330 -0
  156. package/dist/electron-build/agents/x402/payment-recovery.js.map +1 -0
  157. package/dist/electron-build/agents/x402/resource-contract.js +533 -0
  158. package/dist/electron-build/agents/x402/resource-contract.js.map +1 -0
  159. package/dist/electron-build/agents/x402/settlement-state.js +432 -0
  160. package/dist/electron-build/agents/x402/settlement-state.js.map +1 -0
  161. package/dist/electron-build/agents/x402/trade.js +294 -0
  162. package/dist/electron-build/agents/x402/trade.js.map +1 -0
  163. package/dist/electron-build/agents/x402/transaction-protocol.js +109 -0
  164. package/dist/electron-build/agents/x402/transaction-protocol.js.map +1 -0
  165. package/dist/electron-build/agents/x402/transaction-store.js +404 -0
  166. package/dist/electron-build/agents/x402/transaction-store.js.map +1 -0
  167. package/dist/electron-build/agents/x402/x402Pay.js +377 -0
  168. package/dist/electron-build/agents/x402/x402Pay.js.map +1 -0
  169. package/dist/electron-build/bollharness-integration/context-router-judgment.js +269 -0
  170. package/dist/electron-build/bollharness-integration/context-router-judgment.js.map +1 -0
  171. package/dist/electron-build/bollharness-integration/context-router.js +584 -0
  172. package/dist/electron-build/bollharness-integration/context-router.js.map +1 -0
  173. package/dist/electron-build/bollharness-integration/gate-state-machine.js +362 -0
  174. package/dist/electron-build/bollharness-integration/gate-state-machine.js.map +1 -0
  175. package/dist/electron-build/bollharness-integration/gate-transition-hooks.js +136 -0
  176. package/dist/electron-build/bollharness-integration/gate-transition-hooks.js.map +1 -0
  177. package/dist/electron-build/bollharness-integration/guard-checker.js +400 -0
  178. package/dist/electron-build/bollharness-integration/guard-checker.js.map +1 -0
  179. package/dist/electron-build/bollharness-integration/index.js +123 -0
  180. package/dist/electron-build/bollharness-integration/index.js.map +1 -0
  181. package/dist/electron-build/bollharness-integration/integration.js +531 -0
  182. package/dist/electron-build/bollharness-integration/integration.js.map +1 -0
  183. package/dist/electron-build/bollharness-integration/skill-adapter.js +608 -0
  184. package/dist/electron-build/bollharness-integration/skill-adapter.js.map +1 -0
  185. package/dist/electron-build/bootstrap/bootstrap.js +173 -0
  186. package/dist/electron-build/bootstrap/bootstrap.js.map +1 -0
  187. package/dist/electron-build/bootstrap/context-collector.js +358 -0
  188. package/dist/electron-build/bootstrap/context-collector.js.map +1 -0
  189. package/dist/electron-build/bootstrap/context-hierarchy.js +262 -0
  190. package/dist/electron-build/bootstrap/context-hierarchy.js.map +1 -0
  191. package/dist/electron-build/bootstrap/context-manager.js +211 -0
  192. package/dist/electron-build/bootstrap/context-manager.js.map +1 -0
  193. package/dist/electron-build/bootstrap/context-os.js +277 -0
  194. package/dist/electron-build/bootstrap/context-os.js.map +1 -0
  195. package/dist/electron-build/bootstrap/event-log.js +203 -0
  196. package/dist/electron-build/bootstrap/event-log.js.map +1 -0
  197. package/dist/electron-build/bootstrap/exhaust-scrubber.js +277 -0
  198. package/dist/electron-build/bootstrap/exhaust-scrubber.js.map +1 -0
  199. package/dist/electron-build/bootstrap/lifecycle-hooks.js +282 -0
  200. package/dist/electron-build/bootstrap/lifecycle-hooks.js.map +1 -0
  201. package/dist/electron-build/bootstrap/memory-compressor.js +377 -0
  202. package/dist/electron-build/bootstrap/memory-compressor.js.map +1 -0
  203. package/dist/electron-build/bootstrap/persona-loader.js +219 -0
  204. package/dist/electron-build/bootstrap/persona-loader.js.map +1 -0
  205. package/dist/electron-build/bootstrap/project-context.js +162 -0
  206. package/dist/electron-build/bootstrap/project-context.js.map +1 -0
  207. package/dist/electron-build/bootstrap/project-state.js +205 -0
  208. package/dist/electron-build/bootstrap/project-state.js.map +1 -0
  209. package/dist/electron-build/bootstrap/session-window.js +162 -0
  210. package/dist/electron-build/bootstrap/session-window.js.map +1 -0
  211. package/dist/electron-build/bootstrap/vector-index.js +291 -0
  212. package/dist/electron-build/bootstrap/vector-index.js.map +1 -0
  213. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +22 -0
  214. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js.map +1 -0
  215. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js +86 -0
  216. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js.map +1 -0
  217. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +37 -0
  218. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js.map +1 -0
  219. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +20 -0
  220. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js.map +1 -0
  221. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +29 -0
  222. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js.map +1 -0
  223. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +28 -0
  224. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js.map +1 -0
  225. package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js +10 -0
  226. package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js.map +1 -0
  227. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js +68 -0
  228. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js.map +1 -0
  229. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js +14 -0
  230. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js.map +1 -0
  231. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js +17 -0
  232. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js.map +1 -0
  233. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js +59 -0
  234. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js.map +1 -0
  235. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js +29 -0
  236. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js.map +1 -0
  237. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js +14 -0
  238. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js.map +1 -0
  239. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js +29 -0
  240. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js.map +1 -0
  241. package/dist/electron-build/constraints/index.js +11 -0
  242. package/dist/electron-build/constraints/index.js.map +1 -0
  243. package/dist/electron-build/context-compaction/auto-compact.js +182 -0
  244. package/dist/electron-build/context-compaction/auto-compact.js.map +1 -0
  245. package/dist/electron-build/context-compaction/budget-gate.js +32 -0
  246. package/dist/electron-build/context-compaction/budget-gate.js.map +1 -0
  247. package/dist/electron-build/context-compaction/budget-reduce.js +39 -0
  248. package/dist/electron-build/context-compaction/budget-reduce.js.map +1 -0
  249. package/dist/electron-build/context-compaction/context-collapse.js +71 -0
  250. package/dist/electron-build/context-compaction/context-collapse.js.map +1 -0
  251. package/dist/electron-build/context-compaction/index.js +38 -0
  252. package/dist/electron-build/context-compaction/index.js.map +1 -0
  253. package/dist/electron-build/context-compaction/microcompact.js +55 -0
  254. package/dist/electron-build/context-compaction/microcompact.js.map +1 -0
  255. package/dist/electron-build/context-compaction/pipeline.js +128 -0
  256. package/dist/electron-build/context-compaction/pipeline.js.map +1 -0
  257. package/dist/electron-build/context-compaction/snip.js +50 -0
  258. package/dist/electron-build/context-compaction/snip.js.map +1 -0
  259. package/dist/electron-build/context-compaction/token-estimator.js +40 -0
  260. package/dist/electron-build/context-compaction/token-estimator.js.map +1 -0
  261. package/dist/electron-build/context-compaction/types.js +21 -0
  262. package/dist/electron-build/context-compaction/types.js.map +1 -0
  263. package/dist/electron-build/cron/tick-lock.js +247 -0
  264. package/dist/electron-build/cron/tick-lock.js.map +1 -0
  265. package/dist/electron-build/documents/reader.js +131 -0
  266. package/dist/electron-build/documents/reader.js.map +1 -0
  267. package/dist/electron-build/documents/store.js +220 -0
  268. package/dist/electron-build/documents/store.js.map +1 -0
  269. package/dist/electron-build/external-engines/delegate-handle.js +76 -0
  270. package/dist/electron-build/external-engines/delegate-handle.js.map +1 -0
  271. package/dist/electron-build/external-engines/delegate.js +225 -0
  272. package/dist/electron-build/external-engines/delegate.js.map +1 -0
  273. package/dist/electron-build/external-engines/discovery.js +448 -0
  274. package/dist/electron-build/external-engines/discovery.js.map +1 -0
  275. package/dist/electron-build/external-engines/types.js +13 -0
  276. package/dist/electron-build/external-engines/types.js.map +1 -0
  277. package/dist/electron-build/hooks/hooks-engine.js +367 -0
  278. package/dist/electron-build/hooks/hooks-engine.js.map +1 -0
  279. package/dist/electron-build/judgeness/reflect.js +100 -0
  280. package/dist/electron-build/judgeness/reflect.js.map +1 -0
  281. package/dist/electron-build/judgeness/store.js +536 -0
  282. package/dist/electron-build/judgeness/store.js.map +1 -0
  283. package/dist/electron-build/judgeness/types.js +21 -0
  284. package/dist/electron-build/judgeness/types.js.map +1 -0
  285. package/dist/electron-build/llm/config-store.js +551 -0
  286. package/dist/electron-build/llm/config-store.js.map +1 -0
  287. package/dist/electron-build/llm/error-lessons.js +76 -0
  288. package/dist/electron-build/llm/error-lessons.js.map +1 -0
  289. package/dist/electron-build/llm/pi-ai.js +830 -0
  290. package/dist/electron-build/llm/pi-ai.js.map +1 -0
  291. package/dist/electron-build/llm/system-prompt/registry.js +318 -0
  292. package/dist/electron-build/llm/system-prompt/registry.js.map +1 -0
  293. package/dist/electron-build/llm/system-prompt/strip-hibsml.js +55 -0
  294. package/dist/electron-build/llm/system-prompt/strip-hibsml.js.map +1 -0
  295. package/dist/electron-build/locales/en.js +32 -0
  296. package/dist/electron-build/locales/en.js.map +1 -0
  297. package/dist/electron-build/locales/zh.js +30 -0
  298. package/dist/electron-build/locales/zh.js.map +1 -0
  299. package/dist/electron-build/lsp/lsp-manager.js +327 -0
  300. package/dist/electron-build/lsp/lsp-manager.js.map +1 -0
  301. package/dist/electron-build/lsp/lsp-tools.js +226 -0
  302. package/dist/electron-build/lsp/lsp-tools.js.map +1 -0
  303. package/dist/electron-build/migration/external-agent-migrator.js +451 -0
  304. package/dist/electron-build/migration/external-agent-migrator.js.map +1 -0
  305. package/dist/electron-build/network/agent-network.js +775 -0
  306. package/dist/electron-build/network/agent-network.js.map +1 -0
  307. package/dist/electron-build/network/goal-event-bridge.js +62 -0
  308. package/dist/electron-build/network/goal-event-bridge.js.map +1 -0
  309. package/dist/electron-build/network/iroh-integration.js +117 -0
  310. package/dist/electron-build/network/iroh-integration.js.map +1 -0
  311. package/dist/electron-build/network/iroh-transport.js +550 -0
  312. package/dist/electron-build/network/iroh-transport.js.map +1 -0
  313. package/dist/electron-build/network/p2p.js +1103 -0
  314. package/dist/electron-build/network/p2p.js.map +1 -0
  315. package/dist/electron-build/network/storage/adapters/json-adapter.js +416 -0
  316. package/dist/electron-build/network/storage/adapters/json-adapter.js.map +1 -0
  317. package/dist/electron-build/network/storage/types.js +18 -0
  318. package/dist/electron-build/network/storage/types.js.map +1 -0
  319. package/dist/electron-build/orbitdb/agent-tools.js +402 -0
  320. package/dist/electron-build/orbitdb/agent-tools.js.map +1 -0
  321. package/dist/electron-build/orbitdb/cid-database.js +284 -0
  322. package/dist/electron-build/orbitdb/cid-database.js.map +1 -0
  323. package/dist/electron-build/orbitdb/context-store.js +99 -0
  324. package/dist/electron-build/orbitdb/context-store.js.map +1 -0
  325. package/dist/electron-build/orbitdb/ipfs-node.js +120 -0
  326. package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -0
  327. package/dist/electron-build/orbitdb/kanban-store.js +299 -0
  328. package/dist/electron-build/orbitdb/kanban-store.js.map +1 -0
  329. package/dist/electron-build/orbitdb/task-store.js +155 -0
  330. package/dist/electron-build/orbitdb/task-store.js.map +1 -0
  331. package/dist/electron-build/orbitdb/trajectory-store.js +194 -0
  332. package/dist/electron-build/orbitdb/trajectory-store.js.map +1 -0
  333. package/dist/electron-build/orbitdb/ui-cid.js +77 -0
  334. package/dist/electron-build/orbitdb/ui-cid.js.map +1 -0
  335. package/dist/electron-build/pi-ecosystem-a2ui/index.js +89 -0
  336. package/dist/electron-build/pi-ecosystem-a2ui/index.js.map +1 -0
  337. package/dist/electron-build/pi-ecosystem-goals/index.js +512 -0
  338. package/dist/electron-build/pi-ecosystem-goals/index.js.map +1 -0
  339. package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js +325 -0
  340. package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js.map +1 -0
  341. package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js +492 -0
  342. package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js.map +1 -0
  343. package/dist/electron-build/pi-ecosystem-judgment/cleanup.js +167 -0
  344. package/dist/electron-build/pi-ecosystem-judgment/cleanup.js.map +1 -0
  345. package/dist/electron-build/pi-ecosystem-judgment/decision.js +321 -0
  346. package/dist/electron-build/pi-ecosystem-judgment/decision.js.map +1 -0
  347. package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js +175 -0
  348. package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js.map +1 -0
  349. package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js +232 -0
  350. package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js.map +1 -0
  351. package/dist/electron-build/pi-ecosystem-judgment/distillation.js +304 -0
  352. package/dist/electron-build/pi-ecosystem-judgment/distillation.js.map +1 -0
  353. package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js +176 -0
  354. package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js.map +1 -0
  355. package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js +65 -0
  356. package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js.map +1 -0
  357. package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js +808 -0
  358. package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js.map +1 -0
  359. package/dist/electron-build/pi-ecosystem-judgment/index.js +508 -0
  360. package/dist/electron-build/pi-ecosystem-judgment/index.js.map +1 -0
  361. package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js +334 -0
  362. package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js.map +1 -0
  363. package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js +228 -0
  364. package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js.map +1 -0
  365. package/dist/electron-build/pi-ecosystem-judgment/value-injection.js +598 -0
  366. package/dist/electron-build/pi-ecosystem-judgment/value-injection.js.map +1 -0
  367. package/dist/electron-build/pi-ecosystem-mcp/index.js +643 -0
  368. package/dist/electron-build/pi-ecosystem-mcp/index.js.map +1 -0
  369. package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js +116 -0
  370. package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js.map +1 -0
  371. package/dist/electron-build/pi-ecosystem-subagents/index.js +352 -0
  372. package/dist/electron-build/pi-ecosystem-subagents/index.js.map +1 -0
  373. package/dist/electron-build/security/builtin-guards.js +133 -0
  374. package/dist/electron-build/security/builtin-guards.js.map +1 -0
  375. package/dist/electron-build/security/context-router-tool.js +111 -0
  376. package/dist/electron-build/security/context-router-tool.js.map +1 -0
  377. package/dist/electron-build/security/input-scanner.js +263 -0
  378. package/dist/electron-build/security/input-scanner.js.map +1 -0
  379. package/dist/electron-build/security/react-harness.js +148 -0
  380. package/dist/electron-build/security/react-harness.js.map +1 -0
  381. package/dist/electron-build/security/tool-gate.js +287 -0
  382. package/dist/electron-build/security/tool-gate.js.map +1 -0
  383. package/dist/electron-build/setup/setup-store.js +648 -0
  384. package/dist/electron-build/setup/setup-store.js.map +1 -0
  385. package/dist/electron-build/social/channels/ChannelManager.js +444 -0
  386. package/dist/electron-build/social/channels/ChannelManager.js.map +1 -0
  387. package/dist/electron-build/social/channels/DiapChannelBridge.js +451 -0
  388. package/dist/electron-build/social/channels/DiapChannelBridge.js.map +1 -0
  389. package/dist/electron-build/social/channels/InterestMatcher.js +135 -0
  390. package/dist/electron-build/social/channels/InterestMatcher.js.map +1 -0
  391. package/dist/electron-build/social/channels/types.js +21 -0
  392. package/dist/electron-build/social/channels/types.js.map +1 -0
  393. package/dist/electron-build/social/global-shared-context.js +368 -0
  394. package/dist/electron-build/social/global-shared-context.js.map +1 -0
  395. package/dist/electron-build/social/heartbeat.js +882 -0
  396. package/dist/electron-build/social/heartbeat.js.map +1 -0
  397. package/dist/electron-build/storage/did-catalog-bridge.js +314 -0
  398. package/dist/electron-build/storage/did-catalog-bridge.js.map +1 -0
  399. package/dist/electron-build/storage/did-catalog.js +272 -0
  400. package/dist/electron-build/storage/did-catalog.js.map +1 -0
  401. package/dist/electron-build/utils/auto-update.js +140 -558
  402. package/dist/electron-build/utils/auto-update.js.map +1 -1
  403. package/dist/electron-build/utils/module-context.js +98 -0
  404. package/dist/electron-build/utils/module-context.js.map +1 -0
  405. package/dist/electron-build/utils/runtime-bootstrap.js +745 -0
  406. package/dist/electron-build/utils/runtime-bootstrap.js.map +1 -0
  407. package/dist/electron-build/utils/update-manager.js +770 -0
  408. package/dist/electron-build/utils/update-manager.js.map +1 -0
  409. package/dist/electron-build/utils/update-state.js +406 -0
  410. package/dist/electron-build/utils/update-state.js.map +1 -0
  411. package/dist/electron-build/utils/version-info.js +562 -0
  412. package/dist/electron-build/utils/version-info.js.map +1 -0
  413. package/dist/electron-build/web/i18n.js +146 -0
  414. package/dist/electron-build/web/i18n.js.map +1 -0
  415. package/dist/electron-build/web/routes-x402-info.js +232 -0
  416. package/dist/electron-build/web/routes-x402-info.js.map +1 -0
  417. package/dist/electron-build/web/server-storage.js +390 -0
  418. package/dist/electron-build/web/server-storage.js.map +1 -0
  419. package/dist/electron-build/web/server-types.js +52 -0
  420. package/dist/electron-build/web/server-types.js.map +1 -0
  421. package/dist/electron-build/web/task-deps.js +41 -0
  422. package/dist/electron-build/web/task-deps.js.map +1 -0
  423. package/dist/index.js +28 -27
  424. package/dist/llm/system-prompt/registry.js +6 -3
  425. package/dist/utils/auto-update.js +138 -525
  426. package/dist/utils/module-context.js +59 -0
  427. package/dist/utils/runtime-bootstrap.js +682 -0
  428. package/dist/utils/update-cli.js +82 -0
  429. package/dist/utils/update-health.js +401 -0
  430. package/dist/utils/update-manager.js +716 -0
  431. package/dist/utils/update-state.js +353 -0
  432. package/dist/utils/version-info.js +510 -0
  433. package/package.json +1 -1
  434. package/scripts/build-cli.js +32 -151
  435. package/scripts/postinstall.js +153 -76
@@ -0,0 +1,682 @@
1
+ /**
2
+ * runtime-bootstrap.ts — **运行时安装与配置的唯一管理器** (2026-09-19, leo 计划 Phase 0-8)
3
+ *
4
+ * 新的完成定义 (冻结):
5
+ * **Bolloon 安装完成 = Node/npm、Git、Python 三个运行时都已可执行、版本可验证、路径已配置。**
6
+ * 任何一个必需运行时不可用 → 整个安装**不能**宣布成功。
7
+ *
8
+ * 为什么需要它: 此前 `install.sh` 只查 Node/npm, `postinstall.js` 不查 Git/Python,
9
+ * `version-info.ts` 只"探测"Python 不负责配置, PATH 没有任何统一来源 —— 于是
10
+ * "装上但不可用 / 看似成功实际缺失" 这类状态没有任何事实可查。
11
+ *
12
+ * 边界 (冻结):
13
+ * - **不偷偷 sudo / 不静默高权限**: 需要管理员权限时进 `needsAdmin` + 只在显式 `allowSudo` 才执行;
14
+ * - **不覆盖用户已有运行时**: 已满足最低版本一律 `reuse`;
15
+ * - **不写用户配置里除 `runtime.*` 之外的任何字段**;
16
+ * - **每次启动重新验证**, 不盲信配置文件 (配置只是"优先探测路径")。
17
+ *
18
+ * 命令构造与执行分离: 纯函数 (探测/计划/报告) 可单测; 真执行只在 `bootstrapRuntimes` 里发生。
19
+ */
20
+ import * as os from 'os';
21
+ import * as path from 'path';
22
+ import * as fs from 'fs';
23
+ import * as fsp from 'fs/promises';
24
+ import { execFileSync, spawnSync } from 'child_process';
25
+ import { resolveBolloonHome, CANONICAL_CONFIG_FILE } from '../setup/setup-store.js';
26
+ export const RUNTIME_MIN = {
27
+ node: { min: '18.0.0', why: 'Bolloon CLI 与依赖 (ESM / 全局 fetch / node: 前缀) 的运行时' },
28
+ npm: { min: '9.0.0', why: '随 Node 18+ 发布; 全局安装与 `update now` 的安装通道' },
29
+ git: { min: '2.20.0', why: '`git -C` / `--porcelain` / worktree —— 源码更新与协作通道' },
30
+ python: { min: '3.8.0', why: 'scripts/** (wiki 门禁/消融夹具) 与 Python Skill 执行' },
31
+ };
32
+ /** Phase 0 平台范围: 三个平台都在内; 未列出的平台 → `unsupported` (不假装能装)。 */
33
+ export const SUPPORTED_PLATFORMS = ['darwin', 'linux', 'win32'];
34
+ // ── 版本比较 (自己实现, 不引依赖) ──────────────────────────────────────────
35
+ export function parseVersionString(raw) {
36
+ if (!raw)
37
+ return null;
38
+ const m = String(raw).match(/\d+\.\d+(\.\d+)?/);
39
+ return m ? m[0] : null;
40
+ }
41
+ export function versionAtLeast(version, min) {
42
+ if (!version)
43
+ return false;
44
+ const a = version.split('.').map((n) => parseInt(n, 10) || 0);
45
+ const b = min.split('.').map((n) => parseInt(n, 10) || 0);
46
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
47
+ const x = a[i] ?? 0;
48
+ const y = b[i] ?? 0;
49
+ if (x > y)
50
+ return true;
51
+ if (x < y)
52
+ return false;
53
+ }
54
+ return true;
55
+ }
56
+ // ── 探测 (纯执行 + 纯解析) ─────────────────────────────────────────────────
57
+ /** 在 PATH + 平台默认目录里找可执行文件 (找不到返回 null, 不猜)。 */
58
+ export function findExecutable(names, envPath = process.env.PATH || '') {
59
+ const exts = process.platform === 'win32' ? ['.exe', '.cmd', '.bat', ''] : [''];
60
+ const dirs = envPath.split(path.delimiter).filter(Boolean);
61
+ if (process.platform === 'win32') {
62
+ const extra = [process.env.ProgramFiles, process.env['ProgramFiles(x86)'], process.env.LOCALAPPDATA]
63
+ .filter(Boolean).map(String);
64
+ for (const e of extra)
65
+ dirs.push(path.join(e, 'Git', 'cmd'), path.join(e, 'Programs', 'Python'));
66
+ }
67
+ for (const dir of dirs) {
68
+ for (const name of names) {
69
+ for (const ext of exts) {
70
+ const p = path.join(dir, name + ext);
71
+ try {
72
+ const st = fs.statSync(p);
73
+ if (st.isFile())
74
+ return p;
75
+ }
76
+ catch { /* 继续 */ }
77
+ }
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+ function runVersion(cmd, args, timeoutMs = 8000) {
83
+ const t0 = Date.now();
84
+ try {
85
+ const out = execFileSync(cmd, args, { encoding: 'utf-8', timeout: timeoutMs, stdio: ['ignore', 'pipe', 'pipe'] });
86
+ return { ok: true, out: String(out).trim(), err: '', ms: Date.now() - t0 };
87
+ }
88
+ catch (e) {
89
+ return { ok: false, out: String(e?.stdout || '').trim(), err: String(e?.stderr || e?.message || '').trim(), ms: Date.now() - t0 };
90
+ }
91
+ }
92
+ /** Windows "App Execution Aliases" 会拦 Python: 路径在 WindowsApps 下且跑不起来/跑成 0 字节。 */
93
+ export function looksLikeStoreAlias(p) {
94
+ if (!p)
95
+ return false;
96
+ return /WindowsApps[\\/]python/i.test(p);
97
+ }
98
+ /** 探测单个运行时: 真执行 `--version` 拿版本 + 绝对路径。 */
99
+ export function probeRuntime(id, opts = {}) {
100
+ const startedAt = new Date().toISOString();
101
+ const notes = [];
102
+ const min = RUNTIME_MIN[id].min;
103
+ const base = {
104
+ runtime: id, status: 'missing', path: null, version: null, source: 'existing',
105
+ meetsMinimum: false, installedByBolloon: false, startedAt, notes,
106
+ };
107
+ // 候选命令: 配置里的绝对路径优先, 然后是 PATH 常见名
108
+ const candidates = [];
109
+ if (opts.preferredPath)
110
+ candidates.push({ cmd: opts.preferredPath, args: id === 'python' ? ['--version'] : ['--version'] });
111
+ if (id === 'node')
112
+ candidates.push({ cmd: 'node', args: ['--version'] });
113
+ if (id === 'npm')
114
+ candidates.push({ cmd: 'npm', args: ['--version'] });
115
+ if (id === 'git')
116
+ candidates.push({ cmd: 'git', args: ['--version'] });
117
+ if (id === 'python') {
118
+ candidates.push({ cmd: 'python3', args: ['--version'] }, { cmd: 'python', args: ['--version'] });
119
+ if (process.platform === 'win32')
120
+ candidates.push({ cmd: 'py', args: ['-3', '--version'] });
121
+ }
122
+ for (const c of candidates) {
123
+ const r = runVersion(c.cmd, c.args);
124
+ const rawVersion = parseVersionString(r.out || r.err);
125
+ const resolved = findExecutable([path.basename(c.cmd)]) || (opts.preferredPath === c.cmd ? c.cmd : null);
126
+ if (!r.ok || !rawVersion) {
127
+ if (looksLikeStoreAlias(resolved)) {
128
+ notes.push('命令指向 Windows Store alias —— 这不是真的 Python 解释器');
129
+ }
130
+ continue;
131
+ }
132
+ if (id === 'python' && looksLikeStoreAlias(resolved)) {
133
+ base.error = 'python 命令指向 Microsoft Store alias';
134
+ notes.push('Windows App Execution Aliases 拦截: 需在「应用执行别名」里关掉 python.exe 或改用官方安装器');
135
+ base.status = 'missing';
136
+ continue;
137
+ }
138
+ const meets = versionAtLeast(rawVersion, min);
139
+ return {
140
+ ...base,
141
+ status: meets ? 'found' : 'failed',
142
+ path: resolved || c.cmd,
143
+ version: rawVersion,
144
+ meetsMinimum: meets,
145
+ verified: false,
146
+ error: meets ? undefined : `${id} ${rawVersion} 低于最低要求 ${min} (${RUNTIME_MIN[id].why})`,
147
+ notes: [
148
+ ...notes,
149
+ ...(opts.preferredPath && resolved && path.resolve(opts.preferredPath) !== path.resolve(resolved)
150
+ ? ['配置里的路径已失效, 已按 PATH 重新发现'] : []),
151
+ ...(opts.preferredPath && !resolved ? ['配置里的路径不可用'] : []),
152
+ ],
153
+ };
154
+ }
155
+ base.error = `找不到可用的 ${id} 命令`;
156
+ return base;
157
+ }
158
+ const PKG_NAME = {
159
+ // 每个包管理器里运行时的包名 (Linux 由发行版适配器决定, 见 Phase 2)
160
+ node: { brew: ['node'], apt: ['nodejs'], dnf: ['nodejs'], yum: ['nodejs'], pacman: ['nodejs'], zypper: ['nodejs'], apk: ['nodejs'], winget: ['OpenJS.NodeJS.LTS'], choco: ['nodejs-lts'] },
161
+ npm: { apt: ['npm'], dnf: ['npm'], yum: ['npm'], pacman: ['npm'], zypper: ['npm'], apk: ['npm'] },
162
+ git: { brew: ['git'], apt: ['git'], dnf: ['git'], yum: ['git'], pacman: ['git'], zypper: ['git'], apk: ['git'], winget: ['Git.Git'], choco: ['git'] },
163
+ python: { brew: ['python'], apt: ['python3', 'python3-venv'], dnf: ['python3', 'python3-pip'], yum: ['python3'], pacman: ['python'], zypper: ['python3'], apk: ['python3'], winget: ['Python.Python.3.12'], choco: ['python3'] },
164
+ };
165
+ /**
166
+ * 由包管理器种类构造管理器对象 (**纯函数**)。
167
+ * 抽出来的理由: winget/choco 的命令形状必须在 Linux/macOS 上也能被单测覆盖 ——
168
+ * 不然"Windows 支持"就只能靠嘴说。
169
+ */
170
+ export function packageManagerFor(kind, pmPath) {
171
+ const needsAdmin = kind === 'apt' || kind === 'dnf' || kind === 'yum' || kind === 'pacman' || kind === 'zypper' || kind === 'apk' || kind === 'choco';
172
+ return {
173
+ kind,
174
+ path: pmPath,
175
+ needsAdmin,
176
+ installCmd: (pkgs) => {
177
+ switch (kind) {
178
+ case 'brew': return ['brew', 'install', ...pkgs];
179
+ case 'choco': return ['choco', 'install', ...pkgs, '-y'];
180
+ case 'winget': return ['winget', 'install', '--silent', '--accept-package-agreements', '--accept-source-agreements', ...pkgs.flatMap((x) => ['--id', x])];
181
+ case 'apt': return ['apt-get', 'install', '-y', ...pkgs];
182
+ case 'pacman': return ['pacman', '-S', '--noconfirm', ...pkgs];
183
+ case 'zypper': return ['zypper', '--non-interactive', 'install', ...pkgs];
184
+ case 'apk': return ['apk', 'add', ...pkgs];
185
+ default: return [kind, 'install', '-y', ...pkgs];
186
+ }
187
+ },
188
+ };
189
+ }
190
+ export function detectPackageManager(platform = process.platform, envPath = process.env.PATH || '') {
191
+ const defs = platform === 'darwin' ? [{ kind: 'brew', bins: ['brew'] }]
192
+ : platform === 'win32' ? [{ kind: 'winget', bins: ['winget'] }, { kind: 'choco', bins: ['choco'] }]
193
+ : [
194
+ { kind: 'apt', bins: ['apt-get'] },
195
+ { kind: 'dnf', bins: ['dnf'] },
196
+ { kind: 'yum', bins: ['yum'] },
197
+ { kind: 'pacman', bins: ['pacman'] },
198
+ { kind: 'zypper', bins: ['zypper'] },
199
+ { kind: 'apk', bins: ['apk'] },
200
+ ];
201
+ for (const d of defs) {
202
+ const p = findExecutable(d.bins, envPath);
203
+ if (!p)
204
+ continue;
205
+ return packageManagerFor(d.kind, p);
206
+ }
207
+ return null;
208
+ }
209
+ /** 发行版识别 (Linux 适配器用; 只读 /etc/os-release)。 */
210
+ export function detectLinuxDistro() {
211
+ try {
212
+ const txt = fs.readFileSync('/etc/os-release', 'utf-8');
213
+ const id = /^ID=(.+)$/m.exec(txt)?.[1]?.replace(/"/g, '') || '';
214
+ const ver = /^VERSION_ID=(.+)$/m.exec(txt)?.[1]?.replace(/"/g, '');
215
+ return id ? { id, version: ver } : null;
216
+ }
217
+ catch {
218
+ return null;
219
+ }
220
+ }
221
+ export function planBootstrap(facts, opts = {}) {
222
+ const platform = opts.platform || process.platform;
223
+ const manager = opts.manager !== undefined ? opts.manager : detectPackageManager(platform, opts.envPath);
224
+ const supported = SUPPORTED_PLATFORMS.includes(platform);
225
+ const missing = facts.filter((f) => f.status === 'missing').map((f) => f.runtime);
226
+ const belowMinimum = facts.filter((f) => f.status === 'failed').map((f) => f.runtime);
227
+ const present = facts.filter((f) => f.status === 'found').map((f) => f.runtime);
228
+ const steps = [];
229
+ const blockers = [];
230
+ const advice = [];
231
+ let needsAdmin = false;
232
+ let pathChanges = false;
233
+ if (!supported) {
234
+ for (const f of facts) {
235
+ steps.push({
236
+ runtime: f.runtime, action: 'unsupported', command: null,
237
+ note: `平台 ${platform} 未在支持矩阵内 (${SUPPORTED_PLATFORMS.join('/')}) —— 不自动安装, 请手动准备运行时`,
238
+ });
239
+ }
240
+ return { platform, present, missing, belowMinimum, manager: manager ? { kind: manager.kind, path: manager.path } : null, steps, needsAdmin: false, pathChanges: false, canAutoInstall: false, blockers: [`不支持的平台 ${platform}`], advice };
241
+ }
242
+ for (const f of facts) {
243
+ if (f.status === 'found') {
244
+ steps.push({ runtime: f.runtime, action: 'reuse', command: null, note: `已有 ${f.version} (${f.path}) —— 复用, 不覆盖用户已有运行时` });
245
+ continue;
246
+ }
247
+ const pkgs = PKG_NAME[f.runtime]?.[manager?.kind || ''] || [];
248
+ if (!manager) {
249
+ steps.push({
250
+ runtime: f.runtime, action: 'manual', command: null,
251
+ note: platform === 'darwin'
252
+ ? '没有 Homebrew —— 不静默安装 Homebrew (会写 /opt/homebrew 或 /usr/local 并可能要管理员密码); 请手动安装 git/python 或先装 Homebrew'
253
+ : '没有可用的包管理器 —— 请手动安装后重跑',
254
+ });
255
+ advice.push(manualAdvice(f.runtime, platform));
256
+ continue;
257
+ }
258
+ if (pkgs.length === 0) {
259
+ steps.push({ runtime: f.runtime, action: 'manual', command: null, note: `${manager.kind} 里没有 ${f.runtime} 的映射包名` });
260
+ advice.push(manualAdvice(f.runtime, platform));
261
+ continue;
262
+ }
263
+ const needsElevation = manager.needsAdmin && typeof process.getuid === 'function' && process.getuid() !== 0;
264
+ const base = manager.installCmd(pkgs);
265
+ const command = needsElevation ? ['sudo', ...base] : base;
266
+ steps.push({
267
+ runtime: f.runtime, action: 'install', command,
268
+ note: needsElevation ? `需要管理员权限 (会执行 sudo, 只在显式同意后)` : `用 ${manager.kind} 安装: ${pkgs.join(', ')}`,
269
+ });
270
+ needsAdmin = needsAdmin || needsElevation;
271
+ pathChanges = true;
272
+ }
273
+ // Python 安装后 PATH 可能变 (brew/pyenv/Windows); node/npm 同理标注
274
+ const canAutoInstall = steps.some((s) => s.action === 'install') && !blockers.length;
275
+ if (missing.includes('git'))
276
+ advice.push('Git 缺失会让「源码更新」与「协作」能力不可用 —— 不把缺 Git 隐藏成后续运行时错误');
277
+ if (missing.includes('python'))
278
+ advice.push('Python 缺失会让 wiki 门禁脚本与 Python Skill 不可用');
279
+ return { platform, distro: platform === 'linux' ? detectLinuxDistro() : null, present, missing, belowMinimum, manager: manager ? { kind: manager.kind, path: manager.path } : null, steps, needsAdmin, pathChanges, canAutoInstall, blockers, advice };
280
+ }
281
+ export function manualAdvice(id, platform) {
282
+ if (platform === 'darwin') {
283
+ return id === 'python'
284
+ ? 'macOS: 装 Homebrew 后 `brew install python`, 或用 python.org 官方安装器 (https://www.python.org/downloads/macos/)'
285
+ : id === 'git' ? 'macOS: `brew install git`, 或 `xcode-select --install` (Command Line Tools 自带 git)'
286
+ : `macOS: \`brew install ${id}\` 或官方安装器`;
287
+ }
288
+ if (platform === 'win32') {
289
+ return id === 'python'
290
+ ? 'Windows: `winget install Python.Python.3.12` (装完到「应用执行别名」关掉 python.exe, 避免 Store alias 劫持)'
291
+ : `Windows: \`winget install ${id === 'git' ? 'Git.Git' : id === 'node' ? 'OpenJS.NodeJS.LTS' : id}\``;
292
+ }
293
+ return `Linux: 用发行版包管理器安装 ${id} (apt: \`sudo apt-get install -y ${id === 'python' ? 'python3' : id === 'node' ? 'nodejs' : id}\`)`;
294
+ }
295
+ export function renderBootstrapPlan(plan) {
296
+ const L = [];
297
+ L.push('运行时预检结果:');
298
+ L.push(` 平台: ${plan.platform}${plan.distro ? ` (${plan.distro.id}${plan.distro.version ? ' ' + plan.distro.version : ''})` : ''}`);
299
+ L.push(` 已就绪: ${plan.present.join(', ') || '(无)'}`);
300
+ if (plan.missing.length)
301
+ L.push(` 缺失: ${plan.missing.join(', ')}`);
302
+ if (plan.belowMinimum.length)
303
+ L.push(` 版本不足: ${plan.belowMinimum.join(', ')}`);
304
+ L.push(` 包管理器: ${plan.manager ? `${plan.manager.kind} (${plan.manager.path})` : '(无)'}`);
305
+ L.push('');
306
+ for (const s of plan.steps) {
307
+ L.push(` [${s.action}] ${s.runtime}: ${s.note}`);
308
+ if (s.command)
309
+ L.push(` ${s.command.join(' ')}`);
310
+ }
311
+ L.push('');
312
+ L.push(` 需要管理员权限: ${plan.needsAdmin ? '是' : '否'}`);
313
+ L.push(` 将修改 PATH: ${plan.pathChanges ? '是' : '否'}`);
314
+ if (plan.blockers.length)
315
+ L.push(` 阻塞: ${plan.blockers.join('; ')}`);
316
+ for (const a of plan.advice)
317
+ L.push(` ⚠ ${a}`);
318
+ return L.join('\n');
319
+ }
320
+ /** git: 真建一个临时仓库并读状态。 */
321
+ export function verifyGitUsable(gitPath) {
322
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bolloon-git-check-'));
323
+ try {
324
+ const init = spawnSync(gitPath, ['init', '-q'], { cwd: dir, encoding: 'utf-8', timeout: 20000 });
325
+ if (init.status !== 0)
326
+ return { ok: false, detail: `git init 失败: ${(init.stderr || '').slice(0, 200)}` };
327
+ fs.writeFileSync(path.join(dir, 'f.txt'), 'x');
328
+ spawnSync(gitPath, ['add', 'f.txt'], { cwd: dir, encoding: 'utf-8', timeout: 20000 });
329
+ const st = spawnSync(gitPath, ['status', '--porcelain'], { cwd: dir, encoding: 'utf-8', timeout: 20000 });
330
+ const out = String(st.stdout || '').trim();
331
+ if (!/^A\s+f\.txt/m.test(out))
332
+ return { ok: false, detail: `git status 读到 "${out}" (期望 A f.txt)` };
333
+ const cfg = spawnSync(gitPath, ['-C', dir, 'rev-parse', '--is-inside-work-tree'], { encoding: 'utf-8', timeout: 20000 });
334
+ if (!/true/.test(String(cfg.stdout)))
335
+ return { ok: false, detail: 'git -C 不可用' };
336
+ return { ok: true, detail: 'git init/add/status/`-C` 真跑通过' };
337
+ }
338
+ finally {
339
+ try {
340
+ fs.rmSync(dir, { recursive: true, force: true });
341
+ }
342
+ catch { /* 忽略 */ }
343
+ }
344
+ }
345
+ /** python: 真跑一段最小脚本。 */
346
+ export function verifyPythonUsable(pyPath) {
347
+ const r = spawnSync(pyPath, ['-c', 'import sys; sys.stdout.write(str(6*7))'], { encoding: 'utf-8', timeout: 20000 });
348
+ if (r.status !== 0)
349
+ return { ok: false, detail: `执行失败: ${(r.stderr || '').slice(0, 200)}` };
350
+ const out = String(r.stdout || '').trim();
351
+ if (out !== '42')
352
+ return { ok: false, detail: `输出 "${out}" (期望 42)` };
353
+ return { ok: true, detail: 'python -c 真跑通过 (6*7=42)' };
354
+ }
355
+ /** node: 真加载 Bolloon CLI 入口并读回版本 (不是只跑 node --version)。 */
356
+ export function verifyNodeLoadsCli(nodePath, entryPath) {
357
+ const r = spawnSync(nodePath, [entryPath, '--version', 'json'], { encoding: 'utf-8', timeout: 180000, maxBuffer: 8 * 1024 * 1024 });
358
+ if (r.status !== 0)
359
+ return { ok: false, detail: `CLI 启动失败 (exit ${r.status}): ${String(r.stderr || '').slice(0, 200)}` };
360
+ const s = String(r.stdout || '');
361
+ const i = s.indexOf('{');
362
+ if (i < 0)
363
+ return { ok: false, detail: 'CLI 没有输出可解析的版本 JSON' };
364
+ try {
365
+ const v = JSON.parse(s.slice(i));
366
+ return { ok: true, detail: `CLI 加载成功, 报出版本 ${v.packageVersion}` };
367
+ }
368
+ catch {
369
+ return { ok: false, detail: '版本 JSON 无法解析' };
370
+ }
371
+ }
372
+ /** npm: 读本地全局安装信息 (网络查询交给 update 检查, 不在这里重复打 registry)。 */
373
+ export function verifyNpmUsable(npmPath) {
374
+ const r = spawnSync(npmPath, ['ls', '-g', '--depth=0', '--json'], { encoding: 'utf-8', timeout: 60000, maxBuffer: 16 * 1024 * 1024 });
375
+ const out = String(r.stdout || '').trim();
376
+ if (!out)
377
+ return { ok: false, detail: `npm ls -g 无输出: ${String(r.stderr || '').slice(0, 200)}` };
378
+ try {
379
+ const data = JSON.parse(out);
380
+ return { ok: true, detail: `npm 可执行, 全局依赖 ${Object.keys(data.dependencies || {}).length} 个` };
381
+ }
382
+ catch {
383
+ return { ok: false, detail: 'npm ls -g 输出无法解析' };
384
+ }
385
+ }
386
+ /** 四个运行时一起做真执行验证。 */
387
+ export async function verifyRuntimesDeep(facts, entryPath) {
388
+ const byId = new Map(facts.map((f) => [f.runtime, f]));
389
+ const out = [];
390
+ for (const f of facts) {
391
+ if (f.status !== 'found' || !f.path) {
392
+ out.push(f);
393
+ continue;
394
+ }
395
+ const at = new Date().toISOString();
396
+ let v = { ok: false, detail: '未验证' };
397
+ if (f.runtime === 'git')
398
+ v = verifyGitUsable(f.path);
399
+ else if (f.runtime === 'python')
400
+ v = verifyPythonUsable(f.path);
401
+ else if (f.runtime === 'npm')
402
+ v = verifyNpmUsable(f.path);
403
+ else if (f.runtime === 'node') {
404
+ v = entryPath ? verifyNodeLoadsCli(f.path, entryPath) : { ok: true, detail: 'node --version 通过 (未提供 CLI 入口)' };
405
+ }
406
+ out.push({
407
+ ...f,
408
+ verified: v.ok,
409
+ lastVerifiedAt: at,
410
+ notes: [...f.notes, v.ok ? v.detail : `真执行验证失败: ${v.detail}`],
411
+ status: v.ok ? f.status : 'failed',
412
+ ...(v.ok ? {} : { meetsMinimum: false, error: v.detail }),
413
+ });
414
+ }
415
+ void byId;
416
+ return out;
417
+ }
418
+ export function buildRuntimeConfig(facts) {
419
+ const out = {};
420
+ for (const f of facts) {
421
+ out[f.runtime] = {
422
+ path: f.path, version: f.version, source: f.source,
423
+ installedByBolloon: f.installedByBolloon,
424
+ lastVerifiedAt: f.lastVerifiedAt || null,
425
+ meetsMinimum: f.meetsMinimum,
426
+ };
427
+ }
428
+ return out;
429
+ }
430
+ /**
431
+ * 写入 `~/.bolloon/config.json` 的 `runtime` 字段。
432
+ * **只动 runtime 一个键**; 文件不存在时创建 (与 postinstall 同一份默认形状); 其余字段原样保留。
433
+ */
434
+ export async function writeRuntimeConfig(home, facts) {
435
+ const configPath = path.join(home, 'config.json');
436
+ let cfg;
437
+ let created = false;
438
+ try {
439
+ cfg = JSON.parse(await fsp.readFile(configPath, 'utf8'));
440
+ }
441
+ catch {
442
+ cfg = { version: 'unknown', initializedAt: new Date().toISOString(), updateChannel: 'stable', checkUpdates: true, autoInstall: false, autoRestart: false };
443
+ created = true;
444
+ }
445
+ cfg.runtime = buildRuntimeConfig(facts);
446
+ cfg.runtimeUpdatedAt = new Date().toISOString();
447
+ await fsp.mkdir(home, { recursive: true });
448
+ const tmp = `${configPath}.tmp-${process.pid}`;
449
+ await fsp.writeFile(tmp, JSON.stringify(cfg, null, 2), 'utf8');
450
+ await fsp.rename(tmp, configPath);
451
+ return { written: true, configPath, created };
452
+ }
453
+ export async function readRuntimeConfig(home = resolveBolloonHome()) {
454
+ try {
455
+ const p = path.join(home, 'config.json');
456
+ const cfg = JSON.parse(await fsp.readFile(p, 'utf8'));
457
+ return (cfg?.runtime && typeof cfg.runtime === 'object') ? cfg.runtime : {};
458
+ }
459
+ catch {
460
+ return {};
461
+ }
462
+ }
463
+ /** 兼容入口: 有些安装只写 bolloon-config.json (正式配置文件) —— runtime.* 也读它作为回退。 */
464
+ export async function readRuntimeConfigWithFallback(home = resolveBolloonHome()) {
465
+ const a = await readRuntimeConfig(home);
466
+ if (Object.keys(a).length)
467
+ return a;
468
+ try {
469
+ const p = path.join(home, CANONICAL_CONFIG_FILE);
470
+ const cfg = JSON.parse(await fsp.readFile(p, 'utf8'));
471
+ return (cfg?.runtime && typeof cfg.runtime === 'object') ? cfg.runtime : {};
472
+ }
473
+ catch {
474
+ return {};
475
+ }
476
+ }
477
+ // ── 能力矩阵 (Phase 5/8 的六行输出) ────────────────────────────────────────
478
+ export function evaluateCapabilities(facts) {
479
+ const ok = (id) => {
480
+ const f = facts.find((x) => x.runtime === id);
481
+ return !!f && f.status === 'found' && f.meetsMinimum && f.verified !== false;
482
+ };
483
+ const core = ok('node') && ok('npm');
484
+ const git = ok('git');
485
+ const py = ok('python');
486
+ return {
487
+ core,
488
+ sourceUpdate: core && git,
489
+ gitCollaboration: core && git,
490
+ pythonSkill: core && py,
491
+ wikiTools: core && git && py,
492
+ };
493
+ }
494
+ /** 探测四个运行时 (Phase 1 的统一出口; install.sh / postinstall / doctor / --version 都走它)。 */
495
+ export async function detectRuntimeReport(opts = {}) {
496
+ const home = opts.home || resolveBolloonHome();
497
+ const cfg = opts.useConfig === false ? {} : await readRuntimeConfigWithFallback(home);
498
+ const facts = ['node', 'npm', 'git', 'python'].map((id) => probeRuntime(id, { preferredPath: cfg[id]?.path ?? null, envPath: opts.envPath }));
499
+ const checkedAt = new Date().toISOString();
500
+ const withVerify = opts.deep ? await verifyRuntimesDeep(facts, opts.entryPath) : facts;
501
+ const caps = evaluateCapabilities(withVerify);
502
+ const missing = withVerify.filter((f) => f.status === 'missing').map((f) => f.runtime);
503
+ const below = withVerify.filter((f) => f.status === 'failed' && !(f.verified === false)).map((f) => f.runtime);
504
+ const failedStage = withVerify.find((f) => f.status === 'failed');
505
+ const ok = missing.length === 0 && withVerify.every((f) => f.status === 'found' && f.meetsMinimum);
506
+ const advice = [];
507
+ for (const f of withVerify) {
508
+ if (f.status === 'found')
509
+ continue;
510
+ advice.push(`${f.runtime}: ${f.error || '不可用'} → ${manualAdvice(f.runtime, process.platform)}`);
511
+ }
512
+ return {
513
+ schema: 'bolloon-runtime/1',
514
+ platform: process.platform,
515
+ arch: process.arch,
516
+ facts: withVerify,
517
+ ok,
518
+ missing,
519
+ belowMinimum: below,
520
+ failedStage: ok ? null : (failedStage ? `${failedStage.runtime} 验证` : (missing.length ? `${missing.join('/')} 缺失` : '运行时检查')),
521
+ advice,
522
+ capabilities: caps,
523
+ checkedAt,
524
+ installed: [],
525
+ dryRun: false,
526
+ };
527
+ }
528
+ function defaultRun(cmd, args) {
529
+ const r = spawnSync(cmd, args, { encoding: 'utf-8', timeout: 1800_000, maxBuffer: 64 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] });
530
+ return { code: r.status ?? 1, out: String(r.stdout || ''), err: String(r.stderr || r.error?.message || '') };
531
+ }
532
+ /**
533
+ * 运行时安装 (Phase 1/2/3/4/5)。
534
+ * 顺序: 探测 → 计划 → (dryRun 停) → 逐项安装 → 重新探测 → 真执行验证 → 写配置。
535
+ * 不满足任何一个必需运行时 → 报告 `ok:false` + `failedStage` + `advice` (退出码由调用方给非 0)。
536
+ */
537
+ export async function bootstrapRuntimes(opts = {}) {
538
+ const home = opts.home || resolveBolloonHome();
539
+ const log = opts.onProgress || (() => { });
540
+ const envPath = opts.envPath || process.env.PATH || '';
541
+ const manager = detectPackageManager(process.platform, envPath);
542
+ const run = opts.run || defaultRun;
543
+ const before = await detectRuntimeReport({ home, useConfig: true, envPath });
544
+ const plan = planBootstrap(before.facts, { manager, envPath });
545
+ const actions = [];
546
+ if (opts.dryRun) {
547
+ log('[dry-run] 只显示计划, 不执行任何安装');
548
+ return {
549
+ ...before, plan, actions, dryRun: true,
550
+ advice: [...before.advice, ...plan.advice.filter((a) => !before.advice.includes(a))],
551
+ };
552
+ }
553
+ if (!opts.yes) {
554
+ log('未获得显式同意 (需要 --yes / 交互确认) —— 不执行安装');
555
+ return {
556
+ ...before, plan, actions,
557
+ advice: [...before.advice, ...plan.advice.filter((a) => !before.advice.includes(a)),
558
+ before.ok ? '' : '确认后重跑: bolloon runtime install (或 install.sh --yes)'].filter(Boolean),
559
+ };
560
+ }
561
+ const installed = [];
562
+ for (const step of plan.steps) {
563
+ if (step.action !== 'install' || !step.command)
564
+ continue;
565
+ const needsSudo = step.command[0] === 'sudo';
566
+ if (needsSudo && !opts.allowSudo) {
567
+ actions.push({ runtime: step.runtime, command: step.command, code: null, action: 'skipped-needs-sudo' });
568
+ log(`跳过 ${step.runtime}: 需要管理员权限, 未显式允许 sudo (不偷偷提权)`);
569
+ continue;
570
+ }
571
+ log(`安装 ${step.runtime}: ${step.command.join(' ')}`);
572
+ const t0 = new Date().toISOString();
573
+ const r = run(step.command[0], step.command.slice(1));
574
+ const t1 = new Date().toISOString();
575
+ actions.push({ runtime: step.runtime, command: step.command, code: r.code, action: 'install' });
576
+ if (r.code !== 0) {
577
+ log(`安装 ${step.runtime} 失败 (exit ${r.code}): ${(r.err || r.out).slice(0, 300)}`);
578
+ }
579
+ else {
580
+ installed.push(step.runtime);
581
+ }
582
+ void t0;
583
+ void t1;
584
+ }
585
+ // 重新探测 (PATH 可能变) + 真执行验证
586
+ const after = await detectRuntimeReport({ home, useConfig: true, deep: true, entryPath: opts.entryPath, envPath });
587
+ const merged = {
588
+ ...after,
589
+ facts: after.facts.map((f) => installed.includes(f.runtime)
590
+ ? { ...f, status: (f.status === 'found' ? 'installed' : f.status), source: manager?.kind || 'official-installer', installedByBolloon: f.status === 'found' }
591
+ : f),
592
+ installed,
593
+ dryRun: false,
594
+ };
595
+ // 能力矩阵要用最终状态重算
596
+ merged.capabilities = evaluateCapabilities(merged.facts);
597
+ const stillMissing = merged.facts.filter((f) => f.status !== 'found');
598
+ merged.ok = stillMissing.length === 0;
599
+ merged.missing = merged.facts.filter((f) => f.status === 'missing').map((f) => f.runtime);
600
+ merged.failedStage = merged.ok ? null : `运行时验证 (${stillMissing.map((f) => f.runtime).join('/')})`;
601
+ const extraAdvice = stillMissing.map((f) => `${f.runtime}: ${f.error || '仍不可用'} → ${manualAdvice(f.runtime, process.platform)}`);
602
+ merged.advice = Array.from(new Set([...merged.advice, ...plan.advice, ...extraAdvice]));
603
+ if (opts.configurePath !== false) {
604
+ try {
605
+ await writeRuntimeConfig(home, merged.facts);
606
+ log(`已写入运行时配置: ${path.join(home, 'config.json')} (只动 runtime 字段)`);
607
+ }
608
+ catch (e) {
609
+ merged.advice.push(`写运行时配置失败: ${e?.message || e}`);
610
+ }
611
+ }
612
+ // 运行时补齐成功 → 清掉 postinstall 留下的"安装未完成"标记
613
+ if (merged.ok) {
614
+ try {
615
+ await fsp.unlink(path.join(home, 'install-incomplete.json'));
616
+ }
617
+ catch { /* 没有就算了 */ }
618
+ }
619
+ return { ...merged, plan, actions };
620
+ }
621
+ // ── 报告渲染 (Phase 5 的两种形状) ──────────────────────────────────────────
622
+ const CAP_LABEL = {
623
+ core: '核心运行', sourceUpdate: '源码更新', gitCollaboration: 'Git 协作',
624
+ pythonSkill: 'Python Skill', wikiTools: 'Wiki 工具',
625
+ };
626
+ export function renderRuntimeReport(rep, opts = {}) {
627
+ const L = [];
628
+ const nameOf = { node: 'Node.js', npm: 'npm', git: 'Git', python: 'Python' };
629
+ if (!rep.ok) {
630
+ const bad = rep.facts.filter((f) => f.status !== 'found');
631
+ L.push('Bolloon 安装未完成');
632
+ L.push(`失败阶段: ${rep.failedStage || '运行时检查'}`);
633
+ for (const f of bad)
634
+ L.push(`${nameOf[f.runtime]}: ${f.error || '不可用'}${f.path ? ` (路径 ${f.path})` : ''}`);
635
+ if (rep.advice.length) {
636
+ L.push('处理建议:');
637
+ for (const a of rep.advice)
638
+ L.push(` - ${a}`);
639
+ }
640
+ L.push('');
641
+ L.push('(模拟/联调提示: 修复后重跑 `bolloon runtime check`, 或 `bolloon runtime install`)');
642
+ return L.join('\n');
643
+ }
644
+ L.push(rep.installed.length ? 'Bolloon 安装完成 (含本次安装的运行时)' : 'Bolloon 运行时检查通过');
645
+ L.push('');
646
+ for (const f of rep.facts) {
647
+ const extra = opts.verbose ? ` ${f.path || ''} [${f.source}${f.installedByBolloon ? ', 由 Bolloon 安装' : ''}${f.lastVerifiedAt ? `, 验证于 ${f.lastVerifiedAt}` : ''}]` : '';
648
+ L.push(`${nameOf[f.runtime].padEnd(8)} ✓ ${(f.version || '?').padEnd(10)}${extra}`);
649
+ }
650
+ L.push('');
651
+ for (const [k, label] of Object.entries(CAP_LABEL)) {
652
+ L.push(`${label.padEnd(14)} ${rep.capabilities[k] ? '可用' : '不可用'}`);
653
+ }
654
+ return L.join('\n');
655
+ }
656
+ /** `bolloon --version` 的运行时一节 (leo: 展示安装信息时要展示这些配置)。 */
657
+ export async function readIncompleteMarker(home = resolveBolloonHome()) {
658
+ try {
659
+ return JSON.parse(await fsp.readFile(path.join(home, 'install-incomplete.json'), 'utf8'));
660
+ }
661
+ catch {
662
+ return null;
663
+ }
664
+ }
665
+ export function renderRuntimeLines(rep, opts = {}) {
666
+ const nameOf = { node: 'Node.js', npm: 'npm', git: 'Git', python: 'Python' };
667
+ const L = [];
668
+ // 配置里还没写 runtime.* 时不要假装"来自配置" —— 那是实时探测的结果
669
+ L.push(opts.configBacked
670
+ ? '运行时配置: (来自 ~/.bolloon/config.json 的 runtime.*, 每次启动重新验证)'
671
+ : '运行时配置: (实时探测 — 配置里还没有 runtime.*; 跑 `bolloon runtime` 会写入)');
672
+ for (const f of rep.facts) {
673
+ const mark = f.status === 'found' ? '✓' : '✗';
674
+ const src = f.installedByBolloon ? '由 Bolloon 安装' : f.source === 'existing' ? '已有' : f.source;
675
+ L.push(` ${mark} ${nameOf[f.runtime].padEnd(8)} ${(f.version || '未找到').padEnd(10)} ${f.path || '-'} [${src}]`);
676
+ }
677
+ if (opts.verbose) {
678
+ L.push(` 能力: 核心运行=${rep.capabilities.core ? '可用' : '不可用'} · 源码更新=${rep.capabilities.sourceUpdate ? '可用' : '不可用'} · Python Skill=${rep.capabilities.pythonSkill ? '可用' : '不可用'} · Wiki 工具=${rep.capabilities.wikiTools ? '可用' : '不可用'}`);
679
+ L.push(` 检查时间: ${rep.checkedAt}`);
680
+ }
681
+ return L;
682
+ }