@bolloon/bolloon-agent 0.1.35 → 0.1.37
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/README.md +1 -1
- package/dist/agents/p2p-chat-tools.js +6 -6
- package/dist/agents/permission-mode.js +115 -0
- package/dist/agents/pi-sdk.js +435 -25
- package/dist/agents/pre-tool-validator.js +194 -0
- package/dist/agents/workflow-pivot-loop.js +113 -12
- package/dist/bollharness-integration/context-router.js +2 -2
- package/dist/bollharness-integration/guard-checker.js +1 -1
- package/dist/bootstrap/bootstrap.js +3 -0
- package/dist/bootstrap/context-collector.js +17 -1
- package/dist/bootstrap/context-hierarchy.js +218 -0
- package/dist/bootstrap/lifecycle-hooks.js +86 -24
- package/dist/bootstrap/project-context.js +10 -3
- package/dist/context-compaction/auto-compact.js +144 -0
- package/dist/context-compaction/budget-gate.js +28 -0
- package/dist/context-compaction/budget-reduce.js +35 -0
- package/dist/context-compaction/context-collapse.js +66 -0
- package/dist/context-compaction/index.js +21 -0
- package/dist/context-compaction/microcompact.js +51 -0
- package/dist/context-compaction/pipeline.js +123 -0
- package/dist/context-compaction/snip.js +45 -0
- package/dist/context-compaction/token-estimator.js +35 -0
- package/dist/context-compaction/types.js +19 -0
- package/dist/heartbeat/HealthMonitor.js +3 -2
- package/dist/index.js +38 -2
- package/dist/llm/llm-judgment-client.js +32 -30
- package/dist/llm/pi-ai.js +103 -16
- package/dist/llm/system-prompt/health.js +129 -0
- package/dist/llm/system-prompt/registry.js +246 -0
- package/dist/llm/system-prompt/strip-hibsml.js +51 -0
- package/dist/llm/tool-manifest/ask_user_input.js +35 -0
- package/dist/llm/tool-manifest/bash.js +23 -0
- package/dist/llm/tool-manifest/create_file.js +24 -0
- package/dist/llm/tool-manifest/fetch_sports_data.js +26 -0
- package/dist/llm/tool-manifest/image_search.js +24 -0
- package/dist/llm/tool-manifest/index.js +69 -0
- package/dist/llm/tool-manifest/mcp.js +43 -0
- package/dist/llm/tool-manifest/message_compose.js +31 -0
- package/dist/llm/tool-manifest/places.js +83 -0
- package/dist/llm/tool-manifest/present_files.js +21 -0
- package/dist/llm/tool-manifest/recipe.js +40 -0
- package/dist/llm/tool-manifest/recommend_apps.js +23 -0
- package/dist/llm/tool-manifest/str_replace.js +27 -0
- package/dist/llm/tool-manifest/types.js +7 -0
- package/dist/llm/tool-manifest/view.js +24 -0
- package/dist/llm/tool-manifest/weather.js +27 -0
- package/dist/llm/tool-manifest/web.js +51 -0
- package/dist/network/p2p-direct.js +23 -0
- package/dist/network/source-intent-broadcaster.js +203 -0
- package/dist/network/source-intent.js +100 -0
- package/dist/pi-ecosystem-judgment/adaptive-scan.js +48 -0
- package/dist/pi-ecosystem-judgment/injection-gate.js +54 -12
- package/dist/pi-ecosystem-judgment/value-injection.js +8 -2
- package/dist/security/context-router-tool.js +1 -1
- package/dist/security/input-scanner.js +223 -0
- package/dist/web/client.js +3089 -4458
- package/dist/web/index.html +58 -67
- package/dist/web/server.js +299 -117
- package/dist/web/style.css +531 -249
- package/dist/web/ui/message-renderer.js +352 -0
- package/dist/web/ui/step-timeline.js +279 -0
- package/package.json +2 -2
- package/.auto-evolve-calls +0 -1
- package/.last-auto-evolve-baseline +0 -1
- package/Bolloon.md +0 -103
- package/dist/agents/constraint-layer.js.map +0 -1
- package/dist/agents/pi-sdk.js.map +0 -1
- package/dist/agents/workflow-engine.js.map +0 -1
- package/dist/bollharness/src/index.js +0 -5
- package/dist/bollharness/src/scripts/checks/check_adr_plan_numbering.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_api_types.js +0 -45
- package/dist/bollharness/src/scripts/checks/check_artifact_link.js +0 -146
- package/dist/bollharness/src/scripts/checks/check_bridge_deps.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_bugfix_binding.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_bugfix_binding_ci.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_doc_file_references.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +0 -135
- package/dist/bollharness/src/scripts/checks/check_doc_links.js +0 -31
- package/dist/bollharness/src/scripts/checks/check_file_existence_claims.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_fragment_integrity.js +0 -34
- package/dist/bollharness/src/scripts/checks/check_hook_installed.js +0 -63
- package/dist/bollharness/src/scripts/checks/check_issue_closure.js +0 -41
- package/dist/bollharness/src/scripts/checks/check_mcp_parity.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_security.js +0 -48
- package/dist/bollharness/src/scripts/checks/check_skill_parity.js +0 -6
- package/dist/bollharness/src/scripts/checks/check_versions.js +0 -6
- package/dist/bollharness/src/scripts/checks/finding.js +0 -13
- package/dist/bollharness/src/scripts/checks/next_decision_number.js +0 -20
- package/dist/bollharness/src/scripts/checks/regenerate_magic_docs.js +0 -6
- package/dist/bollharness/src/scripts/ci/detect_rebaseline_triggers.js +0 -8
- package/dist/bollharness/src/scripts/ci/scan_subprocess_cfg.js +0 -8
- package/dist/bollharness/src/scripts/ci/scan_verify_artifacts.js +0 -8
- package/dist/bollharness/src/scripts/ci/scan_yaml_schema.js +0 -8
- package/dist/bollharness/src/scripts/context_router.js +0 -67
- package/dist/bollharness/src/scripts/deploy-guard.js +0 -157
- package/dist/bollharness/src/scripts/guard-feedback.js +0 -192
- package/dist/bollharness/src/scripts/guard_router.js +0 -158
- package/dist/bollharness/src/scripts/hooks/_hook_output.js +0 -6
- package/dist/bollharness/src/scripts/hooks/auto-python3.js +0 -6
- package/dist/bollharness/src/scripts/hooks/deploy-progress-on-session-end.js +0 -6
- package/dist/bollharness/src/scripts/hooks/failure-analyzer.js +0 -6
- package/dist/bollharness/src/scripts/hooks/gate-judgment-inject.js +0 -92
- package/dist/bollharness/src/scripts/hooks/gate-transition-judgment.js +0 -63
- package/dist/bollharness/src/scripts/hooks/inbox-ack.js +0 -6
- package/dist/bollharness/src/scripts/hooks/inbox-inject-on-start.js +0 -6
- package/dist/bollharness/src/scripts/hooks/inbox-validate.js +0 -6
- package/dist/bollharness/src/scripts/hooks/inbox-write-ledger.js +0 -6
- package/dist/bollharness/src/scripts/hooks/initializer-agent.js +0 -6
- package/dist/bollharness/src/scripts/hooks/loop-detection.js +0 -73
- package/dist/bollharness/src/scripts/hooks/owner-guard.js +0 -6
- package/dist/bollharness/src/scripts/hooks/precompact.js +0 -6
- package/dist/bollharness/src/scripts/hooks/review-agent-gatekeeper.js +0 -6
- package/dist/bollharness/src/scripts/hooks/risk-tracker.js +0 -108
- package/dist/bollharness/src/scripts/hooks/sanitize-on-read.js +0 -6
- package/dist/bollharness/src/scripts/hooks/session-reflection.js +0 -7
- package/dist/bollharness/src/scripts/hooks/session-start-magic-docs.js +0 -7
- package/dist/bollharness/src/scripts/hooks/session-start-reset-risk.js +0 -7
- package/dist/bollharness/src/scripts/hooks/session-start-toolkit-reminder.js +0 -7
- package/dist/bollharness/src/scripts/hooks/stop-evaluator.js +0 -157
- package/dist/bollharness/src/scripts/hooks/tool-call-counter.js +0 -6
- package/dist/bollharness/src/scripts/hooks/trace-analyzer.js +0 -10
- package/dist/bollharness/src/scripts/install/install-trust-token.js +0 -7
- package/dist/bollharness/src/scripts/install/multi_project_registry.js +0 -9
- package/dist/bollharness/src/scripts/install/phase2_auto.js +0 -21
- package/dist/bollharness/src/scripts/install/pre_commit_installer.js +0 -6
- package/dist/bollharness/src/scripts/install/tier_selector.js +0 -7
- package/dist/bollharness/src/scripts/install/transcript_miner.js +0 -7
- package/dist/bollharness/src/scripts/lib/claim_patterns.js +0 -10
- package/dist/bollharness/src/scripts/lib/sanitize_patterns.js +0 -12
- package/dist/bollharness/src/scripts/sanitize.js +0 -6
- package/dist/bollharness-integration/context-router-judgment.js.map +0 -1
- package/dist/bollharness-integration/context-router.js.map +0 -1
- package/dist/bollharness-integration/gate-state-machine.js.map +0 -1
- package/dist/bollharness-integration/gate-transition-hooks.js.map +0 -1
- package/dist/bollharness-integration/guard-checker.js.map +0 -1
- package/dist/bollharness-integration/index.js.map +0 -1
- package/dist/bollharness-integration/integration.js.map +0 -1
- package/dist/bollharness-integration/llm/pi-ai.d.ts +0 -60
- package/dist/bollharness-integration/pi-ecosystem-colony/index.d.ts +0 -153
- package/dist/bollharness-integration/pi-ecosystem-goals/index.d.ts +0 -136
- package/dist/bollharness-integration/pi-ecosystem-judgment/decision.d.ts +0 -117
- package/dist/bollharness-integration/pi-ecosystem-judgment/distillation.d.ts +0 -78
- package/dist/bollharness-integration/pi-ecosystem-judgment/index.d.ts +0 -139
- package/dist/bollharness-integration/pi-ecosystem-mcp/index.d.ts +0 -127
- package/dist/bollharness-integration/pi-ecosystem-subagents/index.d.ts +0 -95
- package/dist/bollharness-integration/skill-adapter.js.map +0 -1
- package/dist/constraint-runtime/src/_archive_helper.js +0 -9
- package/dist/constraint-runtime/src/agent/coordinator.js +0 -48
- package/dist/constraint-runtime/src/agent/index.js +0 -1
- package/dist/constraint-runtime/src/assistant/index.js +0 -12
- package/dist/constraint-runtime/src/bootstrap/index.js +0 -12
- package/dist/constraint-runtime/src/bootstrap_graph.js +0 -13
- package/dist/constraint-runtime/src/bridge/index.js +0 -12
- package/dist/constraint-runtime/src/buddy/index.js +0 -12
- package/dist/constraint-runtime/src/cli/index.js +0 -12
- package/dist/constraint-runtime/src/command_graph.js +0 -10
- package/dist/constraint-runtime/src/commands.js +0 -60
- package/dist/constraint-runtime/src/components/index.js +0 -12
- package/dist/constraint-runtime/src/constants/index.js +0 -12
- package/dist/constraint-runtime/src/constraint/budget.js +0 -22
- package/dist/constraint-runtime/src/constraint/budget.js.map +0 -1
- package/dist/constraint-runtime/src/constraint/index.js +0 -2
- package/dist/constraint-runtime/src/constraint/permission.js +0 -20
- package/dist/constraint-runtime/src/constraint/permission.js.map +0 -1
- package/dist/constraint-runtime/src/context.js +0 -30
- package/dist/constraint-runtime/src/coordinator/index.js +0 -12
- package/dist/constraint-runtime/src/cost_hook.js +0 -4
- package/dist/constraint-runtime/src/cost_tracker.js +0 -8
- package/dist/constraint-runtime/src/deferred_init.js +0 -10
- package/dist/constraint-runtime/src/direct_modes.js +0 -6
- package/dist/constraint-runtime/src/dynamic-tool-loader.js +0 -85
- package/dist/constraint-runtime/src/entrypoints/index.js +0 -12
- package/dist/constraint-runtime/src/execution_registry.js +0 -44
- package/dist/constraint-runtime/src/history.js +0 -9
- package/dist/constraint-runtime/src/hooks/index.js +0 -12
- package/dist/constraint-runtime/src/index.js +0 -26
- package/dist/constraint-runtime/src/ink.js +0 -4
- package/dist/constraint-runtime/src/keybindings/index.js +0 -12
- package/dist/constraint-runtime/src/memdir/index.js +0 -12
- package/dist/constraint-runtime/src/migrations/index.js +0 -12
- package/dist/constraint-runtime/src/models.js +0 -1
- package/dist/constraint-runtime/src/models.js.map +0 -1
- package/dist/constraint-runtime/src/moreright/index.js +0 -12
- package/dist/constraint-runtime/src/native_ts/index.js +0 -12
- package/dist/constraint-runtime/src/output_styles/index.js +0 -12
- package/dist/constraint-runtime/src/parity_audit.js +0 -12
- package/dist/constraint-runtime/src/plugins/index.js +0 -12
- package/dist/constraint-runtime/src/port_manifest.js +0 -11
- package/dist/constraint-runtime/src/prefetch.js +0 -9
- package/dist/constraint-runtime/src/query.js +0 -1
- package/dist/constraint-runtime/src/remote/index.js +0 -12
- package/dist/constraint-runtime/src/remote_runtime.js +0 -9
- package/dist/constraint-runtime/src/runtime/index.js +0 -1
- package/dist/constraint-runtime/src/runtime/session.js +0 -35
- package/dist/constraint-runtime/src/schemas/index.js +0 -12
- package/dist/constraint-runtime/src/screens/index.js +0 -12
- package/dist/constraint-runtime/src/server/index.js +0 -12
- package/dist/constraint-runtime/src/services/index.js +0 -12
- package/dist/constraint-runtime/src/session_store.js +0 -22
- package/dist/constraint-runtime/src/setup.js +0 -30
- package/dist/constraint-runtime/src/skills/index.js +0 -1
- package/dist/constraint-runtime/src/skills/skill-registry.js +0 -28
- package/dist/constraint-runtime/src/state/index.js +0 -12
- package/dist/constraint-runtime/src/system_init.js +0 -20
- package/dist/constraint-runtime/src/thinking/engine.js +0 -42
- package/dist/constraint-runtime/src/thinking/index.js +0 -1
- package/dist/constraint-runtime/src/tool_pool.js +0 -8
- package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +0 -7
- package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +0 -7
- package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +0 -7
- package/dist/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +0 -6
- package/dist/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +0 -6
- package/dist/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +0 -5
- package/dist/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +0 -6
- package/dist/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +0 -4
- package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +0 -8
- package/dist/constraint-runtime/src/tools/SafeSDK/deploySafe.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools/WalletTools/autoPay.js +0 -29
- package/dist/constraint-runtime/src/tools/WalletTools/createWallet.js +0 -10
- package/dist/constraint-runtime/src/tools/WalletTools/getBalance.js +0 -13
- package/dist/constraint-runtime/src/tools/WalletTools/importWallet.js +0 -22
- package/dist/constraint-runtime/src/tools/WalletTools/sendTransaction.js +0 -25
- package/dist/constraint-runtime/src/tools/WalletTools/signMessage.js +0 -10
- package/dist/constraint-runtime/src/tools/WalletTools/transferToken.js +0 -25
- package/dist/constraint-runtime/src/tools.js +0 -80
- package/dist/constraint-runtime/src/transcript.js +0 -19
- package/dist/constraint-runtime/src/types/index.js +0 -12
- package/dist/constraint-runtime/src/upstream_proxy/index.js +0 -12
- package/dist/constraint-runtime/src/utils/index.js +0 -12
- package/dist/constraint-runtime/src/vim/index.js +0 -12
- package/dist/constraint-runtime/src/voice/index.js +0 -12
- package/dist/constraints/index.js.map +0 -1
- package/dist/documents/reader.js.map +0 -1
- package/dist/llm/config-store.js.map +0 -1
- package/dist/llm/pi-ai.js.map +0 -1
- package/dist/network/agent-network.js.map +0 -1
- package/dist/network/iroh-integration.js.map +0 -1
- package/dist/network/iroh-transport.js.map +0 -1
- package/dist/network/p2p.js.map +0 -1
- package/dist/network/storage/adapters/json-adapter.js.map +0 -1
- package/dist/pi-ecosystem-colony/index.js.map +0 -1
- package/dist/pi-ecosystem-goals/index.js.map +0 -1
- package/dist/pi-ecosystem-judgment/decision.js.map +0 -1
- package/dist/pi-ecosystem-judgment/distillation.js.map +0 -1
- package/dist/pi-ecosystem-judgment/human-value-store.js.map +0 -1
- package/dist/pi-ecosystem-judgment/index.js.map +0 -1
- package/dist/pi-ecosystem-judgment/value-injection.js.map +0 -1
- package/dist/pi-ecosystem-mcp/index.js.map +0 -1
- package/dist/pi-ecosystem-subagents/index.js.map +0 -1
- package/dist/social/ant-colony/AdaptiveHeartbeat.js.map +0 -1
- package/dist/social/ant-colony/PheromoneEngine.js.map +0 -1
- package/dist/social/ant-colony/types.js.map +0 -1
- package/dist/social/channels/ChannelManager.js.map +0 -1
- package/dist/social/channels/DiapChannelBridge.js.map +0 -1
- package/dist/social/channels/InterestMatcher.js.map +0 -1
- package/dist/social/channels/types.js.map +0 -1
- package/dist/social/global-shared-context.js.map +0 -1
- package/dist/social/heartbeat.js.map +0 -1
- package/lefthook.yml +0 -29
- package/scripts/auto-evolve-loop.ts +0 -376
- package/scripts/auto-evolve-oneshot.sh +0 -155
- package/scripts/auto-evolve-snapshot.sh +0 -136
- package/scripts/build-cli.js +0 -216
- package/scripts/build-web.ts +0 -82
- package/scripts/detect-schema-changes.sh +0 -48
- package/scripts/diff-reviewer.ts +0 -159
- package/scripts/postinstall.js +0 -153
- package/scripts/weekly-report.ts +0 -364
- package/src/agents/agent-manifest-protocol.ts +0 -117
- package/src/agents/constraint-layer.ts +0 -309
- package/src/agents/iroh-secret.ts +0 -32
- package/src/agents/p2p-chat-tools.ts +0 -383
- package/src/agents/p2p-document-tools.ts +0 -347
- package/src/agents/pi-sdk.ts +0 -2462
- package/src/agents/protocol.ts +0 -398
- package/src/agents/shell-guard.ts +0 -417
- package/src/agents/shell-tool.ts +0 -103
- package/src/agents/skill-loader.ts +0 -202
- package/src/agents/subagent-manager.ts +0 -553
- package/src/agents/workflow-engine.ts +0 -332
- package/src/agents/workflow-pivot-loop.ts +0 -675
- package/src/bollharness/.sanitize-report.json +0 -13
- package/src/bollharness/CLAUDE.md +0 -73
- package/src/bollharness/LICENSE +0 -21
- package/src/bollharness/README.md +0 -143
- package/src/bollharness/README.zh-CN.md +0 -131
- package/src/bollharness/package.json +0 -20
- package/src/bollharness/reference/SOURCE-COMMIT.txt +0 -3
- package/src/bollharness/reference/boll-reference/scripts/hooks/.sanitize-report.json +0 -12
- package/src/bollharness/reference/boll-reference/scripts/hooks/find-boll-root.sh +0 -27
- package/src/bollharness/reference/boll-reference/scripts/hooks/precompact.sh +0 -57
- package/src/bollharness/reference/boll-reference/scripts/hooks/stop-evaluator.md +0 -57
- package/src/bollharness/schemas/metrics-jsonl-allowlist.json +0 -67
- package/src/bollharness/scripts/checks/next_decision_number.sh +0 -48
- package/src/bollharness/scripts/ci/count-components.sh +0 -65
- package/src/bollharness/scripts/context-fragments/artifact-linkage.md +0 -14
- package/src/bollharness/scripts/context-fragments/auth-consumers.md +0 -17
- package/src/bollharness/scripts/context-fragments/bridge-constitution.md +0 -13
- package/src/bollharness/scripts/context-fragments/catalyst-distributed.md +0 -18
- package/src/bollharness/scripts/context-fragments/closure-checklist.md +0 -13
- package/src/bollharness/scripts/context-fragments/contract-consumers.md +0 -15
- package/src/bollharness/scripts/context-fragments/db-shared-structures.md +0 -15
- package/src/bollharness/scripts/context-fragments/fixed-three-layers.md +0 -19
- package/src/bollharness/scripts/context-fragments/general-dev-principles.md +0 -11
- package/src/bollharness/scripts/context-fragments/issue-first.md +0 -8
- package/src/bollharness/scripts/context-fragments/mcp-parity.md +0 -16
- package/src/bollharness/scripts/context-fragments/pi-agent-operations.md +0 -108
- package/src/bollharness/scripts/context-fragments/protocol-consumers.md +0 -15
- package/src/bollharness/scripts/context-fragments/run-events-consumers.md +0 -15
- package/src/bollharness/scripts/context-fragments/scene-fidelity.md +0 -13
- package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +0 -15
- package/src/bollharness/scripts/context-fragments/two-language.md +0 -15
- package/src/bollharness/scripts/context-fragments/version-sources.md +0 -14
- package/src/bollharness/scripts/hooks/find-project-root.sh +0 -47
- package/src/bollharness/scripts/hooks/inbox-poll.sh +0 -78
- package/src/bollharness/scripts/hooks/precompact.sh +0 -56
- package/src/bollharness/scripts/hooks/stop-evaluator.md +0 -83
- package/src/bollharness/scripts/sync-from-upstream.sh +0 -281
- package/src/bollharness/src/index.ts +0 -5
- package/src/bollharness/src/scripts/checks/check_adr_plan_numbering.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_api_types.ts +0 -52
- package/src/bollharness/src/scripts/checks/check_artifact_link.ts +0 -156
- package/src/bollharness/src/scripts/checks/check_bridge_deps.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_bugfix_binding.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_bugfix_binding_ci.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_doc_file_references.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_doc_freshness.ts +0 -141
- package/src/bollharness/src/scripts/checks/check_doc_links.ts +0 -36
- package/src/bollharness/src/scripts/checks/check_file_existence_claims.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_fragment_integrity.ts +0 -40
- package/src/bollharness/src/scripts/checks/check_hook_installed.ts +0 -70
- package/src/bollharness/src/scripts/checks/check_issue_closure.ts +0 -51
- package/src/bollharness/src/scripts/checks/check_mcp_parity.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_security.ts +0 -54
- package/src/bollharness/src/scripts/checks/check_skill_parity.ts +0 -11
- package/src/bollharness/src/scripts/checks/check_versions.ts +0 -11
- package/src/bollharness/src/scripts/checks/finding.ts +0 -35
- package/src/bollharness/src/scripts/checks/next_decision_number.ts +0 -24
- package/src/bollharness/src/scripts/checks/regenerate_magic_docs.ts +0 -11
- package/src/bollharness/src/scripts/ci/detect_rebaseline_triggers.ts +0 -14
- package/src/bollharness/src/scripts/ci/scan_subprocess_cfg.ts +0 -14
- package/src/bollharness/src/scripts/ci/scan_verify_artifacts.ts +0 -14
- package/src/bollharness/src/scripts/ci/scan_yaml_schema.ts +0 -14
- package/src/bollharness/src/scripts/context_router.ts +0 -76
- package/src/bollharness/src/scripts/deploy-guard.ts +0 -182
- package/src/bollharness/src/scripts/guard-feedback.ts +0 -215
- package/src/bollharness/src/scripts/guard_router.ts +0 -194
- package/src/bollharness/src/scripts/hooks/_hook_output.js +0 -3
- package/src/bollharness/src/scripts/hooks/_hook_output.ts +0 -11
- package/src/bollharness/src/scripts/hooks/auto-python3.ts +0 -10
- package/src/bollharness/src/scripts/hooks/deploy-progress-on-session-end.ts +0 -10
- package/src/bollharness/src/scripts/hooks/failure-analyzer.ts +0 -10
- package/src/bollharness/src/scripts/hooks/gate-judgment-inject.ts +0 -111
- package/src/bollharness/src/scripts/hooks/gate-transition-judgment.ts +0 -74
- package/src/bollharness/src/scripts/hooks/inbox-ack.ts +0 -10
- package/src/bollharness/src/scripts/hooks/inbox-inject-on-start.ts +0 -10
- package/src/bollharness/src/scripts/hooks/inbox-validate.ts +0 -10
- package/src/bollharness/src/scripts/hooks/inbox-write-ledger.ts +0 -10
- package/src/bollharness/src/scripts/hooks/initializer-agent.ts +0 -10
- package/src/bollharness/src/scripts/hooks/loop-detection.ts +0 -83
- package/src/bollharness/src/scripts/hooks/owner-guard.ts +0 -10
- package/src/bollharness/src/scripts/hooks/precompact.ts +0 -10
- package/src/bollharness/src/scripts/hooks/review-agent-gatekeeper.ts +0 -10
- package/src/bollharness/src/scripts/hooks/risk-tracker.ts +0 -121
- package/src/bollharness/src/scripts/hooks/sanitize-on-read.ts +0 -10
- package/src/bollharness/src/scripts/hooks/session-reflection.ts +0 -12
- package/src/bollharness/src/scripts/hooks/session-start-magic-docs.ts +0 -12
- package/src/bollharness/src/scripts/hooks/session-start-reset-risk.ts +0 -12
- package/src/bollharness/src/scripts/hooks/session-start-toolkit-reminder.ts +0 -12
- package/src/bollharness/src/scripts/hooks/stop-evaluator.ts +0 -164
- package/src/bollharness/src/scripts/hooks/tool-call-counter.ts +0 -10
- package/src/bollharness/src/scripts/hooks/trace-analyzer.ts +0 -14
- package/src/bollharness/src/scripts/install/install-trust-token.ts +0 -13
- package/src/bollharness/src/scripts/install/multi_project_registry.ts +0 -13
- package/src/bollharness/src/scripts/install/phase2_auto.ts +0 -28
- package/src/bollharness/src/scripts/install/pre_commit_installer.ts +0 -10
- package/src/bollharness/src/scripts/install/tier_selector.ts +0 -10
- package/src/bollharness/src/scripts/install/transcript_miner.ts +0 -13
- package/src/bollharness/src/scripts/lib/claim_patterns.ts +0 -11
- package/src/bollharness/src/scripts/lib/sanitize_patterns.ts +0 -13
- package/src/bollharness/src/scripts/sanitize.ts +0 -9
- package/src/bollharness/templates/persona/default.json +0 -19
- package/src/bollharness/templates/scaffold/.gitignore.append +0 -16
- package/src/bollharness/templates/scaffold/CLAUDE.md +0 -89
- package/src/bollharness-integration/channel-judgment-engine.ts +0 -634
- package/src/bollharness-integration/context-chain-router.ts +0 -474
- package/src/bollharness-integration/context-router-judgment.ts +0 -339
- package/src/bollharness-integration/context-router.ts +0 -583
- package/src/bollharness-integration/gate-state-machine.ts +0 -444
- package/src/bollharness-integration/gate-transition-hooks.ts +0 -137
- package/src/bollharness-integration/guard-checker.ts +0 -451
- package/src/bollharness-integration/index.ts +0 -195
- package/src/bollharness-integration/integration.ts +0 -538
- package/src/bollharness-integration/judgment-prompts.yaml +0 -535
- package/src/bollharness-integration/llm-judgment-engine.ts +0 -712
- package/src/bollharness-integration/skill-adapter.ts +0 -646
- package/src/bootstrap/bootstrap.ts +0 -132
- package/src/bootstrap/context-collector.ts +0 -342
- package/src/bootstrap/lifecycle-hooks.ts +0 -176
- package/src/bootstrap/project-context.ts +0 -163
- package/src/cli/interface.ts +0 -211
- package/src/cli-entry.ts +0 -304
- package/src/constraints/index.ts +0 -6
- package/src/documents/reader.ts +0 -85
- package/src/documents/store.ts +0 -252
- package/src/electron-preload.ts +0 -25
- package/src/electron.ts +0 -200
- package/src/heartbeat/DaemonManager.ts +0 -283
- package/src/heartbeat/HealthMonitor.ts +0 -316
- package/src/heartbeat/StartupVerifier.ts +0 -223
- package/src/heartbeat/Watchdog.ts +0 -208
- package/src/heartbeat/index.ts +0 -109
- package/src/heartbeat/self-improve-bus.ts +0 -110
- package/src/heartbeat/types.ts +0 -82
- package/src/index.ts +0 -1690
- package/src/llm/audio-config-store.ts +0 -246
- package/src/llm/config-store.ts +0 -400
- package/src/llm/llm-judgment-client.ts +0 -470
- package/src/llm/pi-ai.ts +0 -558
- package/src/llm/video-config-store.ts +0 -257
- package/src/network/agent-network.ts +0 -800
- package/src/network/hybrid-messenger.ts +0 -199
- package/src/network/iroh-bootstrap.ts +0 -57
- package/src/network/iroh-discovery.ts +0 -208
- package/src/network/iroh-integration.ts +0 -158
- package/src/network/iroh-transport.ts +0 -637
- package/src/network/known-peers.ts +0 -102
- package/src/network/p2p-direct.ts +0 -240
- package/src/network/p2p-secret.ts +0 -153
- package/src/network/p2p.ts +0 -964
- package/src/network/storage/adapters/json-adapter.ts +0 -454
- package/src/network/storage/index.ts +0 -203
- package/src/network/storage/types.ts +0 -166
- package/src/security/builtin-guards.ts +0 -162
- package/src/security/context-router-tool.ts +0 -122
- package/src/security/react-harness.ts +0 -177
- package/src/security/tool-gate.ts +0 -294
- package/src/social/ant-colony/index.js +0 -19
- package/src/social/channels/ChannelManager.ts +0 -485
- package/src/social/channels/DiapChannelBridge.ts +0 -501
- package/src/social/channels/InterestMatcher.ts +0 -189
- package/src/social/channels/agent-workflow-config.json +0 -214
- package/src/social/channels/agent-workflow-config.yaml +0 -334
- package/src/social/channels/channel-agent-session.ts +0 -407
- package/src/social/channels/channel-heartbeat-agent.ts +0 -622
- package/src/social/channels/diap-doc-parser.ts +0 -282
- package/src/social/channels/harness-workflow-integrator.ts +0 -594
- package/src/social/channels/index.ts +0 -22
- package/src/social/channels/types.ts +0 -115
- package/src/social/global-shared-context.ts +0 -506
- package/src/social/heartbeat.ts +0 -1057
- package/src/social/persona/enhanced-persona.ts +0 -359
- package/src/types.d.ts +0 -12
- package/src/utils/auto-evolve-policy.ts +0 -138
- package/src/utils/auto-update.ts +0 -482
- package/src/utils/clamp.ts +0 -5
- package/src/web/agent-delegate-server.ts +0 -148
- package/src/web/api-config.html +0 -520
- package/src/web/client.js +0 -4898
- package/src/web/components/p2p/P2PModal.tsx +0 -416
- package/src/web/components/p2p/index.ts +0 -566
- package/src/web/components/p2p/index.tsx +0 -297
- package/src/web/components/p2p/p2p-connection.ts +0 -338
- package/src/web/components/p2p/p2p-identity.ts +0 -92
- package/src/web/components/p2p/p2p-manager.ts +0 -147
- package/src/web/components/p2p/p2p-messages.ts +0 -219
- package/src/web/components/p2p/p2p-modal.ts +0 -685
- package/src/web/components/p2p/p2p-store-memory.ts +0 -162
- package/src/web/components/p2p/p2p-tools.ts +0 -315
- package/src/web/components/p2p/types.ts +0 -170
- package/src/web/components/wallet-viem.mjs +0 -118
- package/src/web/design.md +0 -99
- package/src/web/icons/apple-touch-icon.png +0 -0
- package/src/web/icons/favicon-16x16.png +0 -0
- package/src/web/icons/favicon-192x192.png +0 -0
- package/src/web/icons/favicon-32x32.png +0 -0
- package/src/web/icons/favicon-48x48.png +0 -0
- package/src/web/icons/favicon-512x512.png +0 -0
- package/src/web/icons/favicon.icns +0 -0
- package/src/web/icons/favicon.ico +0 -0
- package/src/web/icons/icon.png +0 -0
- package/src/web/icons/image.png +0 -0
- package/src/web/index.html +0 -382
- package/src/web/iroh-delegate-transport.ts +0 -139
- package/src/web/manifest.json +0 -21
- package/src/web/server.ts +0 -5571
- package/src/web/style.css +0 -4455
- package/staging/auto-evolve/clean-001/.review-verdict +0 -9
- package/staging/auto-evolve/clean-001/clean-001.patch +0 -14
- package/staging/auto-evolve/e2e-001/.patch-id +0 -1
- package/staging/auto-evolve/e2e-001/.review-verdict +0 -12
- package/staging/auto-evolve/e2e-001/e2e-001.patch +0 -11
- package/staging/auto-evolve/test-bad/.review-verdict +0 -12
- package/staging/auto-evolve/test-bad/test-bad.patch +0 -11
- package/tsconfig.cli.json +0 -16
- package/tsconfig.electron.json +0 -20
- package/tsconfig.json +0 -18
package/dist/agents/pi-sdk.js
CHANGED
|
@@ -27,6 +27,8 @@ import { injectJudgmentGate, recordJudgmentUsage } from '../pi-ecosystem-judgmen
|
|
|
27
27
|
import { monitorAfterReply } from '../pi-ecosystem-judgment/monitor-gate.js';
|
|
28
28
|
// Bootstrap 生命周期 hook (SessionStart / Stop / PreToolUse)
|
|
29
29
|
import { onSessionStart, onStop, onPreToolUse } from '../pi-ecosystem-judgment/human-value-pipeline.js';
|
|
30
|
+
import { onPostToolUse } from '../bootstrap/lifecycle-hooks.js';
|
|
31
|
+
import { budgetReduce, snip, microcompact } from '../context-compaction/index.js';
|
|
30
32
|
// React Harness: 8-gate + 4-guard (防越权 / 防 prompt 注入)
|
|
31
33
|
import { ReactHarness } from '../security/react-harness.js';
|
|
32
34
|
const SHARED_SESSION_PATH = path.join(process.env.HOME || '/tmp', '.bolloon', 'sessions');
|
|
@@ -343,9 +345,21 @@ class PiAgentSession {
|
|
|
343
345
|
messageHistory = [];
|
|
344
346
|
tools = new Map();
|
|
345
347
|
skillRegistry = new SkillRegistry();
|
|
346
|
-
|
|
348
|
+
// 2026-06-16 修: 父要求把 ReAct loop 上限放大到 "几乎无限", 靠自动压缩上下文 + fail-safe 兜底
|
|
349
|
+
// 默认 10000 — 正常任务永远跑不到, 但作为防 LLM 死循环 / 防 OOM 的最后一道闸
|
|
350
|
+
// 旧默认 100 写死导致中等复杂度任务 (10-50 个 tool call + 多步反思) 会被误杀
|
|
351
|
+
MAX_REACT_ITERATIONS = 10_000;
|
|
347
352
|
MAX_REFINE_ATTEMPTS = 3;
|
|
348
353
|
QUALITY_THRESHOLD = 0.6;
|
|
354
|
+
/** P1: 上下文溢出阈值 (单轮估算 token 数, 超过则强制终止防止 prompt-too-long) */
|
|
355
|
+
MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD = 60_000; // 60K tokens 上限
|
|
356
|
+
/** 2026-06-16 新增: 累计错误总数兜底 (不管是否同工具, 累计 N 次就强制退出)
|
|
357
|
+
* 防 LLM 轮换工具名绕开 MAX_SAME_TOOL_FAILURES 的死循环攻击 */
|
|
358
|
+
MAX_TOTAL_ERRORS = 20;
|
|
359
|
+
/** 2026-06-16 新增: loop 内自动压缩触发阈值 (相对 60K 阈值的比例) */
|
|
360
|
+
LOOP_COMPACT_RATIO = 0.8;
|
|
361
|
+
/** P1: max output token 升级重试 (LLM 截断时重试, 最多 3 次) */
|
|
362
|
+
MAX_OUTPUT_TOKEN_ESCALATION_RETRIES = 3;
|
|
349
363
|
thinkingEngine = new DeepThinkingEngine(3);
|
|
350
364
|
coordinator = new AgentCoordinator(3);
|
|
351
365
|
harness = null;
|
|
@@ -354,6 +368,10 @@ class PiAgentSession {
|
|
|
354
368
|
reactHarness = new ReactHarness();
|
|
355
369
|
usePivotLoop = false;
|
|
356
370
|
pivotLoopConfig;
|
|
371
|
+
/** P2: 当前会话的 permission mode (每次 promptStream 入口解析) */
|
|
372
|
+
currentPermissionMode = 'default';
|
|
373
|
+
/** P1.2: Context Collapse 读时投影结果 (feature flag 开启时由 maybeAutoCompact 写入, buildContext 优先用) */
|
|
374
|
+
projectedHistory = null;
|
|
357
375
|
/**
|
|
358
376
|
* Judgment 注入门临时结果: 在 prompt / promptStream / promptWithPivotLoop 入口算一次, 拼到本轮 systemPrompt 末尾
|
|
359
377
|
* 每次调用都会重置 (避免上一轮遗留)
|
|
@@ -388,11 +406,13 @@ class PiAgentSession {
|
|
|
388
406
|
};
|
|
389
407
|
safePhase('gate_compute', { detail: '正在检索相关判断力...' });
|
|
390
408
|
try {
|
|
391
|
-
|
|
409
|
+
// P-Action 4 (2026-06-15) 路径 1 整合: 透传 maxChars=1500 (≈ 375 tokens 硬上限)
|
|
410
|
+
// 路径 2/3 检测由 injection-gate 内部 alreadyInjectedSources 处理 (目前 assembleSystemPrompt 还没注入 value-store 标记, 所以这里不传)
|
|
411
|
+
const gate = await injectJudgmentGate(input, {}, { maxChars: 1500 });
|
|
392
412
|
this.judgmentGateAddition = gate.systemAddition;
|
|
393
413
|
this.judgmentGateUsedIds = gate.usedIds;
|
|
394
414
|
if (gate.usedIds.length > 0) {
|
|
395
|
-
safePhase('gate_done', { usedCount: gate.usedIds.length });
|
|
415
|
+
safePhase('gate_done', { usedCount: gate.usedIds.length, didInject: gate.didInject, skipReason: gate.skipReason });
|
|
396
416
|
}
|
|
397
417
|
}
|
|
398
418
|
catch (err) {
|
|
@@ -504,7 +524,7 @@ class PiAgentSession {
|
|
|
504
524
|
this.tools.set('read_document', {
|
|
505
525
|
name: 'read_document',
|
|
506
526
|
description: '读取文档内容,支持 .txt, .md, .pdf, .docx 格式',
|
|
507
|
-
parameters: { path: '
|
|
527
|
+
parameters: { path: 'string' },
|
|
508
528
|
execute: async (args) => {
|
|
509
529
|
try {
|
|
510
530
|
const content = await documentReader.read(args.path);
|
|
@@ -521,7 +541,7 @@ class PiAgentSession {
|
|
|
521
541
|
this.tools.set('summarize_document', {
|
|
522
542
|
name: 'summarize_document',
|
|
523
543
|
description: '总结文档内容,分析并生成摘要',
|
|
524
|
-
parameters: { path: '
|
|
544
|
+
parameters: { path: 'string', context: 'string' },
|
|
525
545
|
execute: async (args) => {
|
|
526
546
|
try {
|
|
527
547
|
if (!this.minimaxAvailable) {
|
|
@@ -541,7 +561,7 @@ class PiAgentSession {
|
|
|
541
561
|
this.tools.set('improve_document', {
|
|
542
562
|
name: 'improve_document',
|
|
543
563
|
description: '根据要求改进文档内容',
|
|
544
|
-
parameters: { path: '
|
|
564
|
+
parameters: { path: 'string', requirements: 'string' },
|
|
545
565
|
execute: async (args) => {
|
|
546
566
|
try {
|
|
547
567
|
if (!this.minimaxAvailable) {
|
|
@@ -849,8 +869,19 @@ class PiAgentSession {
|
|
|
849
869
|
this.currentSignal = options?.signal ?? null;
|
|
850
870
|
this.currentOnStream = options?.onStream ?? null;
|
|
851
871
|
await this.computeJudgmentGate(input);
|
|
872
|
+
// P2: 解析当前 permission mode
|
|
852
873
|
try {
|
|
853
|
-
|
|
874
|
+
const { resolvePermissionMode } = await import('./permission-mode.js');
|
|
875
|
+
this.currentPermissionMode = resolvePermissionMode();
|
|
876
|
+
}
|
|
877
|
+
catch (err) {
|
|
878
|
+
console.warn('[PiAgent] resolvePermissionMode failed (non-fatal):', err);
|
|
879
|
+
this.currentPermissionMode = 'default';
|
|
880
|
+
}
|
|
881
|
+
try {
|
|
882
|
+
// 2026-06-16: runReActLoop 现在返回 { reply, aiFailed, aiFailureReason } — 这里只需 reply 字符串
|
|
883
|
+
const loopResult = await this.runReActLoop(undefined, options?.signal);
|
|
884
|
+
return loopResult.reply;
|
|
854
885
|
}
|
|
855
886
|
finally {
|
|
856
887
|
if (this.judgmentGateUsedIds.length > 0) {
|
|
@@ -879,6 +910,14 @@ class PiAgentSession {
|
|
|
879
910
|
this.currentOnStream = onStream;
|
|
880
911
|
this.currentSignal = signal ?? null;
|
|
881
912
|
await this.computeJudgmentGate(input);
|
|
913
|
+
// P1.1: 异步跑 Auto-Compact (LLM 摘要, 仅在 budget 超限时触发, 失败静默)
|
|
914
|
+
// 复用 computeJudgmentGate 的 onStream 广播 phase, 跟 judgment 注入门风格一致
|
|
915
|
+
try {
|
|
916
|
+
await this.maybeAutoCompact(onStream, signal);
|
|
917
|
+
}
|
|
918
|
+
catch (err) {
|
|
919
|
+
console.warn('[PiAgent] maybeAutoCompact failed (non-fatal):', err);
|
|
920
|
+
}
|
|
882
921
|
// Bootstrap SessionStart: 收集项目 Context, 拼到 systemAddition 头部
|
|
883
922
|
// (失败静默, 5s 限流防止循环)
|
|
884
923
|
let bootstrapAddition = '';
|
|
@@ -890,16 +929,76 @@ class PiAgentSession {
|
|
|
890
929
|
console.warn('[PiAgent] onSessionStart failed (non-fatal):', err);
|
|
891
930
|
}
|
|
892
931
|
this.bootstrapAddition = bootstrapAddition;
|
|
893
|
-
|
|
894
|
-
let result;
|
|
932
|
+
// P2: 解析当前 permission mode (BootstrapOptions > env BOLLOON_PERM_MODE > default)
|
|
895
933
|
try {
|
|
896
|
-
|
|
934
|
+
const { resolvePermissionMode } = await import('./permission-mode.js');
|
|
935
|
+
this.currentPermissionMode = resolvePermissionMode();
|
|
897
936
|
}
|
|
898
937
|
catch (err) {
|
|
899
|
-
|
|
900
|
-
this.
|
|
901
|
-
|
|
902
|
-
|
|
938
|
+
console.warn('[PiAgent] resolvePermissionMode failed (non-fatal, using default):', err);
|
|
939
|
+
this.currentPermissionMode = 'default';
|
|
940
|
+
}
|
|
941
|
+
this.promptStartTime = Date.now();
|
|
942
|
+
// 2026-06-16: loop 自动重试 — runReActLoop 内部遇到 [AI 服务调用失败] sentinel 时,
|
|
943
|
+
// 会设 aiFailed=true 并提前 break. 这里在外层重跑整个 loop (不是单次 LLM 调用),
|
|
944
|
+
// 临时网络抖动 / 配额瞬时超限可自愈. 最多 3 次, 指数退避 1s/2s/4s.
|
|
945
|
+
// 用户看到 status bar 显示 "自动重试中 X/N" — 不暴露按钮.
|
|
946
|
+
const MAX_LOOP_RETRIES = 3;
|
|
947
|
+
let attempt = 0;
|
|
948
|
+
let result = '';
|
|
949
|
+
let lastAiFailureReason = '';
|
|
950
|
+
while (attempt <= MAX_LOOP_RETRIES) {
|
|
951
|
+
try {
|
|
952
|
+
const loopResult = await this.runReActLoop(onStream, signal);
|
|
953
|
+
result = loopResult.reply;
|
|
954
|
+
if (!loopResult.aiFailed)
|
|
955
|
+
break; // 正常完成, 退出 retry 循环
|
|
956
|
+
lastAiFailureReason = loopResult.aiFailureReason || 'AI 调用失败';
|
|
957
|
+
}
|
|
958
|
+
catch (err) {
|
|
959
|
+
// abort 失败: 视作"已中断", 抛错让上层用 partial 兜底
|
|
960
|
+
this.currentOnStream = null;
|
|
961
|
+
this.currentSignal = null;
|
|
962
|
+
throw err;
|
|
963
|
+
}
|
|
964
|
+
attempt++;
|
|
965
|
+
if (attempt > MAX_LOOP_RETRIES) {
|
|
966
|
+
console.warn(`[PiAgent] loop 自动重试 ${MAX_LOOP_RETRIES} 次后仍失败, 终止`);
|
|
967
|
+
if (onStream) {
|
|
968
|
+
onStream({ type: 'status', content: `⛔ loop 自动重试 ${MAX_LOOP_RETRIES} 次后仍失败: ${lastAiFailureReason}`, tool: 'system' });
|
|
969
|
+
}
|
|
970
|
+
result = lastAiFailureReason || 'AI 服务调用失败, 自动重试后仍不可用';
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
const backoffMs = 1000 * Math.pow(2, attempt - 1); // 1s, 2s, 4s
|
|
974
|
+
console.log(`[PiAgent] loop 自动重试 ${attempt}/${MAX_LOOP_RETRIES}, 等待 ${backoffMs}ms`);
|
|
975
|
+
if (onStream) {
|
|
976
|
+
onStream({ type: 'status', content: `↻ 自动重试 loop ${attempt}/${MAX_LOOP_RETRIES} (${(backoffMs / 1000).toFixed(0)}s 后)`, tool: 'system' });
|
|
977
|
+
}
|
|
978
|
+
// 中途 abort 也要响应
|
|
979
|
+
await new Promise((resolve, reject) => {
|
|
980
|
+
const t = setTimeout(() => {
|
|
981
|
+
signal?.removeEventListener?.('abort', onAbort);
|
|
982
|
+
resolve();
|
|
983
|
+
}, backoffMs);
|
|
984
|
+
const onAbort = () => {
|
|
985
|
+
clearTimeout(t);
|
|
986
|
+
reject(new Error('aborted during retry backoff'));
|
|
987
|
+
};
|
|
988
|
+
if (signal?.aborted) {
|
|
989
|
+
clearTimeout(t);
|
|
990
|
+
reject(new Error('aborted during retry backoff'));
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
994
|
+
});
|
|
995
|
+
// 重试时要把这条 user message 从 history 里移除 (避免下一次 runReActLoop 又重复加入),
|
|
996
|
+
// 因为 messageHistory.push({role:'user'}) 在 promptStream 顶部已经做过, 重跑 runReActLoop 不会重复 push,
|
|
997
|
+
// 但 assistant 失败那条也别留 (留了会污染下一轮 LLM context).
|
|
998
|
+
// 简化: 重试前 pop 一次 assistant (如果最后一条是 assistant)
|
|
999
|
+
if (this.messageHistory.length > 0 && this.messageHistory[this.messageHistory.length - 1].role === 'assistant') {
|
|
1000
|
+
this.messageHistory.pop();
|
|
1001
|
+
}
|
|
903
1002
|
}
|
|
904
1003
|
onStream({ type: 'done', content: '' });
|
|
905
1004
|
// 回溯: 异步记录 usage (不等)
|
|
@@ -981,7 +1080,10 @@ ${this.getToolDefinitions()}
|
|
|
981
1080
|
- 仔细分析工具返回结果
|
|
982
1081
|
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
983
1082
|
- 如果需要更多信息,继续调用工具${this.judgmentGateAddition}`;
|
|
984
|
-
|
|
1083
|
+
// 2026-06-15: 把 currentOnStream 传给 loop, 让 step-timeline 在 pivot 循环里也能 emit step_start/done
|
|
1084
|
+
// 之前 loop.execute() 不接 streamCallback, 导致 step-timeline 只能看到老 runReActLoop 路径
|
|
1085
|
+
// promptWithPivotLoop 路径 0 step events — UI 显示 timeline 但永远是空
|
|
1086
|
+
const result = await loop.execute(input, llm, systemPrompt, this.currentOnStream ?? undefined);
|
|
985
1087
|
this.messageHistory.push({ role: 'user', content: input });
|
|
986
1088
|
if (result.response) {
|
|
987
1089
|
this.messageHistory.push({ role: 'assistant', content: result.response });
|
|
@@ -1000,8 +1102,14 @@ ${this.getToolDefinitions()}
|
|
|
1000
1102
|
let lastQualityScore = 0;
|
|
1001
1103
|
let refineAttempts = 0;
|
|
1002
1104
|
let consecutiveErrors = 0;
|
|
1105
|
+
// 2026-06-16 新增: 累计错误数 (跨工具, 兜底防 LLM 轮换工具名死循环)
|
|
1106
|
+
let totalErrors = 0;
|
|
1003
1107
|
let lastFailedTool = ''; // 跟踪最近一次失败的 tool name
|
|
1004
1108
|
let lastFailedToolCount = 0; // 最近失败工具的连续失败次数
|
|
1109
|
+
// 2026-06-16: AI sentinel 标志 — runReActLoop 返回 aiFailed=true,
|
|
1110
|
+
// promptStream 据此自动重跑整个 loop 最多 N 次 (不是单次 LLM 重试)
|
|
1111
|
+
let aiFailed = false;
|
|
1112
|
+
let aiFailureReason = '';
|
|
1005
1113
|
const MAX_CONSECUTIVE_ERRORS = 3;
|
|
1006
1114
|
const MAX_SAME_TOOL_FAILURES = 3; // 同一工具连续失败 3 次, 强制让 LLM 给出最终答案
|
|
1007
1115
|
// 发送循环开始的事件
|
|
@@ -1018,6 +1126,51 @@ ${this.getToolDefinitions()}
|
|
|
1018
1126
|
}
|
|
1019
1127
|
while (iteration < this.MAX_REACT_ITERATIONS) {
|
|
1020
1128
|
iteration++;
|
|
1129
|
+
// 停止条件 1: max turns (fail-safe 10000, 正常任务永远跑不到)
|
|
1130
|
+
if (iteration >= this.MAX_REACT_ITERATIONS) {
|
|
1131
|
+
console.warn(`[PiAgent] 达到最大循环数 ${this.MAX_REACT_ITERATIONS}, 强制终止 (fail-safe)`);
|
|
1132
|
+
onStream?.({ type: 'error', content: `⏹️ 达到最大循环数 (${this.MAX_REACT_ITERATIONS}, fail-safe)`, tool: 'loop' });
|
|
1133
|
+
finalResponse = finalResponse || '(本轮 ReAct 循环达到最大步数, 强制结束)';
|
|
1134
|
+
break;
|
|
1135
|
+
}
|
|
1136
|
+
// 停止条件 2: signal.aborted (显式 abort / 用户中断)
|
|
1137
|
+
if (signal?.aborted) {
|
|
1138
|
+
console.warn('[PiAgent] runReActLoop aborted by signal');
|
|
1139
|
+
onStream?.({ type: 'error', content: '⏹️ 用户中断', tool: 'loop' });
|
|
1140
|
+
finalResponse = finalResponse || '(用户中断)';
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
// 2026-06-16 新增: 累计错误兜底 — 跨工具, 防 LLM 轮换工具名绕过 MAX_SAME_TOOL_FAILURES
|
|
1144
|
+
if (totalErrors >= this.MAX_TOTAL_ERRORS) {
|
|
1145
|
+
console.warn(`[PiAgent] 累计错误 ${totalErrors} >= ${this.MAX_TOTAL_ERRORS}, 强制终止 (防死循环)`);
|
|
1146
|
+
onStream?.({ type: 'error', content: `⛔ 累计 ${totalErrors} 次错误, 强制终止 (防止 LLM 死循环)`, tool: 'loop' });
|
|
1147
|
+
finalResponse = finalResponse || `(本轮 ReAct 循环累计 ${totalErrors} 次错误, 强制结束。请换个思路或简化任务重试。)`;
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
// 2026-06-16 新增: loop 内自动压缩 — token 超 80% 阈值时跑一次
|
|
1151
|
+
// compact 失败走 C 路径: 不强行 break, 让现有 60K 阈值兜底 (后面有检查)
|
|
1152
|
+
const compactThreshold = this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD * this.LOOP_COMPACT_RATIO;
|
|
1153
|
+
const estimatedTokensBefore = this.estimateHistoryTokens();
|
|
1154
|
+
if (estimatedTokensBefore > compactThreshold) {
|
|
1155
|
+
const tokensBeforeCompact = estimatedTokensBefore;
|
|
1156
|
+
console.log(`[PiAgent] loop 入口 token ${tokensBeforeCompact} > ${compactThreshold}, 触发自动压缩`);
|
|
1157
|
+
onStream?.({ type: 'status', content: `🗜️ loop 自动压缩 (token ${tokensBeforeCompact} > ${compactThreshold})`, tool: 'compactor' });
|
|
1158
|
+
try {
|
|
1159
|
+
await this.maybeAutoCompact(onStream, signal);
|
|
1160
|
+
}
|
|
1161
|
+
catch (compactErr) {
|
|
1162
|
+
// C 路径: compact 失败不 break, 让 token 阈值检查兜底
|
|
1163
|
+
console.warn(`[PiAgent] loop 内 maybeAutoCompact 失败 (non-fatal, 继续走 token 阈值):`, compactErr);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
// 停止条件 3: context overflow (compact 后还超, 强制终止)
|
|
1167
|
+
const estimatedTokens = this.estimateHistoryTokens();
|
|
1168
|
+
if (estimatedTokens > this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD) {
|
|
1169
|
+
console.warn(`[PiAgent] context overflow (${estimatedTokens} tokens > ${this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD})`);
|
|
1170
|
+
onStream?.({ type: 'error', content: `⏹️ 上下文溢出 (${estimatedTokens} tokens, 阈值 ${this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD})`, tool: 'loop' });
|
|
1171
|
+
finalResponse = finalResponse || '(本轮 ReAct 循环因上下文溢出终止)';
|
|
1172
|
+
break;
|
|
1173
|
+
}
|
|
1021
1174
|
// 调试日志:显示每次循环开始
|
|
1022
1175
|
console.log(`[PiAgent] 循环 ${iteration}/${this.MAX_REACT_ITERATIONS} 开始`);
|
|
1023
1176
|
if (onStream) {
|
|
@@ -1058,8 +1211,26 @@ ${toolDefs}
|
|
|
1058
1211
|
- 仔细分析工具返回结果
|
|
1059
1212
|
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
1060
1213
|
- 如果需要更多信息,继续调用工具${this.judgmentGateAddition}`;
|
|
1061
|
-
|
|
1062
|
-
|
|
1214
|
+
// 3 个恢复机制 (Claude Code 论文 9-step pipeline 内部):
|
|
1215
|
+
// 1. max output token 升级 (最多 3 次, 每次 maxOutputTokens 翻倍)
|
|
1216
|
+
// 2. reactive compaction (prompt 估算超阈值, 跑压缩)
|
|
1217
|
+
// 3. prompt-too-long (LLM 报错 4xxx token 错误, 跑 reactive compaction 再试 1 次)
|
|
1218
|
+
// 失败静默: 全部重试失败 → 空 reply (上层用 no tool_use 终止)
|
|
1219
|
+
const response = await this.callLlmWithRecovery(llm, context, systemPrompt, signal, onStream);
|
|
1220
|
+
const reply = (response.reply || '').trim();
|
|
1221
|
+
// 2026-06-16: 看到 [AI 服务调用失败] sentinel → 不再立即 break,
|
|
1222
|
+
// 而是设 aiFailed=true, 让外层 promptStream 自动重跑整个 loop 最多 N 次
|
|
1223
|
+
// (LLM API 401 / 网络错 / 配额满时, pi-ai 返回这个 prefix;
|
|
1224
|
+
// 自动 retry 兜底: 临时网络抖动可自愈, 真挂 N 次后才报失败)
|
|
1225
|
+
if (reply.startsWith('[AI 服务调用失败]')) {
|
|
1226
|
+
console.log(`[PiAgent] 收到 AI 错误 sentinel, 标记 aiFailed, 外层会自动重试整个 loop`);
|
|
1227
|
+
aiFailed = true;
|
|
1228
|
+
aiFailureReason = reply.length > 200 ? reply.substring(0, 200) : reply;
|
|
1229
|
+
if (onStream) {
|
|
1230
|
+
onStream({ type: 'status', content: `⚠️ AI 调用失败, 将自动重试整个 loop`, tool: 'system' });
|
|
1231
|
+
}
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1063
1234
|
console.log(`[PiAgent] LLM 回复长度: ${reply.length}, 内容预览: "${reply.substring(0, 80)}..."`);
|
|
1064
1235
|
console.log(`[PiAgent] LLM 完整回复:\n${reply}`);
|
|
1065
1236
|
// 通知前端:收到 LLM 回复
|
|
@@ -1091,21 +1262,35 @@ ${toolDefs}
|
|
|
1091
1262
|
if (toolCall.args && Object.keys(toolCall.args).length > 0) {
|
|
1092
1263
|
onStream({ type: 'status', content: `📋 参数: ${JSON.stringify(toolCall.args)}`, tool: toolCall.name });
|
|
1093
1264
|
}
|
|
1265
|
+
// 2026-06-15: step-timeline 状态机 — 开新节点
|
|
1266
|
+
onStream({
|
|
1267
|
+
type: 'step_start',
|
|
1268
|
+
content: `调用 ${toolCall.name}`,
|
|
1269
|
+
tool: toolCall.name,
|
|
1270
|
+
args: toolCall.args || {},
|
|
1271
|
+
});
|
|
1094
1272
|
}
|
|
1095
1273
|
const tool = this.tools.get(toolCall.name);
|
|
1096
1274
|
if (!tool) {
|
|
1097
1275
|
consecutiveErrors++;
|
|
1276
|
+
// 2026-06-16 新增: 未知工具也要累计 (LLM 幻觉高频场景)
|
|
1277
|
+
totalErrors++;
|
|
1098
1278
|
const errorResult = { success: false, error: `未知工具: ${toolCall.name}` };
|
|
1099
1279
|
this.messageHistory.push({ role: 'tool', content: JSON.stringify(errorResult), toolResult: errorResult });
|
|
1100
1280
|
this.logToHarness(toolCall.name, toolCall.args, errorResult);
|
|
1101
|
-
console.warn(`[PiAgent] 未知工具: ${toolCall.name},跳过并继续`);
|
|
1281
|
+
console.warn(`[PiAgent] 未知工具: ${toolCall.name} (累计 ${totalErrors}/${this.MAX_TOTAL_ERRORS}),跳过并继续`);
|
|
1102
1282
|
continue;
|
|
1103
1283
|
}
|
|
1104
1284
|
// Bootstrap PreToolUse hook: 调工具前校验 (危险命令拦截)
|
|
1105
1285
|
// 失败静默 — hook 自身挂掉 = 放行
|
|
1286
|
+
// P2: 透传 permissionMode (从 BootstrapOptions / env BOLLOON_PERM_MODE 解析)
|
|
1106
1287
|
let toolToExecute = tool;
|
|
1107
1288
|
try {
|
|
1108
|
-
const pre = await onPreToolUse({
|
|
1289
|
+
const pre = await onPreToolUse({
|
|
1290
|
+
tool: toolCall.name,
|
|
1291
|
+
args: toolCall.args || {},
|
|
1292
|
+
permissionMode: this.currentPermissionMode,
|
|
1293
|
+
});
|
|
1109
1294
|
if (!pre.allowed) {
|
|
1110
1295
|
const deniedResult = {
|
|
1111
1296
|
success: false,
|
|
@@ -1123,6 +1308,13 @@ ${toolDefs}
|
|
|
1123
1308
|
content: `🛡️ PreToolUse 拒绝 ${toolCall.name}: ${pre.reason || '安全校验失败'}`,
|
|
1124
1309
|
tool: toolCall.name,
|
|
1125
1310
|
});
|
|
1311
|
+
// 2026-06-15: step-timeline — 拦在 PreToolUse, 标 step_error
|
|
1312
|
+
onStream({
|
|
1313
|
+
type: 'step_error',
|
|
1314
|
+
content: `PreToolUse 拒绝 ${toolCall.name}`,
|
|
1315
|
+
tool: toolCall.name,
|
|
1316
|
+
error: pre.reason || '安全校验失败',
|
|
1317
|
+
});
|
|
1126
1318
|
}
|
|
1127
1319
|
console.warn(`[PiAgent] PreToolUse denied ${toolCall.name}: ${pre.reason}`);
|
|
1128
1320
|
// 不调 tool.execute, 也不计 consecutiveErrors (这是用户级拒绝, 不是工具错)
|
|
@@ -1153,6 +1345,13 @@ ${toolDefs}
|
|
|
1153
1345
|
content: `🛡️ Harness ${pre.details.rejectedBy} 拒绝 ${toolCall.name}: ${pre.reason || '安全校验失败'}`,
|
|
1154
1346
|
tool: toolCall.name,
|
|
1155
1347
|
});
|
|
1348
|
+
// 2026-06-15: step-timeline — Harness gate 拒绝, 标 step_error
|
|
1349
|
+
onStream({
|
|
1350
|
+
type: 'step_error',
|
|
1351
|
+
content: `Harness 拒绝 ${toolCall.name}`,
|
|
1352
|
+
tool: toolCall.name,
|
|
1353
|
+
error: pre.reason || '安全校验失败',
|
|
1354
|
+
});
|
|
1156
1355
|
}
|
|
1157
1356
|
console.warn(`[PiAgent] Harness denied ${toolCall.name} (${pre.details.rejectedBy}): ${pre.reason}`);
|
|
1158
1357
|
continue;
|
|
@@ -1162,8 +1361,26 @@ ${toolDefs}
|
|
|
1162
1361
|
console.warn('[PiAgent] reactHarness.preToolCall failed (non-fatal, allowing):', err);
|
|
1163
1362
|
}
|
|
1164
1363
|
try {
|
|
1364
|
+
const toolStart = Date.now();
|
|
1165
1365
|
let result = await tool.execute(toolCall.args);
|
|
1166
|
-
|
|
1366
|
+
const toolDurationMs = Date.now() - toolStart;
|
|
1367
|
+
console.log(`[PiAgent] 工具 ${toolCall.name} 执行完成: success=${result.success} (${toolDurationMs}ms)`);
|
|
1368
|
+
// PostToolUse 审计 hook: 写 audit log, 默认 continue
|
|
1369
|
+
try {
|
|
1370
|
+
await onPostToolUse({
|
|
1371
|
+
tool: toolCall.name,
|
|
1372
|
+
args: toolCall.args || {},
|
|
1373
|
+
result: {
|
|
1374
|
+
success: result.success,
|
|
1375
|
+
output: result.output?.substring(0, 500),
|
|
1376
|
+
error: result.error,
|
|
1377
|
+
},
|
|
1378
|
+
durationMs: toolDurationMs,
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
catch (postErr) {
|
|
1382
|
+
console.warn('[PiAgent] onPostToolUse failed (non-fatal):', postErr);
|
|
1383
|
+
}
|
|
1167
1384
|
// Context router: 拿最近一次 preToolCall 算的 hint, 拼到 tool result messageHistory
|
|
1168
1385
|
// (LLM 下次看到 tool result 时, 能"记得"这次调用的安全约束)
|
|
1169
1386
|
const routeHint = this.reactHarness.getLastRouteHint();
|
|
@@ -1209,9 +1426,24 @@ ${toolDefs}
|
|
|
1209
1426
|
const outputPreview = result.output.substring(0, 200);
|
|
1210
1427
|
onStream({ type: 'tool', content: `📤 结果: ${outputPreview}${result.output.length > 200 ? '...' : ''}`, tool: toolCall.name });
|
|
1211
1428
|
}
|
|
1429
|
+
// 2026-06-15: step-timeline 状态机 — 关闭当前节点 (成功)
|
|
1430
|
+
onStream({
|
|
1431
|
+
type: 'step_done',
|
|
1432
|
+
content: `${toolCall.name} 执行成功`,
|
|
1433
|
+
tool: toolCall.name,
|
|
1434
|
+
success: true,
|
|
1435
|
+
output: result.output,
|
|
1436
|
+
});
|
|
1212
1437
|
}
|
|
1213
1438
|
else {
|
|
1214
1439
|
onStream({ type: 'error', content: `❌ ${toolCall.name} 执行失败: ${result.error}`, tool: toolCall.name });
|
|
1440
|
+
// 2026-06-15: step-timeline 状态机 — 关闭当前节点 (失败)
|
|
1441
|
+
onStream({
|
|
1442
|
+
type: 'step_error',
|
|
1443
|
+
content: `${toolCall.name} 执行失败`,
|
|
1444
|
+
tool: toolCall.name,
|
|
1445
|
+
error: result.error,
|
|
1446
|
+
});
|
|
1215
1447
|
}
|
|
1216
1448
|
}
|
|
1217
1449
|
if (result.success) {
|
|
@@ -1233,6 +1465,8 @@ ${toolDefs}
|
|
|
1233
1465
|
}
|
|
1234
1466
|
else {
|
|
1235
1467
|
consecutiveErrors++;
|
|
1468
|
+
// 2026-06-16 新增: 累计错误 (跨工具, 兜底防 LLM 轮换工具名死循环)
|
|
1469
|
+
totalErrors++;
|
|
1236
1470
|
// 跟踪同一工具连续失败次数
|
|
1237
1471
|
if (toolCall.name === lastFailedTool) {
|
|
1238
1472
|
lastFailedToolCount++;
|
|
@@ -1241,7 +1475,7 @@ ${toolDefs}
|
|
|
1241
1475
|
lastFailedTool = toolCall.name;
|
|
1242
1476
|
lastFailedToolCount = 1;
|
|
1243
1477
|
}
|
|
1244
|
-
console.warn(`[PiAgent] 工具 ${toolCall.name} 执行失败 (${lastFailedToolCount}/${MAX_SAME_TOOL_FAILURES}): ${result.error}`);
|
|
1478
|
+
console.warn(`[PiAgent] 工具 ${toolCall.name} 执行失败 (${lastFailedToolCount}/${MAX_SAME_TOOL_FAILURES}, 累计 ${totalErrors}/${this.MAX_TOTAL_ERRORS}): ${result.error}`);
|
|
1245
1479
|
// 同一工具连续失败达到上限, 不再重试, 强制 LLM 给出最终答案
|
|
1246
1480
|
if (lastFailedToolCount >= MAX_SAME_TOOL_FAILURES) {
|
|
1247
1481
|
console.log(`[PiAgent] 工具 ${toolCall.name} 连续 ${MAX_SAME_TOOL_FAILURES} 次失败, 放弃并要求直接回答`);
|
|
@@ -1267,10 +1501,12 @@ ${toolDefs}
|
|
|
1267
1501
|
}
|
|
1268
1502
|
catch (execError) {
|
|
1269
1503
|
consecutiveErrors++;
|
|
1504
|
+
// 2026-06-16 新增: 异常分支也要累计
|
|
1505
|
+
totalErrors++;
|
|
1270
1506
|
const errorResult = { success: false, error: String(execError) };
|
|
1271
1507
|
this.messageHistory.push({ role: 'tool', content: JSON.stringify(errorResult), toolResult: errorResult });
|
|
1272
1508
|
this.logToHarness(toolCall.name, toolCall.args, errorResult);
|
|
1273
|
-
console.error(`[PiAgent]
|
|
1509
|
+
console.error(`[PiAgent] 工具执行异常 (累计 ${totalErrors}/${this.MAX_TOTAL_ERRORS}): ${execError}`);
|
|
1274
1510
|
}
|
|
1275
1511
|
}
|
|
1276
1512
|
else {
|
|
@@ -1288,7 +1524,10 @@ ${toolDefs}
|
|
|
1288
1524
|
const containsToolCallIntent = reply.includes('调用工具') || reply.includes('tool(') ||
|
|
1289
1525
|
reply.includes('使用工具') || reply.includes('需要获取') || reply.includes('需要查看') ||
|
|
1290
1526
|
// 兼容 LLM 用对象字面量输出 tool call (上轮没解析成功时, 至少要继续)
|
|
1291
|
-
reply.includes('tool =>') || reply.includes('[TOOL_CALL]')
|
|
1527
|
+
reply.includes('tool =>') || reply.includes('[TOOL_CALL]') ||
|
|
1528
|
+
// 2026-06-15 修: 兼容 LLM 用 XML 标签输出 tool call (<shell_exec>...</shell_exec>)
|
|
1529
|
+
// 这时 parseToolCall 失败, 至少要让 loop 继续
|
|
1530
|
+
/<\w+>[\s\S]*?<\/\w+>/.test(reply);
|
|
1292
1531
|
const hasError = ['不存在', '找不到', '无法找到', 'not found', 'does not exist',
|
|
1293
1532
|
'错误', 'error', '失败', 'failed'].some(k => reply.includes(k));
|
|
1294
1533
|
const isTooShort = reply.length < 50 && reply.length > 0;
|
|
@@ -1341,7 +1580,8 @@ Workspace root folder: ${this.cwd}
|
|
|
1341
1580
|
catch (err) {
|
|
1342
1581
|
console.warn('[PiAgent] reactHarness.onSessionEnd failed (non-fatal):', err);
|
|
1343
1582
|
}
|
|
1344
|
-
|
|
1583
|
+
// 2026-06-16: 暴露 aiFailed 标志 — promptStream 据此决定是否自动重试整个 loop
|
|
1584
|
+
return { reply: finalResponse, aiFailed, aiFailureReason: aiFailureReason || undefined };
|
|
1345
1585
|
}
|
|
1346
1586
|
async deepThink(prompt) {
|
|
1347
1587
|
const result = await this.thinkingEngine.think(prompt);
|
|
@@ -1387,7 +1627,13 @@ Workspace root folder: ${this.cwd}
|
|
|
1387
1627
|
return { outputs, success: allSuccess };
|
|
1388
1628
|
}
|
|
1389
1629
|
buildContext() {
|
|
1390
|
-
|
|
1630
|
+
// P1 接入: 同步跑前 3 层压缩 (Budget Reduction / Snip / Microcompact)
|
|
1631
|
+
// 异步层 (Context Collapse / Auto-Compact) 在 promptStream 入口处单独跑 (用 LLM)
|
|
1632
|
+
// 失败静默: 任何 stage 抛错 → 走老 slice(-10) 逻辑
|
|
1633
|
+
//
|
|
1634
|
+
// P1.2: 如果 maybeAutoCompact 算过 Context Collapse 投影, 用 this.projectedHistory (读时投影, 非破坏)
|
|
1635
|
+
const source = this.projectedHistory ?? this.messageHistory;
|
|
1636
|
+
const recentMessages = this.compressHistorySync(source).slice(-10);
|
|
1391
1637
|
return recentMessages.map(m => {
|
|
1392
1638
|
if (m.role === 'user')
|
|
1393
1639
|
return `用户: ${m.content}`;
|
|
@@ -1400,6 +1646,154 @@ Workspace root folder: ${this.cwd}
|
|
|
1400
1646
|
return m.content;
|
|
1401
1647
|
}).join('\n');
|
|
1402
1648
|
}
|
|
1649
|
+
/**
|
|
1650
|
+
* 估算 messageHistory 的 token 数 (4 字符 ≈ 1 token, 与 context-compaction 同步).
|
|
1651
|
+
* 失败静默: 任何异常 → 0 (不阻塞)
|
|
1652
|
+
*/
|
|
1653
|
+
estimateHistoryTokens() {
|
|
1654
|
+
try {
|
|
1655
|
+
const { estimateTokens } = require('../context-compaction/index.js');
|
|
1656
|
+
return estimateTokens(this.messageHistory);
|
|
1657
|
+
}
|
|
1658
|
+
catch {
|
|
1659
|
+
return 0;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* 3 个恢复机制合一:
|
|
1664
|
+
* 1. max output token 升级: 最多 3 次, 每次 maxOutputTokens 翻倍 (如果 llm.chat 支持)
|
|
1665
|
+
* 2. reactive compaction: 估算 > 80% 阈值, 跑 sync compressHistorySync + 必要时 maybeAutoCompact
|
|
1666
|
+
* 3. prompt-too-long: LLM 报错 4xxx token 错误, 跑 reactive compaction 再试 1 次
|
|
1667
|
+
*
|
|
1668
|
+
* 失败静默: 全部失败 → 返回空 reply, 让上层 no-tool_use 终止
|
|
1669
|
+
*/
|
|
1670
|
+
async callLlmWithRecovery(llm, context, systemPrompt, signal, onStream) {
|
|
1671
|
+
// Reactive compaction 预检: 估算 token 超 80% 阈值, 跑一次
|
|
1672
|
+
const estimated = this.estimateHistoryTokens();
|
|
1673
|
+
if (estimated > this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD * 0.8) {
|
|
1674
|
+
console.warn(`[PiAgent] reactive compaction pre-check (${estimated} tokens > 80% threshold)`);
|
|
1675
|
+
onStream?.({ type: 'status', content: '⚠️ reactive compaction 预检触发', tool: 'recovery' });
|
|
1676
|
+
try {
|
|
1677
|
+
const compacted = this.compressHistorySync(this.messageHistory);
|
|
1678
|
+
this.messageHistory = compacted;
|
|
1679
|
+
if (this.estimateHistoryTokens() > this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD * 0.8) {
|
|
1680
|
+
await this.maybeAutoCompact(onStream, signal);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
catch (err) {
|
|
1684
|
+
console.warn('[PiAgent] reactive compaction pre-check failed:', err);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
// 主调用 + 3 个恢复路径
|
|
1688
|
+
let lastErr = null;
|
|
1689
|
+
for (let attempt = 0; attempt <= this.MAX_OUTPUT_TOKEN_ESCALATION_RETRIES; attempt++) {
|
|
1690
|
+
try {
|
|
1691
|
+
const response = await llm.chat(context, systemPrompt, signal);
|
|
1692
|
+
return { reply: response.reply || '' };
|
|
1693
|
+
}
|
|
1694
|
+
catch (err) {
|
|
1695
|
+
lastErr = err;
|
|
1696
|
+
const errMsg = String(err?.message || err || '');
|
|
1697
|
+
const isPromptTooLong = /token|too long|exceed|length|context|4000|413|429/i.test(errMsg);
|
|
1698
|
+
if (isPromptTooLong) {
|
|
1699
|
+
console.warn(`[PiAgent] prompt-too-long 触发 (attempt ${attempt + 1}), 跑 reactive compaction`);
|
|
1700
|
+
onStream?.({ type: 'status', content: `⚠️ prompt-too-long 触发 (attempt ${attempt + 1}/${this.MAX_OUTPUT_TOKEN_ESCALATION_RETRIES + 1})`, tool: 'recovery' });
|
|
1701
|
+
try {
|
|
1702
|
+
await this.maybeAutoCompact(onStream, signal);
|
|
1703
|
+
}
|
|
1704
|
+
catch (compactionErr) {
|
|
1705
|
+
console.warn('[PiAgent] reactive compaction on prompt-too-long failed:', compactionErr);
|
|
1706
|
+
}
|
|
1707
|
+
// 重新生成 context (compressHistorySync + projected)
|
|
1708
|
+
context = this.buildContext();
|
|
1709
|
+
}
|
|
1710
|
+
else {
|
|
1711
|
+
// 非 prompt-too-long 错误, 1 次重试就放弃
|
|
1712
|
+
if (attempt === 0) {
|
|
1713
|
+
console.warn(`[PiAgent] LLM 调用失败 (non-prompt-too-long), 1 次重试:`, err);
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
break;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
console.warn('[PiAgent] callLlmWithRecovery 全失败 (silent):', lastErr);
|
|
1721
|
+
return { reply: '' };
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* 同步压缩: 跑前 3 层 (Budget Reduction / Snip / Microcompact).
|
|
1725
|
+
* Context Collapse / Auto-Compact 是 async, 不在 buildContext 同步链里跑.
|
|
1726
|
+
* 失败静默: 任何 stage 抛错 → 返回原 history.
|
|
1727
|
+
*/
|
|
1728
|
+
compressHistorySync(history) {
|
|
1729
|
+
try {
|
|
1730
|
+
// context-compaction 的 Message 与 pi-sdk 的 Message 字段兼容
|
|
1731
|
+
// 这里用 any cast 跳过 structural type 严格校验 (避免双向 import)
|
|
1732
|
+
let h = history;
|
|
1733
|
+
const r1 = budgetReduce(h);
|
|
1734
|
+
h = r1.history;
|
|
1735
|
+
const r2 = snip(h);
|
|
1736
|
+
h = r2.history;
|
|
1737
|
+
const r3 = microcompact(h);
|
|
1738
|
+
h = r3.history;
|
|
1739
|
+
return h;
|
|
1740
|
+
}
|
|
1741
|
+
catch (err) {
|
|
1742
|
+
console.warn('[PiAgent] compressHistorySync failed (silent, using original):', err);
|
|
1743
|
+
return history;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
/**
|
|
1747
|
+
* P1.1: 异步跑 Auto-Compact (LLM 摘要).
|
|
1748
|
+
* 入口: promptStream 入口, 在 computeJudgmentGate 之后, onSessionStart 之前.
|
|
1749
|
+
*
|
|
1750
|
+
* 逻辑:
|
|
1751
|
+
* 1. 跑完整 compactPipeline (5 层, 异步)
|
|
1752
|
+
* 2. 第 5 层 (Auto-Compact) 需要 LLM, 通过 getMinimax().chat 注入
|
|
1753
|
+
* 3. 如果 budgetGate 不超限, 5 层短路在前 3 层, 不会调 LLM → 零开销
|
|
1754
|
+
* 4. 失败静默: 任何异常 → console.warn + 保留原 messageHistory
|
|
1755
|
+
*
|
|
1756
|
+
* onStream 广播: 跟 computeJudgmentGate 风格一致 (phase 事件供 UI timeline 显示)
|
|
1757
|
+
*/
|
|
1758
|
+
async maybeAutoCompact(onStream, signal) {
|
|
1759
|
+
if (this.messageHistory.length < 10)
|
|
1760
|
+
return; // 历史太短, 不值得压
|
|
1761
|
+
onStream?.({ type: 'status', content: '🗜️ 评估是否需要压缩上下文...', tool: 'compactor' });
|
|
1762
|
+
// 注入 LLM (用 getMinimax().chat, 与 judgment 注入门 / ReAct 循环同一来源)
|
|
1763
|
+
// 给 Context Collapse (虚拟投影) 和 Auto-Compact (摘要) 共用
|
|
1764
|
+
const llm = getMinimax();
|
|
1765
|
+
const llmChat = async (systemPrompt, userPrompt) => {
|
|
1766
|
+
const r = await llm.chat(userPrompt, systemPrompt, signal);
|
|
1767
|
+
return r.reply;
|
|
1768
|
+
};
|
|
1769
|
+
const { compactPipeline, isContextCollapseEnabled } = await import('../context-compaction/index.js');
|
|
1770
|
+
const result = await compactPipeline(this.messageHistory, {
|
|
1771
|
+
maxTokens: 8000,
|
|
1772
|
+
llmChat,
|
|
1773
|
+
collapseLlmChat: llmChat, // P1.2: Context Collapse 投影也用同一 LLM
|
|
1774
|
+
cacheScope: this.currentChannelId || 'default',
|
|
1775
|
+
});
|
|
1776
|
+
if (result.compacted && result.history.length < this.messageHistory.length) {
|
|
1777
|
+
const saved = this.messageHistory.length - result.history.length;
|
|
1778
|
+
const stagesApplied = result.stages.filter((s) => s.applied).map((s) => s.stage).join(' → ');
|
|
1779
|
+
onStream?.({
|
|
1780
|
+
type: 'status',
|
|
1781
|
+
content: `🗜️ 上下文压缩: ${stagesApplied || 'no-op'} | 节省 ${saved} 条 (剩余 ${result.history.length}, collapse=${isContextCollapseEnabled() ? 'on' : 'off'})`,
|
|
1782
|
+
tool: 'compactor',
|
|
1783
|
+
});
|
|
1784
|
+
// 关键: 第 4 层 (Context Collapse) 是读时投影 (非破坏)
|
|
1785
|
+
// 第 5 层 (Auto-Compact) 是破坏性折叠
|
|
1786
|
+
// 这里用 if-else 区分: collapse on → 仅 buildContext 用; collapse off → 真更新
|
|
1787
|
+
if (isContextCollapseEnabled()) {
|
|
1788
|
+
this.projectedHistory = result.history; // buildContext 用
|
|
1789
|
+
// messageHistory 不变 (非破坏)
|
|
1790
|
+
}
|
|
1791
|
+
else {
|
|
1792
|
+
this.messageHistory = result.history; // 真破坏性更新
|
|
1793
|
+
this.projectedHistory = null;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1403
1797
|
isFinalResponse(content) {
|
|
1404
1798
|
// 只有明确输出 <final gen> 才认为是最终回答
|
|
1405
1799
|
return content.includes('<final gen>');
|
|
@@ -1439,6 +1833,9 @@ Workspace root folder: ${this.cwd}
|
|
|
1439
1833
|
/\btool\s*=>\s*["'](\w+)["']/,
|
|
1440
1834
|
// 兼容: [TOOL_CALL] 块内 JSON 形式 {"name": "x", "args": {...}}
|
|
1441
1835
|
/\[TOOL_CALL\][\s\S]*?\{\s*"name"\s*:\s*"(\w+)"\s*,\s*"args"\s*:\s*(\{[\s\S]*?\})/i,
|
|
1836
|
+
// 2026-06-15 修: 兼容 LLM 输出的 XML 格式 <tool_name>...<arg>value</arg>...</tool_name>
|
|
1837
|
+
// 实际 LLM 习惯: <shell_exec>\n<command>ls</command>\n<args>["-la", "..."]</args>\n</shell_exec>
|
|
1838
|
+
/<(\w+)>([\s\S]*?)<\/\1>/,
|
|
1442
1839
|
];
|
|
1443
1840
|
for (const pattern of patterns) {
|
|
1444
1841
|
const match = content.match(pattern);
|
|
@@ -1464,6 +1861,19 @@ Workspace root folder: ${this.cwd}
|
|
|
1464
1861
|
}
|
|
1465
1862
|
}
|
|
1466
1863
|
}
|
|
1864
|
+
else if (rawArgs && /<\w+>[\s\S]*<\/\w+>/.test(rawArgs)) {
|
|
1865
|
+
// 2026-06-15 修: XML 格式, 解析内嵌子标签 <argname>value</argname>
|
|
1866
|
+
// 例: <command>ls</command>\n<args>["-la","~/.bolloon/skills"]</args>
|
|
1867
|
+
const xmlArgPattern = /<(\w+)>([\s\S]*?)<\/\1>/g;
|
|
1868
|
+
let xmlMatch;
|
|
1869
|
+
while ((xmlMatch = xmlArgPattern.exec(rawArgs)) !== null) {
|
|
1870
|
+
const argName = xmlMatch[1];
|
|
1871
|
+
const argValue = xmlMatch[2].trim();
|
|
1872
|
+
if (argName && argValue) {
|
|
1873
|
+
args[argName] = argValue;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1467
1877
|
else if (rawArgs) {
|
|
1468
1878
|
// 形参串, 形如 key: value, key2: value2
|
|
1469
1879
|
const argPairs = rawArgs.split(',').map(s => s.trim()).filter(Boolean);
|