@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.
- package/bin/bolloon.cjs +18 -148
- package/bin/bolloon.cmd +6 -3
- package/dist/agents/pi-sdk-tools.js +3 -1
- package/dist/agents/pi-sdk.js +4 -1
- package/dist/cli/update-commands.js +349 -0
- package/dist/cli-entry.js +41 -55
- package/dist/electron-build/agents/agent-gateway.js +169 -0
- package/dist/electron-build/agents/agent-gateway.js.map +1 -0
- package/dist/electron-build/agents/agent-identity-store.js +212 -0
- package/dist/electron-build/agents/agent-identity-store.js.map +1 -0
- package/dist/electron-build/agents/agent-identity.js +196 -0
- package/dist/electron-build/agents/agent-identity.js.map +1 -0
- package/dist/electron-build/agents/agent-manifest-protocol.js +151 -0
- package/dist/electron-build/agents/agent-manifest-protocol.js.map +1 -0
- package/dist/electron-build/agents/agent-registry.js +217 -0
- package/dist/electron-build/agents/agent-registry.js.map +1 -0
- package/dist/electron-build/agents/agent-reputation.js +60 -0
- package/dist/electron-build/agents/agent-reputation.js.map +1 -0
- package/dist/electron-build/agents/agent-service-client.js +186 -0
- package/dist/electron-build/agents/agent-service-client.js.map +1 -0
- package/dist/electron-build/agents/browser-cdp.js +765 -0
- package/dist/electron-build/agents/browser-cdp.js.map +1 -0
- package/dist/electron-build/agents/computer-use.js +341 -0
- package/dist/electron-build/agents/computer-use.js.map +1 -0
- package/dist/electron-build/agents/constraint-layer.js +210 -0
- package/dist/electron-build/agents/constraint-layer.js.map +1 -0
- package/dist/electron-build/agents/decision-store.js +292 -0
- package/dist/electron-build/agents/decision-store.js.map +1 -0
- package/dist/electron-build/agents/deny-pipeline.js +125 -0
- package/dist/electron-build/agents/deny-pipeline.js.map +1 -0
- package/dist/electron-build/agents/economic-policy.js +172 -0
- package/dist/electron-build/agents/economic-policy.js.map +1 -0
- package/dist/electron-build/agents/error-classifier.js +125 -0
- package/dist/electron-build/agents/error-classifier.js.map +1 -0
- package/dist/electron-build/agents/execution-supervisor.js +539 -0
- package/dist/electron-build/agents/execution-supervisor.js.map +1 -0
- package/dist/electron-build/agents/external-events.js +171 -0
- package/dist/electron-build/agents/external-events.js.map +1 -0
- package/dist/electron-build/agents/gateway-join.js +315 -0
- package/dist/electron-build/agents/gateway-join.js.map +1 -0
- package/dist/electron-build/agents/gateway-network.js +505 -0
- package/dist/electron-build/agents/gateway-network.js.map +1 -0
- package/dist/electron-build/agents/goal-criteria.js +133 -0
- package/dist/electron-build/agents/goal-criteria.js.map +1 -0
- package/dist/electron-build/agents/goal-resume.js +364 -0
- package/dist/electron-build/agents/goal-resume.js.map +1 -0
- package/dist/electron-build/agents/goal-store.js +587 -0
- package/dist/electron-build/agents/goal-store.js.map +1 -0
- package/dist/electron-build/agents/intent-classifier.js +104 -0
- package/dist/electron-build/agents/intent-classifier.js.map +1 -0
- package/dist/electron-build/agents/iroh-secret.js +70 -0
- package/dist/electron-build/agents/iroh-secret.js.map +1 -0
- package/dist/electron-build/agents/loop-review.js +101 -0
- package/dist/electron-build/agents/loop-review.js.map +1 -0
- package/dist/electron-build/agents/memory-recall.js +154 -0
- package/dist/electron-build/agents/memory-recall.js.map +1 -0
- package/dist/electron-build/agents/p2p-document-tools.js +328 -0
- package/dist/electron-build/agents/p2p-document-tools.js.map +1 -0
- package/dist/electron-build/agents/parse-tool-call.js +564 -0
- package/dist/electron-build/agents/parse-tool-call.js.map +1 -0
- package/dist/electron-build/agents/patch-tool.js +205 -0
- package/dist/electron-build/agents/patch-tool.js.map +1 -0
- package/dist/electron-build/agents/payment-approval.js +183 -0
- package/dist/electron-build/agents/payment-approval.js.map +1 -0
- package/dist/electron-build/agents/payment-gate.js +139 -0
- package/dist/electron-build/agents/payment-gate.js.map +1 -0
- package/dist/electron-build/agents/permission-mode.js +124 -0
- package/dist/electron-build/agents/permission-mode.js.map +1 -0
- package/dist/electron-build/agents/pi-harness.js +268 -0
- package/dist/electron-build/agents/pi-harness.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk-session-factory.js +117 -0
- package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk-session-manager.js +335 -0
- package/dist/electron-build/agents/pi-sdk-session-manager.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk-tools.js +4042 -0
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk-types.js +17 -0
- package/dist/electron-build/agents/pi-sdk-types.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk.js +3325 -0
- package/dist/electron-build/agents/pi-sdk.js.map +1 -0
- package/dist/electron-build/agents/plan-store.js +212 -0
- package/dist/electron-build/agents/plan-store.js.map +1 -0
- package/dist/electron-build/agents/pre-tool-validator.js +200 -0
- package/dist/electron-build/agents/pre-tool-validator.js.map +1 -0
- package/dist/electron-build/agents/process-runner.js +148 -0
- package/dist/electron-build/agents/process-runner.js.map +1 -0
- package/dist/electron-build/agents/react-loop.js +131 -0
- package/dist/electron-build/agents/react-loop.js.map +1 -0
- package/dist/electron-build/agents/resource-store.js +180 -0
- package/dist/electron-build/agents/resource-store.js.map +1 -0
- package/dist/electron-build/agents/resource-token.js +118 -0
- package/dist/electron-build/agents/resource-token.js.map +1 -0
- package/dist/electron-build/agents/resource-wallet.js +84 -0
- package/dist/electron-build/agents/resource-wallet.js.map +1 -0
- package/dist/electron-build/agents/run-store.js +854 -0
- package/dist/electron-build/agents/run-store.js.map +1 -0
- package/dist/electron-build/agents/runner-resolver.js +267 -0
- package/dist/electron-build/agents/runner-resolver.js.map +1 -0
- package/dist/electron-build/agents/session-store.js +294 -0
- package/dist/electron-build/agents/session-store.js.map +1 -0
- package/dist/electron-build/agents/shell-guard.js +465 -0
- package/dist/electron-build/agents/shell-guard.js.map +1 -0
- package/dist/electron-build/agents/shell-tool.js +102 -0
- package/dist/electron-build/agents/shell-tool.js.map +1 -0
- package/dist/electron-build/agents/skill-loader.js +216 -0
- package/dist/electron-build/agents/skill-loader.js.map +1 -0
- package/dist/electron-build/agents/skill-readiness.js +174 -0
- package/dist/electron-build/agents/skill-readiness.js.map +1 -0
- package/dist/electron-build/agents/skill-share.js +394 -0
- package/dist/electron-build/agents/skill-share.js.map +1 -0
- package/dist/electron-build/agents/skill-supervisor-link.js +75 -0
- package/dist/electron-build/agents/skill-supervisor-link.js.map +1 -0
- package/dist/electron-build/agents/skill-writer.js +347 -0
- package/dist/electron-build/agents/skill-writer.js.map +1 -0
- package/dist/electron-build/agents/skills-manager.js +763 -0
- package/dist/electron-build/agents/skills-manager.js.map +1 -0
- package/dist/electron-build/agents/supervisor-host.js +294 -0
- package/dist/electron-build/agents/supervisor-host.js.map +1 -0
- package/dist/electron-build/agents/task/local-seller.js +188 -0
- package/dist/electron-build/agents/task/local-seller.js.map +1 -0
- package/dist/electron-build/agents/task/report-card.js +152 -0
- package/dist/electron-build/agents/task/report-card.js.map +1 -0
- package/dist/electron-build/agents/task/resource-advisor.js +222 -0
- package/dist/electron-build/agents/task/resource-advisor.js.map +1 -0
- package/dist/electron-build/agents/task/task-budget.js +111 -0
- package/dist/electron-build/agents/task/task-budget.js.map +1 -0
- package/dist/electron-build/agents/task/task-runner.js +670 -0
- package/dist/electron-build/agents/task/task-runner.js.map +1 -0
- package/dist/electron-build/agents/task-state.js +266 -0
- package/dist/electron-build/agents/task-state.js.map +1 -0
- package/dist/electron-build/agents/tool-registry.js +141 -0
- package/dist/electron-build/agents/tool-registry.js.map +1 -0
- package/dist/electron-build/agents/treasury-bridge.js +165 -0
- package/dist/electron-build/agents/treasury-bridge.js.map +1 -0
- package/dist/electron-build/agents/user-questions.js +223 -0
- package/dist/electron-build/agents/user-questions.js.map +1 -0
- package/dist/electron-build/agents/verify-recipe.js +90 -0
- package/dist/electron-build/agents/verify-recipe.js.map +1 -0
- package/dist/electron-build/agents/workflow-engine.js +222 -0
- package/dist/electron-build/agents/workflow-engine.js.map +1 -0
- package/dist/electron-build/agents/workflow-pivot-loop.js +988 -0
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -0
- package/dist/electron-build/agents/write-staging.js +133 -0
- package/dist/electron-build/agents/write-staging.js.map +1 -0
- package/dist/electron-build/agents/x402/goal-run-bridge.js +115 -0
- package/dist/electron-build/agents/x402/goal-run-bridge.js.map +1 -0
- package/dist/electron-build/agents/x402/milestone-settlement.js +163 -0
- package/dist/electron-build/agents/x402/milestone-settlement.js.map +1 -0
- package/dist/electron-build/agents/x402/paid-info-protocol.js +274 -0
- package/dist/electron-build/agents/x402/paid-info-protocol.js.map +1 -0
- package/dist/electron-build/agents/x402/paid-info-store.js +409 -0
- package/dist/electron-build/agents/x402/paid-info-store.js.map +1 -0
- package/dist/electron-build/agents/x402/paid-info-tools.js +346 -0
- package/dist/electron-build/agents/x402/paid-info-tools.js.map +1 -0
- package/dist/electron-build/agents/x402/payment-recovery.js +330 -0
- package/dist/electron-build/agents/x402/payment-recovery.js.map +1 -0
- package/dist/electron-build/agents/x402/resource-contract.js +533 -0
- package/dist/electron-build/agents/x402/resource-contract.js.map +1 -0
- package/dist/electron-build/agents/x402/settlement-state.js +432 -0
- package/dist/electron-build/agents/x402/settlement-state.js.map +1 -0
- package/dist/electron-build/agents/x402/trade.js +294 -0
- package/dist/electron-build/agents/x402/trade.js.map +1 -0
- package/dist/electron-build/agents/x402/transaction-protocol.js +109 -0
- package/dist/electron-build/agents/x402/transaction-protocol.js.map +1 -0
- package/dist/electron-build/agents/x402/transaction-store.js +404 -0
- package/dist/electron-build/agents/x402/transaction-store.js.map +1 -0
- package/dist/electron-build/agents/x402/x402Pay.js +377 -0
- package/dist/electron-build/agents/x402/x402Pay.js.map +1 -0
- package/dist/electron-build/bollharness-integration/context-router-judgment.js +269 -0
- package/dist/electron-build/bollharness-integration/context-router-judgment.js.map +1 -0
- package/dist/electron-build/bollharness-integration/context-router.js +584 -0
- package/dist/electron-build/bollharness-integration/context-router.js.map +1 -0
- package/dist/electron-build/bollharness-integration/gate-state-machine.js +362 -0
- package/dist/electron-build/bollharness-integration/gate-state-machine.js.map +1 -0
- package/dist/electron-build/bollharness-integration/gate-transition-hooks.js +136 -0
- package/dist/electron-build/bollharness-integration/gate-transition-hooks.js.map +1 -0
- package/dist/electron-build/bollharness-integration/guard-checker.js +400 -0
- package/dist/electron-build/bollharness-integration/guard-checker.js.map +1 -0
- package/dist/electron-build/bollharness-integration/index.js +123 -0
- package/dist/electron-build/bollharness-integration/index.js.map +1 -0
- package/dist/electron-build/bollharness-integration/integration.js +531 -0
- package/dist/electron-build/bollharness-integration/integration.js.map +1 -0
- package/dist/electron-build/bollharness-integration/skill-adapter.js +608 -0
- package/dist/electron-build/bollharness-integration/skill-adapter.js.map +1 -0
- package/dist/electron-build/bootstrap/bootstrap.js +173 -0
- package/dist/electron-build/bootstrap/bootstrap.js.map +1 -0
- package/dist/electron-build/bootstrap/context-collector.js +358 -0
- package/dist/electron-build/bootstrap/context-collector.js.map +1 -0
- package/dist/electron-build/bootstrap/context-hierarchy.js +262 -0
- package/dist/electron-build/bootstrap/context-hierarchy.js.map +1 -0
- package/dist/electron-build/bootstrap/context-manager.js +211 -0
- package/dist/electron-build/bootstrap/context-manager.js.map +1 -0
- package/dist/electron-build/bootstrap/context-os.js +277 -0
- package/dist/electron-build/bootstrap/context-os.js.map +1 -0
- package/dist/electron-build/bootstrap/event-log.js +203 -0
- package/dist/electron-build/bootstrap/event-log.js.map +1 -0
- package/dist/electron-build/bootstrap/exhaust-scrubber.js +277 -0
- package/dist/electron-build/bootstrap/exhaust-scrubber.js.map +1 -0
- package/dist/electron-build/bootstrap/lifecycle-hooks.js +282 -0
- package/dist/electron-build/bootstrap/lifecycle-hooks.js.map +1 -0
- package/dist/electron-build/bootstrap/memory-compressor.js +377 -0
- package/dist/electron-build/bootstrap/memory-compressor.js.map +1 -0
- package/dist/electron-build/bootstrap/persona-loader.js +219 -0
- package/dist/electron-build/bootstrap/persona-loader.js.map +1 -0
- package/dist/electron-build/bootstrap/project-context.js +162 -0
- package/dist/electron-build/bootstrap/project-context.js.map +1 -0
- package/dist/electron-build/bootstrap/project-state.js +205 -0
- package/dist/electron-build/bootstrap/project-state.js.map +1 -0
- package/dist/electron-build/bootstrap/session-window.js +162 -0
- package/dist/electron-build/bootstrap/session-window.js.map +1 -0
- package/dist/electron-build/bootstrap/vector-index.js +291 -0
- package/dist/electron-build/bootstrap/vector-index.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +22 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js +86 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +37 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +20 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +29 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +28 -0
- package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js +10 -0
- package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js +68 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js +14 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js +17 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js +59 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js +29 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js +14 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js.map +1 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js +29 -0
- package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js.map +1 -0
- package/dist/electron-build/constraints/index.js +11 -0
- package/dist/electron-build/constraints/index.js.map +1 -0
- package/dist/electron-build/context-compaction/auto-compact.js +182 -0
- package/dist/electron-build/context-compaction/auto-compact.js.map +1 -0
- package/dist/electron-build/context-compaction/budget-gate.js +32 -0
- package/dist/electron-build/context-compaction/budget-gate.js.map +1 -0
- package/dist/electron-build/context-compaction/budget-reduce.js +39 -0
- package/dist/electron-build/context-compaction/budget-reduce.js.map +1 -0
- package/dist/electron-build/context-compaction/context-collapse.js +71 -0
- package/dist/electron-build/context-compaction/context-collapse.js.map +1 -0
- package/dist/electron-build/context-compaction/index.js +38 -0
- package/dist/electron-build/context-compaction/index.js.map +1 -0
- package/dist/electron-build/context-compaction/microcompact.js +55 -0
- package/dist/electron-build/context-compaction/microcompact.js.map +1 -0
- package/dist/electron-build/context-compaction/pipeline.js +128 -0
- package/dist/electron-build/context-compaction/pipeline.js.map +1 -0
- package/dist/electron-build/context-compaction/snip.js +50 -0
- package/dist/electron-build/context-compaction/snip.js.map +1 -0
- package/dist/electron-build/context-compaction/token-estimator.js +40 -0
- package/dist/electron-build/context-compaction/token-estimator.js.map +1 -0
- package/dist/electron-build/context-compaction/types.js +21 -0
- package/dist/electron-build/context-compaction/types.js.map +1 -0
- package/dist/electron-build/cron/tick-lock.js +247 -0
- package/dist/electron-build/cron/tick-lock.js.map +1 -0
- package/dist/electron-build/documents/reader.js +131 -0
- package/dist/electron-build/documents/reader.js.map +1 -0
- package/dist/electron-build/documents/store.js +220 -0
- package/dist/electron-build/documents/store.js.map +1 -0
- package/dist/electron-build/external-engines/delegate-handle.js +76 -0
- package/dist/electron-build/external-engines/delegate-handle.js.map +1 -0
- package/dist/electron-build/external-engines/delegate.js +225 -0
- package/dist/electron-build/external-engines/delegate.js.map +1 -0
- package/dist/electron-build/external-engines/discovery.js +448 -0
- package/dist/electron-build/external-engines/discovery.js.map +1 -0
- package/dist/electron-build/external-engines/types.js +13 -0
- package/dist/electron-build/external-engines/types.js.map +1 -0
- package/dist/electron-build/hooks/hooks-engine.js +367 -0
- package/dist/electron-build/hooks/hooks-engine.js.map +1 -0
- package/dist/electron-build/judgeness/reflect.js +100 -0
- package/dist/electron-build/judgeness/reflect.js.map +1 -0
- package/dist/electron-build/judgeness/store.js +536 -0
- package/dist/electron-build/judgeness/store.js.map +1 -0
- package/dist/electron-build/judgeness/types.js +21 -0
- package/dist/electron-build/judgeness/types.js.map +1 -0
- package/dist/electron-build/llm/config-store.js +551 -0
- package/dist/electron-build/llm/config-store.js.map +1 -0
- package/dist/electron-build/llm/error-lessons.js +76 -0
- package/dist/electron-build/llm/error-lessons.js.map +1 -0
- package/dist/electron-build/llm/pi-ai.js +830 -0
- package/dist/electron-build/llm/pi-ai.js.map +1 -0
- package/dist/electron-build/llm/system-prompt/registry.js +318 -0
- package/dist/electron-build/llm/system-prompt/registry.js.map +1 -0
- package/dist/electron-build/llm/system-prompt/strip-hibsml.js +55 -0
- package/dist/electron-build/llm/system-prompt/strip-hibsml.js.map +1 -0
- package/dist/electron-build/locales/en.js +32 -0
- package/dist/electron-build/locales/en.js.map +1 -0
- package/dist/electron-build/locales/zh.js +30 -0
- package/dist/electron-build/locales/zh.js.map +1 -0
- package/dist/electron-build/lsp/lsp-manager.js +327 -0
- package/dist/electron-build/lsp/lsp-manager.js.map +1 -0
- package/dist/electron-build/lsp/lsp-tools.js +226 -0
- package/dist/electron-build/lsp/lsp-tools.js.map +1 -0
- package/dist/electron-build/migration/external-agent-migrator.js +451 -0
- package/dist/electron-build/migration/external-agent-migrator.js.map +1 -0
- package/dist/electron-build/network/agent-network.js +775 -0
- package/dist/electron-build/network/agent-network.js.map +1 -0
- package/dist/electron-build/network/goal-event-bridge.js +62 -0
- package/dist/electron-build/network/goal-event-bridge.js.map +1 -0
- package/dist/electron-build/network/iroh-integration.js +117 -0
- package/dist/electron-build/network/iroh-integration.js.map +1 -0
- package/dist/electron-build/network/iroh-transport.js +550 -0
- package/dist/electron-build/network/iroh-transport.js.map +1 -0
- package/dist/electron-build/network/p2p.js +1103 -0
- package/dist/electron-build/network/p2p.js.map +1 -0
- package/dist/electron-build/network/storage/adapters/json-adapter.js +416 -0
- package/dist/electron-build/network/storage/adapters/json-adapter.js.map +1 -0
- package/dist/electron-build/network/storage/types.js +18 -0
- package/dist/electron-build/network/storage/types.js.map +1 -0
- package/dist/electron-build/orbitdb/agent-tools.js +402 -0
- package/dist/electron-build/orbitdb/agent-tools.js.map +1 -0
- package/dist/electron-build/orbitdb/cid-database.js +284 -0
- package/dist/electron-build/orbitdb/cid-database.js.map +1 -0
- package/dist/electron-build/orbitdb/context-store.js +99 -0
- package/dist/electron-build/orbitdb/context-store.js.map +1 -0
- package/dist/electron-build/orbitdb/ipfs-node.js +120 -0
- package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -0
- package/dist/electron-build/orbitdb/kanban-store.js +299 -0
- package/dist/electron-build/orbitdb/kanban-store.js.map +1 -0
- package/dist/electron-build/orbitdb/task-store.js +155 -0
- package/dist/electron-build/orbitdb/task-store.js.map +1 -0
- package/dist/electron-build/orbitdb/trajectory-store.js +194 -0
- package/dist/electron-build/orbitdb/trajectory-store.js.map +1 -0
- package/dist/electron-build/orbitdb/ui-cid.js +77 -0
- package/dist/electron-build/orbitdb/ui-cid.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-a2ui/index.js +89 -0
- package/dist/electron-build/pi-ecosystem-a2ui/index.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-goals/index.js +512 -0
- package/dist/electron-build/pi-ecosystem-goals/index.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js +325 -0
- package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js +492 -0
- package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/cleanup.js +167 -0
- package/dist/electron-build/pi-ecosystem-judgment/cleanup.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/decision.js +321 -0
- package/dist/electron-build/pi-ecosystem-judgment/decision.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js +175 -0
- package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js +232 -0
- package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/distillation.js +304 -0
- package/dist/electron-build/pi-ecosystem-judgment/distillation.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js +176 -0
- package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js +65 -0
- package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js +808 -0
- package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/index.js +508 -0
- package/dist/electron-build/pi-ecosystem-judgment/index.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js +334 -0
- package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js +228 -0
- package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/value-injection.js +598 -0
- package/dist/electron-build/pi-ecosystem-judgment/value-injection.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-mcp/index.js +643 -0
- package/dist/electron-build/pi-ecosystem-mcp/index.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js +116 -0
- package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-subagents/index.js +352 -0
- package/dist/electron-build/pi-ecosystem-subagents/index.js.map +1 -0
- package/dist/electron-build/security/builtin-guards.js +133 -0
- package/dist/electron-build/security/builtin-guards.js.map +1 -0
- package/dist/electron-build/security/context-router-tool.js +111 -0
- package/dist/electron-build/security/context-router-tool.js.map +1 -0
- package/dist/electron-build/security/input-scanner.js +263 -0
- package/dist/electron-build/security/input-scanner.js.map +1 -0
- package/dist/electron-build/security/react-harness.js +148 -0
- package/dist/electron-build/security/react-harness.js.map +1 -0
- package/dist/electron-build/security/tool-gate.js +287 -0
- package/dist/electron-build/security/tool-gate.js.map +1 -0
- package/dist/electron-build/setup/setup-store.js +648 -0
- package/dist/electron-build/setup/setup-store.js.map +1 -0
- package/dist/electron-build/social/channels/ChannelManager.js +444 -0
- package/dist/electron-build/social/channels/ChannelManager.js.map +1 -0
- package/dist/electron-build/social/channels/DiapChannelBridge.js +451 -0
- package/dist/electron-build/social/channels/DiapChannelBridge.js.map +1 -0
- package/dist/electron-build/social/channels/InterestMatcher.js +135 -0
- package/dist/electron-build/social/channels/InterestMatcher.js.map +1 -0
- package/dist/electron-build/social/channels/types.js +21 -0
- package/dist/electron-build/social/channels/types.js.map +1 -0
- package/dist/electron-build/social/global-shared-context.js +368 -0
- package/dist/electron-build/social/global-shared-context.js.map +1 -0
- package/dist/electron-build/social/heartbeat.js +882 -0
- package/dist/electron-build/social/heartbeat.js.map +1 -0
- package/dist/electron-build/storage/did-catalog-bridge.js +314 -0
- package/dist/electron-build/storage/did-catalog-bridge.js.map +1 -0
- package/dist/electron-build/storage/did-catalog.js +272 -0
- package/dist/electron-build/storage/did-catalog.js.map +1 -0
- package/dist/electron-build/utils/auto-update.js +140 -558
- package/dist/electron-build/utils/auto-update.js.map +1 -1
- package/dist/electron-build/utils/module-context.js +98 -0
- package/dist/electron-build/utils/module-context.js.map +1 -0
- package/dist/electron-build/utils/runtime-bootstrap.js +745 -0
- package/dist/electron-build/utils/runtime-bootstrap.js.map +1 -0
- package/dist/electron-build/utils/update-manager.js +770 -0
- package/dist/electron-build/utils/update-manager.js.map +1 -0
- package/dist/electron-build/utils/update-state.js +406 -0
- package/dist/electron-build/utils/update-state.js.map +1 -0
- package/dist/electron-build/utils/version-info.js +562 -0
- package/dist/electron-build/utils/version-info.js.map +1 -0
- package/dist/electron-build/web/i18n.js +146 -0
- package/dist/electron-build/web/i18n.js.map +1 -0
- package/dist/electron-build/web/routes-x402-info.js +232 -0
- package/dist/electron-build/web/routes-x402-info.js.map +1 -0
- package/dist/electron-build/web/server-storage.js +390 -0
- package/dist/electron-build/web/server-storage.js.map +1 -0
- package/dist/electron-build/web/server-types.js +52 -0
- package/dist/electron-build/web/server-types.js.map +1 -0
- package/dist/electron-build/web/task-deps.js +41 -0
- package/dist/electron-build/web/task-deps.js.map +1 -0
- package/dist/index.js +28 -27
- package/dist/llm/system-prompt/registry.js +6 -3
- package/dist/utils/auto-update.js +138 -525
- package/dist/utils/module-context.js +59 -0
- package/dist/utils/runtime-bootstrap.js +682 -0
- package/dist/utils/update-cli.js +82 -0
- package/dist/utils/update-health.js +401 -0
- package/dist/utils/update-manager.js +716 -0
- package/dist/utils/update-state.js +353 -0
- package/dist/utils/version-info.js +510 -0
- package/package.json +1 -1
- package/scripts/build-cli.js +32 -151
- package/scripts/postinstall.js +153 -76
|
@@ -0,0 +1,770 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* update-manager.ts — 更新系统的**唯一决策者** (Phase 2/4/5, 2026-09-19)
|
|
4
|
+
*
|
|
5
|
+
* 职责只有三件 (不多做):
|
|
6
|
+
* ① 识别当前安装 (`detectInstallation`)
|
|
7
|
+
* ② 查询目标版本 (npm registry, 唯一稳定渠道)
|
|
8
|
+
* ③ 形成更新计划 (`buildUpdatePlan`) / 执行更新 (`applyUpdate`)
|
|
9
|
+
*
|
|
10
|
+
* 它**不**直接改用户配置, **不**默认自动安装, **不**碰 `~/.bolloon` 的用户数据
|
|
11
|
+
* (goals / runs / transactions / skills / config 一律不动)。
|
|
12
|
+
*
|
|
13
|
+
* 渠道决定 (2026-09-19, 冻结): **npm 是唯一稳定发行渠道**; GitHub 只作为源码与发布记录。
|
|
14
|
+
* 因此安装脚本不再优先查 GitHub Releases, 版本解析也只有一份 (本模块)。
|
|
15
|
+
*
|
|
16
|
+
* 与计划的刻意偏差 (如实记录, 见 docs/wiki/update-protocol.md §5):
|
|
17
|
+
* "安装到临时位置 → 原子切换" 落成 **"临时位置下载并校验 tarball → 交给 npm 完成替换 → 验证可启动 → 失败回滚"**。
|
|
18
|
+
* 理由: 手工把整棵 node_modules (949 个包) 复制/切换一遍, 比 npm 自己的替换更危险也更容易半更新;
|
|
19
|
+
* 真正要保的性质 ("不能删掉旧版本后才发现新版本起不来") 由**切换后验证 + 失败回滚**保证, 这两步是真跑的。
|
|
20
|
+
*/
|
|
21
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
24
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
25
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(o, k2, desc);
|
|
28
|
+
}) : (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
o[k2] = m[k];
|
|
31
|
+
}));
|
|
32
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
33
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34
|
+
}) : function(o, v) {
|
|
35
|
+
o["default"] = v;
|
|
36
|
+
});
|
|
37
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
38
|
+
var ownKeys = function(o) {
|
|
39
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
40
|
+
var ar = [];
|
|
41
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
42
|
+
return ar;
|
|
43
|
+
};
|
|
44
|
+
return ownKeys(o);
|
|
45
|
+
};
|
|
46
|
+
return function (mod) {
|
|
47
|
+
if (mod && mod.__esModule) return mod;
|
|
48
|
+
var result = {};
|
|
49
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
50
|
+
__setModuleDefault(result, mod);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.NPM_FETCH_RETRY_FLAGS = exports.IN_FLIGHT_STAGES = exports.MIN_FREE_BYTES = void 0;
|
|
56
|
+
exports.parseJsonFromStdout = parseJsonFromStdout;
|
|
57
|
+
exports.parseVersion = parseVersion;
|
|
58
|
+
exports.compareVersions = compareVersions;
|
|
59
|
+
exports.isKnownVersion = isKnownVersion;
|
|
60
|
+
exports.classifyRegistryError = classifyRegistryError;
|
|
61
|
+
exports.queryRegistryDoc = queryRegistryDoc;
|
|
62
|
+
exports.checkForUpdate = checkForUpdate;
|
|
63
|
+
exports.freeBytesAt = freeBytesAt;
|
|
64
|
+
exports.buildUpdatePlan = buildUpdatePlan;
|
|
65
|
+
exports.renderUpdatePlan = renderUpdatePlan;
|
|
66
|
+
exports.validateStagedPackage = validateStagedPackage;
|
|
67
|
+
exports.installedVersionOnDisk = installedVersionOnDisk;
|
|
68
|
+
exports.applyUpdate = applyUpdate;
|
|
69
|
+
exports.readUpdateStatus = readUpdateStatus;
|
|
70
|
+
exports.readHistory = readHistory;
|
|
71
|
+
exports.renderHistory = renderHistory;
|
|
72
|
+
exports.updateSummaryFor = updateSummaryFor;
|
|
73
|
+
const os = __importStar(require("os"));
|
|
74
|
+
const path = __importStar(require("path"));
|
|
75
|
+
const fs = __importStar(require("fs"));
|
|
76
|
+
const fsp = __importStar(require("fs/promises"));
|
|
77
|
+
const https = __importStar(require("https"));
|
|
78
|
+
const http = __importStar(require("http"));
|
|
79
|
+
const child_process_1 = require("child_process");
|
|
80
|
+
const version_info_js_1 = require("./version-info.js");
|
|
81
|
+
const update_state_js_1 = require("./update-state.js");
|
|
82
|
+
// ── 版本比较 (唯一一份) ─────────────────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* 从子进程 stdout 里取 JSON —— **不要**按"行首是否 { "过滤:
|
|
85
|
+
* `JSON.stringify(x, null, 2)` 是**多行**的, 只留第一行 `{` 会解析失败
|
|
86
|
+
* (真跑抓到过: 更新后验证永远判失败 → 每次都"回滚").
|
|
87
|
+
*/
|
|
88
|
+
function parseJsonFromStdout(stdout) {
|
|
89
|
+
const s = String(stdout || '');
|
|
90
|
+
const start = s.indexOf('{');
|
|
91
|
+
if (start < 0)
|
|
92
|
+
return null;
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(s.slice(start));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// 尾部可能有非 JSON 输出: 退一步只取到最后一个 }
|
|
98
|
+
const end = s.lastIndexOf('}');
|
|
99
|
+
if (end > start) {
|
|
100
|
+
try {
|
|
101
|
+
return JSON.parse(s.slice(start, end + 1));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function parseVersion(v) {
|
|
111
|
+
const clean = String(v || '').trim().replace(/^v/, '').split('-')[0];
|
|
112
|
+
const parts = clean.split('.').map((p) => parseInt(p.replace(/\D.*$/, ''), 10));
|
|
113
|
+
return parts.map((n) => (Number.isFinite(n) ? n : 0));
|
|
114
|
+
}
|
|
115
|
+
/** -1 = a<b, 0 = 相等, 1 = a>b (只比数值段, 忽略预发布标签) */
|
|
116
|
+
function compareVersions(a, b) {
|
|
117
|
+
const pa = parseVersion(a);
|
|
118
|
+
const pb = parseVersion(b);
|
|
119
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
120
|
+
const x = pa[i] ?? 0;
|
|
121
|
+
const y = pb[i] ?? 0;
|
|
122
|
+
if (x < y)
|
|
123
|
+
return -1;
|
|
124
|
+
if (x > y)
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
function isKnownVersion(v) {
|
|
130
|
+
return !!v && v !== 'unknown' && /^\d/.test(String(v).trim().replace(/^v/, ''));
|
|
131
|
+
}
|
|
132
|
+
function httpGetJson(url, timeoutMs = 10000) {
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
const client = url.startsWith('https') ? https : http;
|
|
135
|
+
const req = client.get(url, { timeout: timeoutMs, headers: { Accept: 'application/json' } }, (res) => {
|
|
136
|
+
let data = '';
|
|
137
|
+
res.on('data', (c) => { data += c; });
|
|
138
|
+
res.on('end', () => resolve({ status: res.statusCode || 0, body: data }));
|
|
139
|
+
});
|
|
140
|
+
req.on('error', reject);
|
|
141
|
+
req.on('timeout', () => { req.destroy(new Error('timeout')); });
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const OFFLINE_CODES = new Set(['ENOTFOUND', 'EAI_AGAIN', 'ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT', 'EHOSTUNREACH', 'ENETUNREACH', 'ENETDOWN', 'EAI_FAIL', 'UND_ERR_CONNECT_TIMEOUT']);
|
|
145
|
+
/** 网络类错误 → offline; 其它 (HTTP 5xx / 解析失败 / 包不存在) → registry_unavailable。 */
|
|
146
|
+
function classifyRegistryError(err, httpStatus) {
|
|
147
|
+
const code = String(err?.code || '');
|
|
148
|
+
if (OFFLINE_CODES.has(code) || /timeout|timed out|ENOTFOUND|getaddrinfo|network|socket hang up|超时/i.test(String(err?.message || ''))) {
|
|
149
|
+
return { kind: 'offline', detail: `${code || err?.message || '网络不可达'}` };
|
|
150
|
+
}
|
|
151
|
+
if (httpStatus && httpStatus >= 500)
|
|
152
|
+
return { kind: 'registry_unavailable', detail: `registry 返回 HTTP ${httpStatus}` };
|
|
153
|
+
if (httpStatus === 404)
|
|
154
|
+
return { kind: 'registry_unavailable', detail: `registry 上没有 ${version_info_js_1.PKG_NAME} (HTTP 404)` };
|
|
155
|
+
if (httpStatus && httpStatus >= 400)
|
|
156
|
+
return { kind: 'registry_unavailable', detail: `registry 返回 HTTP ${httpStatus}` };
|
|
157
|
+
return { kind: 'registry_unavailable', detail: code || err?.message || '未知错误' };
|
|
158
|
+
}
|
|
159
|
+
async function queryRegistryDoc(pkg = version_info_js_1.PKG_NAME, timeoutMs = 10000) {
|
|
160
|
+
const url = `${version_info_js_1.NPM_REGISTRY_BASE}/${encodeURIComponent(pkg).replace('%40', '@')}`;
|
|
161
|
+
try {
|
|
162
|
+
const { status, body } = await httpGetJson(url, timeoutMs);
|
|
163
|
+
if (status < 200 || status >= 300)
|
|
164
|
+
return { ok: false, ...classifyRegistryError(null, status) };
|
|
165
|
+
let raw;
|
|
166
|
+
try {
|
|
167
|
+
raw = JSON.parse(body);
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
return { ok: false, kind: 'registry_unavailable', detail: 'registry 返回了无法解析的内容' };
|
|
171
|
+
}
|
|
172
|
+
const distTags = (raw?.['dist-tags'] || {});
|
|
173
|
+
const versions = Object.keys(raw?.versions || {});
|
|
174
|
+
if (!distTags.latest && versions.length === 0) {
|
|
175
|
+
return { ok: false, kind: 'registry_unavailable', detail: 'registry 上没有可用版本' };
|
|
176
|
+
}
|
|
177
|
+
const gitHeads = {};
|
|
178
|
+
for (const v of versions) {
|
|
179
|
+
const gh = raw.versions[v]?.gitHead;
|
|
180
|
+
if (typeof gh === 'string' && gh)
|
|
181
|
+
gitHeads[v] = gh;
|
|
182
|
+
}
|
|
183
|
+
return { ok: true, doc: { latest: distTags.latest || versions[versions.length - 1], distTags, versions, gitHeads } };
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
return { ok: false, ...classifyRegistryError(e) };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 检查更新。**这是唯一的检查入口** —— CLI / 启动后台 / Python 检查器 / 安装脚本都走它。
|
|
191
|
+
*
|
|
192
|
+
* 结论优先级 (刻意定死, 防"模糊行为"):
|
|
193
|
+
* 1. 读不到本地版本 → local_version_unknown (绝不默认 0.0.0 后继续)
|
|
194
|
+
* 2. 安装方式不支持自动更新 → unsupported_installation (仍会带出 latestVersion)
|
|
195
|
+
* 3. 显式跳过 / 节流 → check_skipped (结论来自缓存)
|
|
196
|
+
* 4. 网络不可达 → offline (绝不显示"已是最新")
|
|
197
|
+
* 5. registry 不可用 / 包不存在 → registry_unavailable
|
|
198
|
+
* 6. latest > current → update_available
|
|
199
|
+
* 7. 否则 → up_to_date
|
|
200
|
+
*/
|
|
201
|
+
async function checkForUpdate(opts = {}) {
|
|
202
|
+
const home = opts.home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
203
|
+
const prefs = await (0, update_state_js_1.readUpdatePrefs)({ home, env: opts.env });
|
|
204
|
+
const channel = (0, version_info_js_1.resolveUpdateChannel)(opts.channel || prefs.channel);
|
|
205
|
+
const install = opts.installation || (0, version_info_js_1.detectInstallation)({ home });
|
|
206
|
+
const pkg = (0, version_info_js_1.readPackageAt)(install.packageRoot);
|
|
207
|
+
const current = isKnownVersion(pkg?.version) ? String(pkg?.version) : 'unknown';
|
|
208
|
+
const now = new Date().toISOString();
|
|
209
|
+
const state = await (0, update_state_js_1.readUpdateState)(home);
|
|
210
|
+
const persist = opts.persist !== false;
|
|
211
|
+
const base = {
|
|
212
|
+
currentVersion: current,
|
|
213
|
+
channel,
|
|
214
|
+
source: install.updateSource,
|
|
215
|
+
installMethod: install.method,
|
|
216
|
+
checkedAt: now,
|
|
217
|
+
fromCache: false,
|
|
218
|
+
};
|
|
219
|
+
const commit = async (r) => {
|
|
220
|
+
if (persist) {
|
|
221
|
+
await (0, update_state_js_1.writeUpdateState)({
|
|
222
|
+
currentVersion: r.currentVersion,
|
|
223
|
+
latestVersion: r.latestVersion,
|
|
224
|
+
channel: r.channel,
|
|
225
|
+
installMethod: r.installMethod,
|
|
226
|
+
installDir: install.installDir,
|
|
227
|
+
entryPath: install.entryPath,
|
|
228
|
+
nodeVersion: process.version.replace(/^v/, ''),
|
|
229
|
+
platform: os.platform(),
|
|
230
|
+
arch: os.arch(),
|
|
231
|
+
lastCheckAt: r.checkedAt,
|
|
232
|
+
lastCheckStatus: r.status,
|
|
233
|
+
lastCheckReason: r.reason,
|
|
234
|
+
}, home);
|
|
235
|
+
}
|
|
236
|
+
return r;
|
|
237
|
+
};
|
|
238
|
+
// 1. 本地版本读不到 —— 不猜
|
|
239
|
+
if (!isKnownVersion(current)) {
|
|
240
|
+
return commit({ ...base, status: 'local_version_unknown', latestVersion: null, reason: `读不到 ${install.packageRoot}/package.json 的版本` });
|
|
241
|
+
}
|
|
242
|
+
// 3. 显式跳过 / 节流
|
|
243
|
+
const throttled = !opts.force && state.lastCheckAt
|
|
244
|
+
? (Date.now() - Date.parse(state.lastCheckAt)) < prefs.checkIntervalHours * 3600_000
|
|
245
|
+
: false;
|
|
246
|
+
const useCache = !!opts.offline || throttled;
|
|
247
|
+
if (useCache && state.lastCheckStatus) {
|
|
248
|
+
// 语义: 本次**没有真的检查** → 结论就是 check_skipped, 上次的结论原样带出来
|
|
249
|
+
// (绝不把缓存里的 update_available/up_to_date 冒充成"刚查出来的")
|
|
250
|
+
const cached = state.lastCheckStatus;
|
|
251
|
+
const r = await commit({
|
|
252
|
+
...base, fromCache: true,
|
|
253
|
+
status: 'check_skipped',
|
|
254
|
+
cachedStatus: cached,
|
|
255
|
+
latestVersion: state.latestVersion,
|
|
256
|
+
reason: opts.offline
|
|
257
|
+
? `离线模式: 使用缓存结论 (${cached})`
|
|
258
|
+
: `距上次检查不足 ${prefs.checkIntervalHours}h, 使用缓存结论 (${cached})`,
|
|
259
|
+
checkedAt: state.lastCheckAt || now,
|
|
260
|
+
});
|
|
261
|
+
if (persist)
|
|
262
|
+
await (0, update_state_js_1.writeUpdateState)({ lastCheckReason: r.reason }, home);
|
|
263
|
+
return r;
|
|
264
|
+
}
|
|
265
|
+
// 2. 安装方式不支持自动更新 —— 仍把 latest / 可回滚性带出来, 但结论就是"不支持"
|
|
266
|
+
const registry = opts.registry || await queryRegistryDoc(version_info_js_1.PKG_NAME);
|
|
267
|
+
const latest = registry.ok ? (registry.doc.distTags[(0, version_info_js_1.distTagForChannel)(channel)] || registry.doc.latest) : null;
|
|
268
|
+
const targetPublishedOf = (v) => v && registry.ok ? registry.doc.versions.includes(v) : undefined;
|
|
269
|
+
const rollbackSupportedOf = registry.ok ? registry.doc.versions.includes(current) : undefined;
|
|
270
|
+
if (install.method === 'development' || install.method === 'unknown' || install.method === 'release-binary') {
|
|
271
|
+
return commit({
|
|
272
|
+
...base, status: 'unsupported_installation', latestVersion: latest,
|
|
273
|
+
reason: `${install.reason}; 这种安装方式不支持自动更新`,
|
|
274
|
+
targetPublished: targetPublishedOf(latest),
|
|
275
|
+
rollbackSupported: rollbackSupportedOf,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
// 4/5. registry 拿不到 —— 绝不显示"已是最新"
|
|
279
|
+
if (!registry.ok) {
|
|
280
|
+
return commit({
|
|
281
|
+
...base,
|
|
282
|
+
status: registry.kind === 'offline' ? 'offline' : 'registry_unavailable',
|
|
283
|
+
latestVersion: null,
|
|
284
|
+
reason: registry.detail,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
const targetPublished = !!latest && registry.doc.versions.includes(latest);
|
|
288
|
+
const rollbackSupported = rollbackSupportedOf === true;
|
|
289
|
+
// 6/7. 比较
|
|
290
|
+
if (latest && compareVersions(current, latest) < 0) {
|
|
291
|
+
return commit({
|
|
292
|
+
...base, status: 'update_available', latestVersion: latest, targetPublished, rollbackSupported,
|
|
293
|
+
reason: `当前 ${current} → 目标 ${latest}`,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
return commit({ ...base, status: 'up_to_date', latestVersion: latest, targetPublished, rollbackSupported });
|
|
297
|
+
}
|
|
298
|
+
const WILL_NOT_TOUCH = [
|
|
299
|
+
'~/.bolloon/config.json',
|
|
300
|
+
'~/.bolloon/goals/',
|
|
301
|
+
'~/.bolloon/runs/',
|
|
302
|
+
'~/.bolloon/transactions/',
|
|
303
|
+
'~/.bolloon/skills/',
|
|
304
|
+
'~/.bolloon/sessions/',
|
|
305
|
+
'~/.bolloon/identity/',
|
|
306
|
+
];
|
|
307
|
+
/** 磁盘余量 (字节)。statfs 不可用时返回 null (不假装知道)。 */
|
|
308
|
+
function freeBytesAt(dir) {
|
|
309
|
+
try {
|
|
310
|
+
const st = fs.statfsSync?.(dir);
|
|
311
|
+
if (!st)
|
|
312
|
+
return null;
|
|
313
|
+
return Number(st.bavail) * Number(st.bsize);
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
exports.MIN_FREE_BYTES = 300 * 1024 * 1024;
|
|
320
|
+
/** 安装类风险: 与"机器上有没有在跑的任务"无关, 任何计划都要评估 (测试也不许跳过)。 */
|
|
321
|
+
async function collectInstallRisk(install) {
|
|
322
|
+
const out = [];
|
|
323
|
+
out.push({
|
|
324
|
+
id: 'install_method', label: '安装方式支持自动更新', ok: install.method === 'npm-global', blocking: true,
|
|
325
|
+
detail: install.method === 'npm-global'
|
|
326
|
+
? `npm 全局安装 (${install.installDir})`
|
|
327
|
+
: `${install.method}: ${install.reason} (请用对应方式更新: git pull + npm run build:all / 项目的包管理)`,
|
|
328
|
+
});
|
|
329
|
+
out.push({
|
|
330
|
+
id: 'install_dir_writable', label: '安装目录可写', ok: install.writable, blocking: true,
|
|
331
|
+
detail: install.writable ? install.installDir : `${install.installDir} 不可写 (需要 sudo 或改 npm prefix)`,
|
|
332
|
+
});
|
|
333
|
+
const free = freeBytesAt(install.installDir);
|
|
334
|
+
out.push({
|
|
335
|
+
id: 'disk_space', label: '磁盘空间充足', ok: free === null ? true : free >= exports.MIN_FREE_BYTES,
|
|
336
|
+
blocking: free === null ? false : free < exports.MIN_FREE_BYTES,
|
|
337
|
+
detail: free === null ? '无法读取磁盘余量 (跳过)' : `${(free / 1024 / 1024 / 1024).toFixed(2)} GiB 可用 (需 ≥ ${(exports.MIN_FREE_BYTES / 1024 / 1024).toFixed(0)} MiB)`,
|
|
338
|
+
});
|
|
339
|
+
const lock = (0, update_state_js_1.readUpdateLock)();
|
|
340
|
+
out.push({
|
|
341
|
+
id: 'update_lock', label: '没有其它更新进程', ok: !lock || (0, update_state_js_1.lockIsStale)(lock), blocking: !!lock && !(0, update_state_js_1.lockIsStale)(lock),
|
|
342
|
+
detail: !lock ? '无更新锁'
|
|
343
|
+
: (0, update_state_js_1.lockIsStale)(lock) ? `存在陈旧锁 (pid ${lock.pid}, ${lock.at}) — 可回收`
|
|
344
|
+
: `另一个更新进程持有锁 (pid ${lock.pid}, ${lock.at})`,
|
|
345
|
+
});
|
|
346
|
+
return out;
|
|
347
|
+
}
|
|
348
|
+
/** 负载类风险: Supervisor / Goal / Run / 支付 (非阻塞提醒, 但会把默认策略变成"等 Run 结束")。 */
|
|
349
|
+
async function collectWorkloadRisk() {
|
|
350
|
+
const out = [];
|
|
351
|
+
try {
|
|
352
|
+
const { supervisorStatePath } = await Promise.resolve().then(() => __importStar(require('../agents/supervisor-host.js')));
|
|
353
|
+
let sup = null;
|
|
354
|
+
try {
|
|
355
|
+
sup = JSON.parse(await fsp.readFile(supervisorStatePath(), 'utf8'));
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
sup = null;
|
|
359
|
+
}
|
|
360
|
+
const alive = sup && typeof sup.pid === 'number' ? (() => { try {
|
|
361
|
+
process.kill(sup.pid, 0);
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
catch (e) {
|
|
365
|
+
return e?.code === 'EPERM';
|
|
366
|
+
} })() : false;
|
|
367
|
+
const running = !!sup && alive && !sup.stoppedAt;
|
|
368
|
+
out.push({
|
|
369
|
+
id: 'supervisor_running', label: 'Supervisor 未在运行', ok: !running, blocking: false, advisory: true,
|
|
370
|
+
detail: running ? `Supervisor 正在运行 (pid ${sup.pid}, owner ${sup.owner}, 最近 tick ${sup.lastTickAt || '未知'})` : '无运行中的 Supervisor 宿主',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
out.push({ id: 'supervisor_running', label: 'Supervisor 未在运行', ok: true, blocking: false, advisory: true, detail: '无法读取 supervisor.json (按未运行处理)' });
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const { listGoals } = await Promise.resolve().then(() => __importStar(require('../agents/goal-store.js')));
|
|
378
|
+
const goals = await listGoals({ status: ['open', 'active', 'recovering', 'retry_wait', 'awaiting_external', 'stalled'], limit: 50 });
|
|
379
|
+
out.push({
|
|
380
|
+
id: 'active_goals', label: '没有进行中的 Goal', ok: goals.length === 0, blocking: false, advisory: true,
|
|
381
|
+
detail: goals.length === 0 ? '无进行中 Goal' : `${goals.length} 个未收尾 Goal (${goals.slice(0, 3).map((g) => `${g.goalId}:${g.status}`).join(', ')}${goals.length > 3 ? ', …' : ''})`,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
out.push({ id: 'active_goals', label: '没有进行中的 Goal', ok: true, blocking: false, advisory: true, detail: '无法读取 goals (按无处理)' });
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
const { listRuns } = await Promise.resolve().then(() => __importStar(require('../agents/run-store.js')));
|
|
389
|
+
const runs = await listRuns({ status: ['queued', 'running', 'recovering', 'paused', 'awaiting_external', 'interrupted', 'stalled'], limit: 50 });
|
|
390
|
+
out.push({
|
|
391
|
+
id: 'active_runs', label: '没有进行中的 Run', ok: runs.length === 0, blocking: false, advisory: true,
|
|
392
|
+
detail: runs.length === 0 ? '无进行中 Run' : `${runs.length} 个未收尾 Run (${runs.slice(0, 3).map((r) => `${r.runId}:${r.status}`).join(', ')}${runs.length > 3 ? ', …' : ''})`,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
out.push({ id: 'active_runs', label: '没有进行中的 Run', ok: true, blocking: false, advisory: true, detail: '无法读取 runs (按无处理)' });
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
const { pendingTransactions } = await Promise.resolve().then(() => __importStar(require('../agents/x402/transaction-store.js')));
|
|
400
|
+
const pend = await pendingTransactions();
|
|
401
|
+
const paying = pend.filter((t) => ['paying', 'payment_required'].includes(t.status));
|
|
402
|
+
out.push({
|
|
403
|
+
id: 'payment_in_flight', label: '没有支付中的交易', ok: paying.length === 0, blocking: false, advisory: true,
|
|
404
|
+
detail: paying.length === 0
|
|
405
|
+
? (pend.length ? `${pend.length} 笔待收尾交易 (无支付中, 可继续)` : '无待收尾交易')
|
|
406
|
+
: `${paying.length} 笔支付中/待付交易 (${paying.slice(0, 3).map((t) => t.id || t.transactionId).join(', ')}) — 更新前应先对账`,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
out.push({ id: 'payment_in_flight', label: '没有支付中的交易', ok: true, blocking: false, advisory: true, detail: '无法读取 transactions (按无处理)' });
|
|
411
|
+
}
|
|
412
|
+
return out;
|
|
413
|
+
}
|
|
414
|
+
async function buildUpdatePlan(opts = {}) {
|
|
415
|
+
const home = opts.home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
416
|
+
const install = opts.installation || (0, version_info_js_1.detectInstallation)({ home });
|
|
417
|
+
const check = await checkForUpdate({ ...opts, home, persist: false, installation: install });
|
|
418
|
+
const risk = [
|
|
419
|
+
...await collectInstallRisk(install),
|
|
420
|
+
...(opts.workloadRiskOverride || await collectWorkloadRisk()),
|
|
421
|
+
];
|
|
422
|
+
// registry 侧风险项来自检查结论
|
|
423
|
+
risk.push({
|
|
424
|
+
id: 'registry_reachable',
|
|
425
|
+
label: 'registry 可达',
|
|
426
|
+
ok: check.status !== 'offline' && check.status !== 'registry_unavailable',
|
|
427
|
+
blocking: check.status === 'offline' || check.status === 'registry_unavailable' || check.status === 'local_version_unknown',
|
|
428
|
+
detail: check.status === 'offline' ? `离线: ${check.reason}`
|
|
429
|
+
: check.status === 'registry_unavailable' ? `registry 不可用: ${check.reason}`
|
|
430
|
+
: 'npm registry 可达',
|
|
431
|
+
});
|
|
432
|
+
risk.push({
|
|
433
|
+
id: 'target_published',
|
|
434
|
+
label: '目标版本真实存在',
|
|
435
|
+
ok: check.targetPublished !== false,
|
|
436
|
+
blocking: !!check.latestVersion && check.targetPublished === false,
|
|
437
|
+
detail: check.targetPublished === false
|
|
438
|
+
? `registry 上没有 ${version_info_js_1.PKG_NAME}@${check.latestVersion} — 不执行更新`
|
|
439
|
+
: check.targetPublished === true ? `已确认 ${check.latestVersion} 可下载` : '未检查 (离线)',
|
|
440
|
+
});
|
|
441
|
+
risk.push({
|
|
442
|
+
id: 'rollback_supported',
|
|
443
|
+
label: '当前版本可回滚',
|
|
444
|
+
ok: check.rollbackSupported !== false,
|
|
445
|
+
blocking: false,
|
|
446
|
+
detail: check.rollbackSupported === false
|
|
447
|
+
? `registry 上找不到当前版本 ${check.currentVersion} — 更新失败将无法用 npm 回滚`
|
|
448
|
+
: check.rollbackSupported === true ? `registry 上存在 ${check.currentVersion} (可回滚)` : '未检查 (离线)',
|
|
449
|
+
});
|
|
450
|
+
const blockers = risk.filter((r) => !r.ok && r.blocking).map((r) => `${r.label}: ${r.detail}`);
|
|
451
|
+
const advisories = risk.filter((r) => !r.ok && !r.blocking).map((r) => `${r.label}: ${r.detail}`);
|
|
452
|
+
const target = check.latestVersion && compareVersions(check.currentVersion, check.latestVersion) < 0
|
|
453
|
+
? check.latestVersion
|
|
454
|
+
: null;
|
|
455
|
+
return {
|
|
456
|
+
ok: blockers.length === 0 && !!target,
|
|
457
|
+
currentVersion: check.currentVersion,
|
|
458
|
+
targetVersion: target,
|
|
459
|
+
channel: check.channel,
|
|
460
|
+
installMethod: check.installMethod,
|
|
461
|
+
source: check.source,
|
|
462
|
+
installDir: install.installDir,
|
|
463
|
+
needsRestart: !!target,
|
|
464
|
+
willUpdate: target && install.method === 'npm-global' ? [version_info_js_1.PKG_NAME, version_info_js_1.CONSTRAINT_PKG_NAME] : [],
|
|
465
|
+
willNotTouch: WILL_NOT_TOUCH,
|
|
466
|
+
risk, blockers, advisories,
|
|
467
|
+
strategies: ['now', 'wait', 'cancel'],
|
|
468
|
+
defaultStrategy: advisories.length > 0 ? 'wait' : 'now',
|
|
469
|
+
check,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
function renderUpdatePlan(plan) {
|
|
473
|
+
const L = [];
|
|
474
|
+
L.push(`当前版本: ${plan.currentVersion}`);
|
|
475
|
+
L.push(`目标版本: ${plan.targetVersion || '(无可用更新)'}`);
|
|
476
|
+
L.push(`安装方式: ${plan.installMethod}`);
|
|
477
|
+
L.push(`更新通道: ${plan.channel} (来源: ${plan.source})`);
|
|
478
|
+
L.push(`安装目录: ${plan.installDir}`);
|
|
479
|
+
L.push('');
|
|
480
|
+
L.push('将更新:');
|
|
481
|
+
if (plan.willUpdate.length === 0)
|
|
482
|
+
L.push(' (无 — 当前没有可执行的更新)');
|
|
483
|
+
for (const p of plan.willUpdate)
|
|
484
|
+
L.push(` ${p}`);
|
|
485
|
+
L.push('');
|
|
486
|
+
L.push('不会修改:');
|
|
487
|
+
for (const p of plan.willNotTouch)
|
|
488
|
+
L.push(` ${p}`);
|
|
489
|
+
L.push('');
|
|
490
|
+
L.push(`需要重启: ${plan.needsRestart ? '是' : '否'}`);
|
|
491
|
+
L.push(`风险检查: ${plan.blockers.length === 0 ? '通过' : `未通过 (${plan.blockers.length} 项阻塞)`}`);
|
|
492
|
+
for (const r of plan.risk)
|
|
493
|
+
L.push(` ${r.ok ? '✓' : r.blocking ? '✗' : '!'} ${r.label}: ${r.detail}`);
|
|
494
|
+
if (plan.blockers.length) {
|
|
495
|
+
L.push('');
|
|
496
|
+
L.push('阻塞项 (修好才能更新):');
|
|
497
|
+
for (const b of plan.blockers)
|
|
498
|
+
L.push(` - ${b}`);
|
|
499
|
+
}
|
|
500
|
+
if (plan.advisories.length) {
|
|
501
|
+
L.push('');
|
|
502
|
+
L.push('提醒 (不阻塞, 但建议先处理):');
|
|
503
|
+
for (const a of plan.advisories)
|
|
504
|
+
L.push(` - ${a}`);
|
|
505
|
+
L.push(` 建议策略: 等当前 Run 结束后更新 (bolloon update --now --wait)`);
|
|
506
|
+
}
|
|
507
|
+
L.push('');
|
|
508
|
+
L.push('可选: 立即更新 (bolloon update --now) / 等当前 Run 结束 (bolloon update --now --wait) / 取消');
|
|
509
|
+
L.push(`默认: ${plan.defaultStrategy === 'wait' ? '等待当前 Run 结束后更新' : '立即更新'}`);
|
|
510
|
+
return L.join('\n');
|
|
511
|
+
}
|
|
512
|
+
/** 进行中的阶段 (落盘时看到它 = 上次更新被中断; 与 update-state 的 IN_FLIGHT_RUN_STATUSES 同义) */
|
|
513
|
+
exports.IN_FLIGHT_STAGES = ['planned', 'downloading', 'staged', 'switching', 'verifying'];
|
|
514
|
+
/** npm 默认只重试 2 次/10s —— 真网络抖动会让一次干净安装失败 (本机 ECONNRESET 实测)。 */
|
|
515
|
+
exports.NPM_FETCH_RETRY_FLAGS = [
|
|
516
|
+
'--fetch-retries=5', '--fetch-retry-mintimeout=10000', '--fetch-retry-maxtimeout=120000',
|
|
517
|
+
];
|
|
518
|
+
function defaultRunNpm(args, cwd) {
|
|
519
|
+
const finalArgs = args[0] === 'pack' || args[0] === 'install' ? [...args, ...exports.NPM_FETCH_RETRY_FLAGS] : args;
|
|
520
|
+
const r = (0, child_process_1.spawnSync)('npm', finalArgs, { cwd, encoding: 'utf-8', timeout: 900_000, maxBuffer: 32 * 1024 * 1024 });
|
|
521
|
+
return { code: r.status ?? 1, stdout: r.stdout || '', stderr: r.stderr || '' };
|
|
522
|
+
}
|
|
523
|
+
/** 校验一个解压后的包目录: 版本对得上 + 入口存在。 */
|
|
524
|
+
function validateStagedPackage(dir, target) {
|
|
525
|
+
const pkg = (0, version_info_js_1.readPackageAt)(dir);
|
|
526
|
+
if (!pkg)
|
|
527
|
+
return { ok: false, detail: `${dir}/package.json 读不到` };
|
|
528
|
+
if (pkg.version !== target)
|
|
529
|
+
return { ok: false, detail: `临时目录版本 ${pkg.version} ≠ 目标 ${target}` };
|
|
530
|
+
const entry = path.join(dir, 'dist', 'cli-entry.js');
|
|
531
|
+
if (!fs.existsSync(entry))
|
|
532
|
+
return { ok: false, detail: '包内缺少 dist/cli-entry.js' };
|
|
533
|
+
return { ok: true, detail: `版本 ${pkg.version} + 入口存在` };
|
|
534
|
+
}
|
|
535
|
+
/** 读"磁盘上真的装了什么版本" (不看进程内存), 供切换后验证。 */
|
|
536
|
+
function installedVersionOnDisk(installRoot) {
|
|
537
|
+
return (0, version_info_js_1.readPackageAt)(installRoot)?.version ?? null;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* 执行更新。
|
|
541
|
+
*
|
|
542
|
+
* 流水线: 计划(检查+锁) → 下载 tarball 到临时目录并校验 → 切换(npm 替换) → 验证 → 成功/回滚。
|
|
543
|
+
* 任何一步失败: 清理临时目录、保留旧版本、写失败原因、释放锁、用户继续用旧版本。
|
|
544
|
+
*/
|
|
545
|
+
async function applyUpdate(opts = {}) {
|
|
546
|
+
const started = Date.now();
|
|
547
|
+
const home = opts.home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
548
|
+
const install = opts.installation || (0, version_info_js_1.detectInstallation)({ home });
|
|
549
|
+
/** 落盘"进行中"的阶段 —— 这样进程被 SIGKILL 时盘上会留下证据 (doctor 报"上次更新异常中断") */
|
|
550
|
+
const markInFlight = async (s, detail) => {
|
|
551
|
+
if (!exports.IN_FLIGHT_STAGES.includes(s))
|
|
552
|
+
return;
|
|
553
|
+
try {
|
|
554
|
+
await (0, update_state_js_1.writeUpdateState)({
|
|
555
|
+
lastUpdate: { at: new Date().toISOString(), from, to, status: s, reason: detail },
|
|
556
|
+
}, home);
|
|
557
|
+
}
|
|
558
|
+
catch { /* 阶段留痕写失败不能影响更新本身 */ }
|
|
559
|
+
};
|
|
560
|
+
/**
|
|
561
|
+
* 报阶段 —— **必须 await**: 先在盘上落下"进行中"的阶段, 再去做那件危险的事
|
|
562
|
+
* (否则进程在写状态之前被杀, 盘上就没有"上次更新中断"的证据)。
|
|
563
|
+
*/
|
|
564
|
+
const stage = async (s, detail) => {
|
|
565
|
+
try {
|
|
566
|
+
opts.onStage?.(s, detail);
|
|
567
|
+
}
|
|
568
|
+
catch { /* 回调失败不影响流程 */ }
|
|
569
|
+
await markInFlight(s, detail);
|
|
570
|
+
};
|
|
571
|
+
const plan = await buildUpdatePlan({
|
|
572
|
+
home, env: opts.env, force: true, installation: install, registry: opts.registry,
|
|
573
|
+
workloadRiskOverride: opts.workloadRiskOverride,
|
|
574
|
+
});
|
|
575
|
+
const from = plan.currentVersion;
|
|
576
|
+
const to = plan.targetVersion || plan.currentVersion;
|
|
577
|
+
const record = async (r, historyStatus) => {
|
|
578
|
+
const rec = { at: new Date().toISOString(), from: r.from, to: r.to, status: historyStatus, durationMs: r.durationMs, reason: r.reason };
|
|
579
|
+
// 记账失败**不能**把"更新其实成功了"变成向上抛异常 (真被测试 teardown 竞态抓到过:
|
|
580
|
+
// HOME 在写到一半时消失 → rename ENOENT)。失败就如实记进 reason, 结果照常返回。
|
|
581
|
+
try {
|
|
582
|
+
await (0, update_state_js_1.appendUpdateHistory)(rec, home);
|
|
583
|
+
await (0, update_state_js_1.writeUpdateState)({
|
|
584
|
+
lastUpdate: rec,
|
|
585
|
+
lastFailure: r.ok ? null : { at: rec.at, stage: r.failedAt || r.stage, reason: r.reason || '未知原因' },
|
|
586
|
+
needsRestart: r.ok ? r.needsRestart : false,
|
|
587
|
+
currentVersion: r.from,
|
|
588
|
+
}, home);
|
|
589
|
+
}
|
|
590
|
+
catch (e) {
|
|
591
|
+
const note = `状态记录写入失败: ${e?.message || e}`;
|
|
592
|
+
return { ...r, reason: r.reason ? `${r.reason}; ${note}` : note };
|
|
593
|
+
}
|
|
594
|
+
return r;
|
|
595
|
+
};
|
|
596
|
+
if (!plan.targetVersion) {
|
|
597
|
+
await stage('blocked', '没有可执行的更新');
|
|
598
|
+
return record({ stage: 'blocked', ok: false, from, to, durationMs: Date.now() - started, reason: plan.blockers[0] || '已是最新, 无需更新', needsRestart: false }, 'blocked');
|
|
599
|
+
}
|
|
600
|
+
if (plan.blockers.length > 0) {
|
|
601
|
+
await stage('blocked', plan.blockers.join('; '));
|
|
602
|
+
return record({ stage: 'blocked', ok: false, from, to, durationMs: Date.now() - started, reason: `阻塞: ${plan.blockers.join('; ')}`, needsRestart: false }, 'blocked');
|
|
603
|
+
}
|
|
604
|
+
if (opts.strategy === 'wait' && plan.advisories.length > 0) {
|
|
605
|
+
await stage('blocked', '按策略等待当前 Run 结束');
|
|
606
|
+
const reason = `等待当前 Run 结束后更新 (${plan.advisories.length} 项提醒); 待收尾后重新执行 bolloon update --now`;
|
|
607
|
+
await (0, update_state_js_1.appendUpdateHistory)({ at: new Date().toISOString(), from, to, status: 'planned', reason }, home);
|
|
608
|
+
return { stage: 'blocked', ok: false, from, to, durationMs: Date.now() - started, reason, needsRestart: false };
|
|
609
|
+
}
|
|
610
|
+
// 锁 (第二个进程不许同时更新)
|
|
611
|
+
const lock = await (0, update_state_js_1.acquireUpdateLock)({ home, reason: `${from} → ${to}` });
|
|
612
|
+
if (!lock.ok) {
|
|
613
|
+
const held = lock.heldBy;
|
|
614
|
+
await stage('blocked', `已有更新进程 (pid ${held?.pid})`);
|
|
615
|
+
return record({ stage: 'blocked', ok: false, from, to, durationMs: Date.now() - started, reason: `已有更新进程持有锁 (pid ${held?.pid}, ${held?.at})`, needsRestart: false }, 'blocked');
|
|
616
|
+
}
|
|
617
|
+
const tmpRoot = await fsp.mkdtemp(path.join(os.tmpdir(), 'bolloon-update-'));
|
|
618
|
+
const runNpm = opts.runNpm || defaultRunNpm;
|
|
619
|
+
let stagedTarball = null;
|
|
620
|
+
try {
|
|
621
|
+
// 1. 下载 tarball 到临时目录 (不动现有安装)
|
|
622
|
+
await stage('downloading', `npm pack ${version_info_js_1.PKG_NAME}@${to}`);
|
|
623
|
+
const packed = runNpm(['pack', `${version_info_js_1.PKG_NAME}@${to}`, '--pack-destination', tmpRoot, '--loglevel=error'], tmpRoot);
|
|
624
|
+
if (packed.code !== 0) {
|
|
625
|
+
throw Object.assign(new Error(`下载 ${version_info_js_1.PKG_NAME}@${to} 失败: ${(packed.stderr || packed.stdout).trim().slice(0, 400)}`), { stage: 'downloading' });
|
|
626
|
+
}
|
|
627
|
+
const tarballs = (await fsp.readdir(tmpRoot)).filter((f) => f.endsWith('.tgz'));
|
|
628
|
+
if (tarballs.length === 0)
|
|
629
|
+
throw Object.assign(new Error('npm pack 没有产出 tarball'), { stage: 'downloading' });
|
|
630
|
+
stagedTarball = path.join(tmpRoot, tarballs[0]);
|
|
631
|
+
// 2. 解压 + 校验包内容 (版本 + 入口)
|
|
632
|
+
await stage('staged', `解压并校验 ${path.basename(stagedTarball)}`);
|
|
633
|
+
const extractDir = path.join(tmpRoot, 'extract');
|
|
634
|
+
await fsp.mkdir(extractDir, { recursive: true });
|
|
635
|
+
const tar = (0, child_process_1.spawnSync)('tar', ['-xzf', stagedTarball, '-C', extractDir], { encoding: 'utf-8', timeout: 120_000 });
|
|
636
|
+
if (tar.status !== 0)
|
|
637
|
+
throw Object.assign(new Error(`解压失败: ${(tar.stderr || '').slice(0, 300)}`), { stage: 'staged' });
|
|
638
|
+
const stagedCheck = validateStagedPackage(path.join(extractDir, 'package'), to);
|
|
639
|
+
if (!stagedCheck.ok)
|
|
640
|
+
throw Object.assign(new Error(`目标包校验失败: ${stagedCheck.detail}`), { stage: 'staged' });
|
|
641
|
+
// 3. 切换 (npm 完成替换; 旧版本在替换成功前不会消失)
|
|
642
|
+
await stage('switching', `npm install -g ${version_info_js_1.PKG_NAME}@${to}`);
|
|
643
|
+
const installed = runNpm(['install', '-g', `${version_info_js_1.PKG_NAME}@${to}`, '--no-fund', '--no-audit', '--loglevel=error'], os.tmpdir());
|
|
644
|
+
if (installed.code !== 0) {
|
|
645
|
+
throw Object.assign(new Error(`npm 安装失败: ${(installed.stderr || installed.stdout).trim().slice(0, 400)}`), { stage: 'switching' });
|
|
646
|
+
}
|
|
647
|
+
// 4. 验证: 磁盘版本 + 新入口真能启动 + 健康检查
|
|
648
|
+
await stage('verifying', '核对磁盘版本并试启新入口');
|
|
649
|
+
const verify = opts.verifyInstall || defaultVerifyInstall;
|
|
650
|
+
const ok = await verify(to, home);
|
|
651
|
+
if (!ok)
|
|
652
|
+
throw Object.assign(new Error(`切换后验证失败: 新版本 ${to} 未能正确启动`), { stage: 'verifying' });
|
|
653
|
+
await stage('succeeded', `已更新到 ${to}`);
|
|
654
|
+
const out = {
|
|
655
|
+
stage: 'succeeded', ok: true, from, to, durationMs: Date.now() - started, needsRestart: true, stagedTarball,
|
|
656
|
+
};
|
|
657
|
+
await record(out, 'succeeded');
|
|
658
|
+
return out;
|
|
659
|
+
}
|
|
660
|
+
catch (e) {
|
|
661
|
+
const failureStage = e?.stage || 'failed';
|
|
662
|
+
const reason = e?.message || String(e);
|
|
663
|
+
await stage(failureStage, reason);
|
|
664
|
+
// 失败处理: 保留旧版本 → 能回滚就回滚 → 写原因 → 释放锁
|
|
665
|
+
let finalStage = 'failed';
|
|
666
|
+
let finalReason = reason;
|
|
667
|
+
try {
|
|
668
|
+
const nowVersion = installedVersionOnDisk(install.packageRoot);
|
|
669
|
+
if (install.method === 'npm-global' && nowVersion && nowVersion !== from && nowVersion !== to) {
|
|
670
|
+
await stage('rolled_back', `检测到半更新 (磁盘版本 ${nowVersion}), 回滚到 ${from}`);
|
|
671
|
+
const rb = runNpm(['install', '-g', `${version_info_js_1.PKG_NAME}@${from}`, '--no-fund', '--no-audit', '--loglevel=error'], os.tmpdir());
|
|
672
|
+
const after = installedVersionOnDisk(install.packageRoot);
|
|
673
|
+
if (rb.code === 0 && after === from) {
|
|
674
|
+
finalStage = 'rolled_back';
|
|
675
|
+
finalReason = `${reason}; 已回滚到 ${from}`;
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
finalReason = `${reason}; 回滚也未成功 (磁盘版本 ${after || 'unknown'}) — 请手动: npm install -g ${version_info_js_1.PKG_NAME}@${from}`;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
else if (nowVersion === to && failureStage === 'verifying') {
|
|
682
|
+
// 装上了但验证没过: 保留新版本但如实报失败, 并给出回滚指令
|
|
683
|
+
finalReason = `${reason}; 磁盘版本已是 ${to}, 如需回退: npm install -g ${version_info_js_1.PKG_NAME}@${from}`;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
catch (e2) {
|
|
687
|
+
finalReason = `${reason}; 回滚过程出错: ${e2?.message || e2}`;
|
|
688
|
+
}
|
|
689
|
+
const out = {
|
|
690
|
+
stage: finalStage, failedAt: failureStage, ok: false, from, to, durationMs: Date.now() - started,
|
|
691
|
+
reason: finalReason, needsRestart: false, stagedTarball,
|
|
692
|
+
};
|
|
693
|
+
await record(out, finalStage === 'rolled_back' ? 'rolled_back' : 'failed');
|
|
694
|
+
return out;
|
|
695
|
+
}
|
|
696
|
+
finally {
|
|
697
|
+
// 临时目录清理 (成功/失败都清)
|
|
698
|
+
try {
|
|
699
|
+
await fsp.rm(tmpRoot, { recursive: true, force: true });
|
|
700
|
+
}
|
|
701
|
+
catch { /* 忽略 */ }
|
|
702
|
+
await (0, update_state_js_1.releaseUpdateLock)(home);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
async function defaultVerifyInstall(target, home) {
|
|
706
|
+
const install = (0, version_info_js_1.detectInstallation)({ home });
|
|
707
|
+
const onDisk = installedVersionOnDisk(install.packageRoot);
|
|
708
|
+
if (onDisk !== target)
|
|
709
|
+
return false;
|
|
710
|
+
const entry = path.join(install.packageRoot, 'dist', 'cli-entry.js');
|
|
711
|
+
if (!fs.existsSync(entry))
|
|
712
|
+
return false;
|
|
713
|
+
const r = (0, child_process_1.spawnSync)(process.execPath, [entry, '--version', '--json'], { encoding: 'utf-8', timeout: 120_000, maxBuffer: 8 * 1024 * 1024 });
|
|
714
|
+
if (r.status !== 0)
|
|
715
|
+
return false;
|
|
716
|
+
const parsed = parseJsonFromStdout(String(r.stdout || ''));
|
|
717
|
+
return parsed?.packageVersion === target;
|
|
718
|
+
}
|
|
719
|
+
async function readUpdateStatus(opts = {}) {
|
|
720
|
+
const home = opts.home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
721
|
+
const st = await (0, update_state_js_1.readUpdateState)(home);
|
|
722
|
+
const prefs = await (0, update_state_js_1.readUpdatePrefs)({ home, env: opts.env });
|
|
723
|
+
const lock = (0, update_state_js_1.readUpdateLock)(home);
|
|
724
|
+
const install = (0, version_info_js_1.detectInstallation)({ home });
|
|
725
|
+
const pkg = (0, version_info_js_1.readPackageAt)(install.packageRoot);
|
|
726
|
+
return {
|
|
727
|
+
currentVersion: isKnownVersion(pkg?.version) ? String(pkg?.version) : st.currentVersion,
|
|
728
|
+
latestVersion: st.latestVersion,
|
|
729
|
+
channel: prefs.channel,
|
|
730
|
+
installMethod: install.method,
|
|
731
|
+
installDir: install.installDir,
|
|
732
|
+
entryPath: install.entryPath,
|
|
733
|
+
lastCheckAt: st.lastCheckAt,
|
|
734
|
+
lastCheckStatus: st.lastCheckStatus,
|
|
735
|
+
lastCheckReason: st.lastCheckReason,
|
|
736
|
+
lastUpdate: st.lastUpdate,
|
|
737
|
+
lastFailure: st.lastFailure,
|
|
738
|
+
needsRestart: st.needsRestart,
|
|
739
|
+
prefs,
|
|
740
|
+
lock: lock ? { ...lock, stale: (0, update_state_js_1.lockIsStale)(lock) } : null,
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
async function readHistory(limit = 10, home) {
|
|
744
|
+
const h = home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
745
|
+
return (0, update_state_js_1.readUpdateHistory)(limit, h);
|
|
746
|
+
}
|
|
747
|
+
function renderHistory(records) {
|
|
748
|
+
if (records.length === 0)
|
|
749
|
+
return '没有更新历史记录。';
|
|
750
|
+
const L = ['时间 · 当前版本 → 目标版本 · 结果 · 耗时 · 原因'];
|
|
751
|
+
for (const r of records) {
|
|
752
|
+
const ms = r.durationMs != null ? `${(r.durationMs / 1000).toFixed(1)}s` : '-';
|
|
753
|
+
L.push(`${r.at} · ${r.from} → ${r.to} · ${r.status} · ${ms}${r.reason ? ` · ${r.reason}` : ''}`);
|
|
754
|
+
}
|
|
755
|
+
return L.join('\n');
|
|
756
|
+
}
|
|
757
|
+
/** 启动后台检查用的摘要 (供 --version 显示)。 */
|
|
758
|
+
async function updateSummaryFor(home) {
|
|
759
|
+
const h = home ?? (await Promise.resolve().then(() => __importStar(require('../setup/setup-store.js')))).resolveBolloonHome();
|
|
760
|
+
const st = await (0, update_state_js_1.readUpdateState)(h);
|
|
761
|
+
return {
|
|
762
|
+
lastCheckAt: st.lastCheckAt,
|
|
763
|
+
lastCheckStatus: st.lastCheckStatus,
|
|
764
|
+
lastCheckReason: st.lastCheckReason,
|
|
765
|
+
latestVersion: st.latestVersion,
|
|
766
|
+
lastUpdate: st.lastUpdate ? { at: st.lastUpdate.at, from: st.lastUpdate.from, to: st.lastUpdate.to, status: st.lastUpdate.status, reason: st.lastUpdate.reason } : null,
|
|
767
|
+
needsRestart: st.needsRestart,
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
//# sourceMappingURL=update-manager.js.map
|