@bolloon/bolloon-agent 0.4.28 → 0.4.30
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/contacts/chain.js +579 -0
- package/dist/agents/contacts/cli.js +158 -0
- package/dist/agents/contacts/consent.js +124 -0
- package/dist/agents/contacts/grant-payload.js +45 -0
- package/dist/agents/contacts/grants.js +451 -0
- package/dist/agents/contacts/policy.js +264 -0
- package/dist/agents/contacts/preview-types.js +6 -0
- package/dist/agents/contacts/providers.js +341 -0
- package/dist/agents/contacts/store.js +326 -0
- package/dist/agents/contacts/tools.js +154 -0
- package/dist/agents/contacts/types.js +148 -0
- package/dist/agents/pi-sdk-tools.js +3 -1
- package/dist/agents/pi-sdk.js +14 -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/contacts/chain.js +619 -0
- package/dist/electron-build/agents/contacts/chain.js.map +1 -0
- package/dist/electron-build/agents/contacts/consent.js +163 -0
- package/dist/electron-build/agents/contacts/consent.js.map +1 -0
- package/dist/electron-build/agents/contacts/grant-payload.js +52 -0
- package/dist/electron-build/agents/contacts/grant-payload.js.map +1 -0
- package/dist/electron-build/agents/contacts/grants.js +500 -0
- package/dist/electron-build/agents/contacts/grants.js.map +1 -0
- package/dist/electron-build/agents/contacts/policy.js +271 -0
- package/dist/electron-build/agents/contacts/policy.js.map +1 -0
- package/dist/electron-build/agents/contacts/preview-types.js +8 -0
- package/dist/electron-build/agents/contacts/preview-types.js.map +1 -0
- package/dist/electron-build/agents/contacts/providers.js +384 -0
- package/dist/electron-build/agents/contacts/providers.js.map +1 -0
- package/dist/electron-build/agents/contacts/store.js +370 -0
- package/dist/electron-build/agents/contacts/store.js.map +1 -0
- package/dist/electron-build/agents/contacts/tools.js +159 -0
- package/dist/electron-build/agents/contacts/tools.js.map +1 -0
- package/dist/electron-build/agents/contacts/types.js +166 -0
- package/dist/electron-build/agents/contacts/types.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 +3335 -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 +291 -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 +58 -27
- package/dist/llm/system-prompt/registry.js +6 -3
- package/dist/security/tool-gate.js +4 -0
- 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/dist/web/mobile-contacts.js +329 -0
- package/dist/web/mobile-core.js +481 -15
- package/dist/web/mobile.html +32 -0
- package/dist/web/mobile.js +139 -0
- package/dist/web/routes-contacts.js +420 -0
- package/dist/web/server.js +5 -0
- package/package.json +1 -1
- package/scripts/build-cli.js +32 -151
- package/scripts/postinstall.js +153 -76
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* contacts/store.ts — 联系方式事实的唯一落盘层 (2026-09-19, Phase 1/4)
|
|
3
|
+
*
|
|
4
|
+
* 目录: ~/.bolloon/contacts/
|
|
5
|
+
* social-identity.json SocialIdentity (DID 主身份 + 已验证 contactId 列表)
|
|
6
|
+
* contacts.json VerifiedContact[] (含 normalizedValue, 只在本层读写)
|
|
7
|
+
* secrets.json Secret Store, **0600**; 记录里只引用 secretRef
|
|
8
|
+
* sent.json SendRecord[] (requestId 去重 + 回信关联)
|
|
9
|
+
* ledger.jsonl 只追加的通信台账 (脱敏, 可回放)
|
|
10
|
+
* outbox/ 本地投递通道 (provider=local-sink) 的真落盘目录
|
|
11
|
+
*
|
|
12
|
+
* 纪律:
|
|
13
|
+
* - 所有写都是 tmp + rename (原子); secrets.json 额外 chmod 0600。
|
|
14
|
+
* - 读失败**不吞成空**: 解析损坏时抛/标记, 由调用方决定, 不许静默当成"没有联系方式"。
|
|
15
|
+
* - 任何对外返回值都先过 `maskContact()` —— 明文只在本层内部流转。
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as fsp from 'fs/promises';
|
|
19
|
+
import * as os from 'os';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { displayFor, newIdentityId, } from './types.js';
|
|
22
|
+
const home = () => process.env.HOME || os.homedir() || '/tmp';
|
|
23
|
+
export function contactsDir(homeDir) {
|
|
24
|
+
return path.join(homeDir || home(), '.bolloon', 'contacts');
|
|
25
|
+
}
|
|
26
|
+
const f = (dir, name) => path.join(dir, name);
|
|
27
|
+
// ── 原子写 + 权限 ───────────────────────────────────────────────────────────
|
|
28
|
+
async function writeJsonAtomic(file, data, mode) {
|
|
29
|
+
// 目录可能还没建 (例如首个动作就是写 secret) → 先建, 否则 rename 必 ENOENT
|
|
30
|
+
await fsp.mkdir(path.dirname(file), { recursive: true });
|
|
31
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now().toString(36)}`;
|
|
32
|
+
await fsp.writeFile(tmp, JSON.stringify(data, null, 2), 'utf8');
|
|
33
|
+
if (mode) {
|
|
34
|
+
try {
|
|
35
|
+
await fsp.chmod(tmp, mode);
|
|
36
|
+
}
|
|
37
|
+
catch { /* 平台不支持就算了, 但要如实记 */ }
|
|
38
|
+
}
|
|
39
|
+
await fsp.rename(tmp, file);
|
|
40
|
+
if (mode) {
|
|
41
|
+
try {
|
|
42
|
+
await fsp.chmod(file, mode);
|
|
43
|
+
}
|
|
44
|
+
catch { /* 同上 */ }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function readJson(file) {
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(await fsp.readFile(file, 'utf8'));
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (err?.code === 'ENOENT')
|
|
53
|
+
return null;
|
|
54
|
+
// 损坏的文件绝不静默当空: 抛出去, 让上层报 degraded
|
|
55
|
+
throw new Error(`联系方式存储损坏 (${file}): ${err?.message || err}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** 任何离开 store 的联系方式都要走这里 (明文 → 脱敏) */
|
|
59
|
+
export function maskContact(c) {
|
|
60
|
+
const { normalizedValue: _drop, consentScope: _scope, secretRef: _ref, ...rest } = c;
|
|
61
|
+
return { ...rest, displayValue: c.displayValue || displayFor(c.kind, c.normalizedValue) };
|
|
62
|
+
}
|
|
63
|
+
export class SecretStore {
|
|
64
|
+
dir;
|
|
65
|
+
constructor(dir) { this.dir = dir; }
|
|
66
|
+
file() { return f(this.dir, 'secrets.json'); }
|
|
67
|
+
async list() {
|
|
68
|
+
const all = (await readJson(this.file())) || [];
|
|
69
|
+
return all.map(({ value: _v, ...rest }) => rest);
|
|
70
|
+
}
|
|
71
|
+
/** 真值只在这里出现; 调用方只能是 provider 适配器 */
|
|
72
|
+
async get(ref) {
|
|
73
|
+
if (!ref)
|
|
74
|
+
return null;
|
|
75
|
+
const all = (await readJson(this.file())) || [];
|
|
76
|
+
return all.find((s) => s.ref === ref) || null;
|
|
77
|
+
}
|
|
78
|
+
async put(ref, provider, value) {
|
|
79
|
+
const all = (await readJson(this.file())) || [];
|
|
80
|
+
const i = all.findIndex((s) => s.ref === ref);
|
|
81
|
+
const entry = { ref, provider, value, createdAt: all[i]?.createdAt || new Date().toISOString(), lastVerifiedAt: all[i]?.lastVerifiedAt };
|
|
82
|
+
if (i >= 0)
|
|
83
|
+
all[i] = entry;
|
|
84
|
+
else
|
|
85
|
+
all.push(entry);
|
|
86
|
+
await writeJsonAtomic(this.file(), all, 0o600);
|
|
87
|
+
}
|
|
88
|
+
async remove(ref) {
|
|
89
|
+
const all = (await readJson(this.file())) || [];
|
|
90
|
+
await writeJsonAtomic(this.file(), all.filter((s) => s.ref !== ref), 0o600);
|
|
91
|
+
}
|
|
92
|
+
async has(ref) { return !!(await this.get(ref)); }
|
|
93
|
+
}
|
|
94
|
+
// ── 主 store ────────────────────────────────────────────────────────────────
|
|
95
|
+
export class ContactsStore {
|
|
96
|
+
dir;
|
|
97
|
+
secrets;
|
|
98
|
+
constructor(homeDir) {
|
|
99
|
+
this.dir = contactsDir(homeDir);
|
|
100
|
+
this.secrets = new SecretStore(this.dir);
|
|
101
|
+
}
|
|
102
|
+
async ensureDirs() {
|
|
103
|
+
await fsp.mkdir(this.dir, { recursive: true });
|
|
104
|
+
await fsp.mkdir(f(this.dir, 'outbox'), { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
// ── 身份 ──────────────────────────────────────────────────────────────────
|
|
107
|
+
async getIdentity(ownerDid) {
|
|
108
|
+
const ids = (await readJson(f(this.dir, 'social-identity.json'))) || [];
|
|
109
|
+
return ids.find((i) => i.ownerDid === ownerDid) || null;
|
|
110
|
+
}
|
|
111
|
+
async ensureIdentity(ownerDid, displayName = '') {
|
|
112
|
+
await this.ensureDirs();
|
|
113
|
+
const file = f(this.dir, 'social-identity.json');
|
|
114
|
+
const ids = (await readJson(file)) || [];
|
|
115
|
+
let id = ids.find((i) => i.ownerDid === ownerDid);
|
|
116
|
+
if (!id) {
|
|
117
|
+
id = {
|
|
118
|
+
identityId: newIdentityId(),
|
|
119
|
+
ownerDid,
|
|
120
|
+
displayName,
|
|
121
|
+
verifiedContacts: [],
|
|
122
|
+
privacyPolicy: {
|
|
123
|
+
plaintextVisibleToAgent: false,
|
|
124
|
+
batchAllowed: false,
|
|
125
|
+
note: '明文联系方式不进 prompt/Run/Git; 外部只看到 已验证/可联系/不可联系/需要重新授权',
|
|
126
|
+
},
|
|
127
|
+
createdAt: new Date().toISOString(),
|
|
128
|
+
updatedAt: new Date().toISOString(),
|
|
129
|
+
};
|
|
130
|
+
ids.push(id);
|
|
131
|
+
}
|
|
132
|
+
await writeJsonAtomic(file, ids);
|
|
133
|
+
return id;
|
|
134
|
+
}
|
|
135
|
+
// ── 联系方式 ──────────────────────────────────────────────────────────────
|
|
136
|
+
async listContacts(opts = {}) {
|
|
137
|
+
const all = (await readJson(f(this.dir, 'contacts.json'))) || [];
|
|
138
|
+
return opts.identityId ? all.filter((c) => c.identityId === opts.identityId) : all;
|
|
139
|
+
}
|
|
140
|
+
async getContact(contactId) {
|
|
141
|
+
return (await this.listContacts()).find((c) => c.contactId === contactId) || null;
|
|
142
|
+
}
|
|
143
|
+
/** 内部用 —— 拿明文值 (只有 provider / 回信校验该调) */
|
|
144
|
+
async getNormalized(contactId) {
|
|
145
|
+
const c = await this.getContact(contactId);
|
|
146
|
+
return c ? c.normalizedValue : null;
|
|
147
|
+
}
|
|
148
|
+
async putContact(c) {
|
|
149
|
+
await this.ensureDirs();
|
|
150
|
+
const file = f(this.dir, 'contacts.json');
|
|
151
|
+
const all = (await readJson(file)) || [];
|
|
152
|
+
const i = all.findIndex((x) => x.contactId === c.contactId);
|
|
153
|
+
c.updatedAt = new Date().toISOString();
|
|
154
|
+
if (i >= 0)
|
|
155
|
+
all[i] = c;
|
|
156
|
+
else
|
|
157
|
+
all.push(c);
|
|
158
|
+
// 2026-09-19: contacts.json 里存 normalizedValue (真发信要用它), 所以按 0600 落盘 ——
|
|
159
|
+
// 明文联系方式不该有"随便能被别人读"的副本; Run/Goal/ledger 里永远只有脱敏值。
|
|
160
|
+
await writeJsonAtomic(file, all, 0o600);
|
|
161
|
+
// 身份里的 verifiedContacts 跟着走
|
|
162
|
+
const sf = f(this.dir, 'social-identity.json');
|
|
163
|
+
const ids = (await readJson(sf)) || [];
|
|
164
|
+
const idIdx = ids.findIndex((x) => x.identityId === c.identityId);
|
|
165
|
+
if (idIdx >= 0) {
|
|
166
|
+
const list = new Set(ids[idIdx].verifiedContacts);
|
|
167
|
+
if (c.verificationStatus === 'verified' && !c.revokedAt)
|
|
168
|
+
list.add(c.contactId);
|
|
169
|
+
else
|
|
170
|
+
list.delete(c.contactId);
|
|
171
|
+
ids[idIdx].verifiedContacts = [...list];
|
|
172
|
+
ids[idIdx].updatedAt = new Date().toISOString();
|
|
173
|
+
await writeJsonAtomic(sf, ids);
|
|
174
|
+
}
|
|
175
|
+
return c;
|
|
176
|
+
}
|
|
177
|
+
/** 按 contactId → DID → 明确名称/别名 匹配 (禁止模糊姓名自动发送) */
|
|
178
|
+
async resolve(opts) {
|
|
179
|
+
const all = (await this.listContacts({ identityId: opts.identityId })).filter((c) => !c.revokedAt);
|
|
180
|
+
if (opts.contactId) {
|
|
181
|
+
const hit = all.find((c) => c.contactId === opts.contactId);
|
|
182
|
+
return { contact: hit || null, by: hit ? 'contactId' : 'none' };
|
|
183
|
+
}
|
|
184
|
+
if (opts.did) {
|
|
185
|
+
const hits = all.filter((c) => c.peerDid && c.peerDid === opts.did);
|
|
186
|
+
if (hits.length === 1)
|
|
187
|
+
return { contact: hits[0], by: 'did' };
|
|
188
|
+
if (hits.length > 1)
|
|
189
|
+
return { contact: null, by: 'none', ambiguous: true };
|
|
190
|
+
}
|
|
191
|
+
if (opts.name) {
|
|
192
|
+
const n = opts.name.trim().toLowerCase();
|
|
193
|
+
const hits = all.filter((c) => (c.aliases || []).some((a) => a.trim().toLowerCase() === n));
|
|
194
|
+
if (hits.length === 1)
|
|
195
|
+
return { contact: hits[0], by: 'name' };
|
|
196
|
+
if (hits.length > 1)
|
|
197
|
+
return { contact: null, by: 'none', ambiguous: true };
|
|
198
|
+
}
|
|
199
|
+
return { contact: null, by: 'none' };
|
|
200
|
+
}
|
|
201
|
+
// ── 发送台账 (去重 + 回信关联) ─────────────────────────────────────────────
|
|
202
|
+
async listSends() {
|
|
203
|
+
return (await readJson(f(this.dir, 'sent.json'))) || [];
|
|
204
|
+
}
|
|
205
|
+
/** 同一 requestId 已发过 → 返回旧记录 (调用方必须拒绝重复发送) */
|
|
206
|
+
async findSend(requestId) {
|
|
207
|
+
return (await this.listSends()).find((s) => s.requestId === requestId) || null;
|
|
208
|
+
}
|
|
209
|
+
async findSendByThread(threadToken) {
|
|
210
|
+
return (await this.listSends()).find((s) => s.threadToken === threadToken) || null;
|
|
211
|
+
}
|
|
212
|
+
async recordSend(rec) {
|
|
213
|
+
await this.ensureDirs();
|
|
214
|
+
const file = f(this.dir, 'sent.json');
|
|
215
|
+
const all = await this.listSends();
|
|
216
|
+
all.push(rec);
|
|
217
|
+
await writeJsonAtomic(file, all.slice(-500));
|
|
218
|
+
}
|
|
219
|
+
async patchSend(requestId, patch) {
|
|
220
|
+
const file = f(this.dir, 'sent.json');
|
|
221
|
+
const all = await this.listSends();
|
|
222
|
+
const i = all.findIndex((s) => s.requestId === requestId);
|
|
223
|
+
if (i < 0)
|
|
224
|
+
return;
|
|
225
|
+
all[i] = { ...all[i], ...patch };
|
|
226
|
+
await writeJsonAtomic(file, all.slice(-500));
|
|
227
|
+
}
|
|
228
|
+
/** 当天该 contact 的发送条数 (速率限制真值) */
|
|
229
|
+
async countSentToday(contactId, now = Date.now()) {
|
|
230
|
+
const day = new Date(now).toISOString().slice(0, 10);
|
|
231
|
+
return (await this.listSends()).filter((s) => s.contactId === contactId && s.sentAt.slice(0, 10) === day && s.status === 'sent').length;
|
|
232
|
+
}
|
|
233
|
+
async countSentForGoal(goalId) {
|
|
234
|
+
return (await this.listSends()).filter((s) => s.goalId === goalId && s.status === 'sent').length;
|
|
235
|
+
}
|
|
236
|
+
async markUsed(contactId) {
|
|
237
|
+
const c = await this.getContact(contactId);
|
|
238
|
+
if (!c)
|
|
239
|
+
return;
|
|
240
|
+
c.lastUsedAt = new Date().toISOString();
|
|
241
|
+
await this.putContact(c);
|
|
242
|
+
}
|
|
243
|
+
// ── 待批准正文 (用户内容, 0600, 发完即删) ───────────────────────────────────
|
|
244
|
+
/** 待批准时把真实正文暂存起来 —— consents.json 里只放脱敏预览 */
|
|
245
|
+
async putPendingBody(requestId, body, subject, exec) {
|
|
246
|
+
const file = path.join(this.dir, 'pending', `${requestId}.json`);
|
|
247
|
+
// 2026-09-19: 执行参数 (是否等回复 / 等多久) 必须和正文一起留下来 ——
|
|
248
|
+
// 否则"批准后执行"会退回默认 48h, 把用户/任务指定的等待窗口丢掉 (真跑抓到过)。
|
|
249
|
+
await writeJsonAtomic(file, {
|
|
250
|
+
requestId, body, subject, replyExpected: exec?.replyExpected, replyWindowMs: exec?.replyWindowMs,
|
|
251
|
+
createdAt: new Date().toISOString(),
|
|
252
|
+
}, 0o600);
|
|
253
|
+
}
|
|
254
|
+
async getPendingBody(requestId) {
|
|
255
|
+
try {
|
|
256
|
+
const raw = JSON.parse(await fsp.readFile(path.join(this.dir, 'pending', `${requestId}.json`), 'utf8'));
|
|
257
|
+
return { body: String(raw?.body || ''), subject: raw?.subject, replyExpected: raw?.replyExpected, replyWindowMs: raw?.replyWindowMs };
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async clearPendingBody(requestId) {
|
|
264
|
+
try {
|
|
265
|
+
await fsp.unlink(path.join(this.dir, 'pending', `${requestId}.json`));
|
|
266
|
+
}
|
|
267
|
+
catch { /* 没有就算了 */ }
|
|
268
|
+
}
|
|
269
|
+
// ── 台账 (只追加) ─────────────────────────────────────────────────────────
|
|
270
|
+
evidenceRefFor(contactId, activity, ts) {
|
|
271
|
+
return `contact:${contactId}@${ts}#${activity}`;
|
|
272
|
+
}
|
|
273
|
+
async appendLedger(entry) {
|
|
274
|
+
await this.ensureDirs();
|
|
275
|
+
const full = {
|
|
276
|
+
...entry,
|
|
277
|
+
detail: String(entry.detail || '').slice(0, 300),
|
|
278
|
+
evidenceRef: entry.evidenceRef || this.evidenceRefFor(entry.contactId || '-', entry.activity, entry.ts),
|
|
279
|
+
};
|
|
280
|
+
await fsp.appendFile(f(this.dir, 'ledger.jsonl'), JSON.stringify(full) + '\n', 'utf8');
|
|
281
|
+
return full;
|
|
282
|
+
}
|
|
283
|
+
async readLedger(opts = {}) {
|
|
284
|
+
try {
|
|
285
|
+
const raw = await fsp.readFile(f(this.dir, 'ledger.jsonl'), 'utf8');
|
|
286
|
+
let rows = raw.split('\n').filter(Boolean).map((l) => { try {
|
|
287
|
+
return JSON.parse(l);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return null;
|
|
291
|
+
} }).filter(Boolean);
|
|
292
|
+
if (opts.contactId)
|
|
293
|
+
rows = rows.filter((r) => r.contactId === opts.contactId);
|
|
294
|
+
if (opts.goalId)
|
|
295
|
+
rows = rows.filter((r) => r.goalId === opts.goalId);
|
|
296
|
+
return opts.limit ? rows.slice(-opts.limit) : rows;
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
if (err?.code === 'ENOENT')
|
|
300
|
+
return [];
|
|
301
|
+
throw err;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/** 单例 (默认 HOME); 测试要隔离时直接 new ContactsStore(tmpHome) */
|
|
306
|
+
let _default = null;
|
|
307
|
+
export function contactsStore(homeDir) {
|
|
308
|
+
if (homeDir)
|
|
309
|
+
return new ContactsStore(homeDir);
|
|
310
|
+
if (!_default)
|
|
311
|
+
_default = new ContactsStore();
|
|
312
|
+
return _default;
|
|
313
|
+
}
|
|
314
|
+
export function resetContactsStore() { _default = null; }
|
|
315
|
+
/** 文件权限自检 (doctor 用): secrets.json 必须 0600 */
|
|
316
|
+
export async function secretsFileMode(homeDir) {
|
|
317
|
+
const p = f(contactsDir(homeDir), 'secrets.json');
|
|
318
|
+
try {
|
|
319
|
+
const st = fs.statSync(p);
|
|
320
|
+
const mode = (st.mode & 0o777).toString(8);
|
|
321
|
+
return { path: p, mode, ok: mode === '600' };
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
return { path: p, mode: null, ok: true }; // 还没有 secret = 不算问题
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* contacts/tools.ts — 暴露给 Agent 的联系工具 (2026-09-19, Phase 8)
|
|
3
|
+
*
|
|
4
|
+
* 设计铁律:
|
|
5
|
+
* - Agent **拿不到**手机号/邮箱原文, 只能拿 `contactId` + 脱敏 displayValue。
|
|
6
|
+
* - Agent **不能**指定任意收件人地址 —— 只能指定已授权 contactId (或已在别名表里的名字)。
|
|
7
|
+
* - 每个工具都经 policy 判定, 返回里带 blockKind / requiresApproval, 不吞掉拒绝原因。
|
|
8
|
+
*
|
|
9
|
+
* 六个工具: contact.list_authorized / preview / request_consent / send / await_reply / revoke
|
|
10
|
+
*/
|
|
11
|
+
export const CONTACT_TOOL_NAMES = [
|
|
12
|
+
'contact.list_authorized',
|
|
13
|
+
'contact.preview',
|
|
14
|
+
'contact.request_consent',
|
|
15
|
+
'contact.send',
|
|
16
|
+
'contact.await_reply',
|
|
17
|
+
'contact.revoke',
|
|
18
|
+
];
|
|
19
|
+
function text(v) { return String(v ?? '').trim(); }
|
|
20
|
+
export function registerContactTools(ctx, chain) {
|
|
21
|
+
const registered = [];
|
|
22
|
+
ctx.tools.set('contact.list_authorized', {
|
|
23
|
+
name: 'contact.list_authorized',
|
|
24
|
+
description: '列出已授权可联系的联系方式 (只返回脱敏值: 联系人不给完整手机号/邮箱)。需要联系某人先调这个; 拿到的 contactId 才能用于发送。',
|
|
25
|
+
parameters: {},
|
|
26
|
+
execute: async () => {
|
|
27
|
+
const list = await chain.listAuthorized();
|
|
28
|
+
return {
|
|
29
|
+
success: true,
|
|
30
|
+
contacts: list,
|
|
31
|
+
channels: chain.channels(),
|
|
32
|
+
note: list.length ? '只能对这里列出的 contactId 发送; 未验证/已撤销的一律发不出去' : '还没有任何已绑定的联系方式 —— 需要用户在 CLI/桌面/手机上先绑定并验证',
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
ctx.tools.set('contact.preview', {
|
|
37
|
+
name: 'contact.preview',
|
|
38
|
+
description: '生成一份可审计的发送预览 (联系人/通道/收件人脱敏/任务/权限/是否需要人工批准), 不发送任何东西。',
|
|
39
|
+
parameters: {
|
|
40
|
+
contactId: '联系人 id (必填, 来自 contact.list_authorized)',
|
|
41
|
+
body: '正文 (必填)',
|
|
42
|
+
subject: '主题 (可选, 邮箱用)',
|
|
43
|
+
goalId: '关联的长期任务 id (可选但强烈建议; 未绑定的任务联系人会被拒绝)',
|
|
44
|
+
},
|
|
45
|
+
execute: async (args) => {
|
|
46
|
+
const contactId = text(args.contactId);
|
|
47
|
+
if (!contactId)
|
|
48
|
+
return { success: false, error: 'contactId 必填 (不允许按姓名直接发送)' };
|
|
49
|
+
const { decision, text: rendered } = await chain.preview({
|
|
50
|
+
contactId, body: text(args.body), subject: text(args.subject) || undefined, goalId: text(args.goalId) || undefined,
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
success: true,
|
|
54
|
+
preview: rendered,
|
|
55
|
+
allowed: decision.allowed,
|
|
56
|
+
blockKind: decision.blockKind,
|
|
57
|
+
reason: decision.reason,
|
|
58
|
+
requiresApproval: decision.requiresApproval,
|
|
59
|
+
reallySent: decision.reallySent,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const sendLike = (name, description) => async (args) => {
|
|
64
|
+
const contactId = text(args.contactId);
|
|
65
|
+
if (!contactId)
|
|
66
|
+
return { success: false, error: 'contactId 必填 (不允许按姓名直接发送; 用 contact.list_authorized 拿 id)' };
|
|
67
|
+
const res = await chain.send({
|
|
68
|
+
contactId,
|
|
69
|
+
goalId: text(args.goalId) || undefined,
|
|
70
|
+
runId: text(args.runId) || undefined,
|
|
71
|
+
taskKind: text(args.taskKind) || undefined,
|
|
72
|
+
subject: text(args.subject) || undefined,
|
|
73
|
+
body: text(args.body),
|
|
74
|
+
requestId: text(args.requestId) || undefined,
|
|
75
|
+
replyExpected: args.replyExpected !== false,
|
|
76
|
+
});
|
|
77
|
+
const ok = res.status === 'sent' || res.status === 'awaiting_reply';
|
|
78
|
+
return {
|
|
79
|
+
success: ok,
|
|
80
|
+
status: res.status,
|
|
81
|
+
reason: res.reason,
|
|
82
|
+
blockKind: res.blockKind,
|
|
83
|
+
requestId: res.requestId,
|
|
84
|
+
consentId: res.consentId,
|
|
85
|
+
preview: res.preview,
|
|
86
|
+
evidenceRef: res.evidenceRef,
|
|
87
|
+
goalStatus: res.goalStatus,
|
|
88
|
+
// 让 Agent 说人话: 被拒/等批准时必须如实转述, 不许假装已发送
|
|
89
|
+
note: res.status === 'awaiting_approval'
|
|
90
|
+
? '已生成待批准请求: 需要用户在 CLI/桌面/手机点批准后才会真正发送 (首次联系/敏感内容/策略要求时必然如此)'
|
|
91
|
+
: res.status === 'denied' ? `被策略拒绝 (${res.blockKind}): ${res.reason}` : undefined,
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
const sendParams = {
|
|
95
|
+
contactId: '联系人 id (必填)',
|
|
96
|
+
body: '正文 (必填)',
|
|
97
|
+
subject: '主题 (可选)',
|
|
98
|
+
goalId: '长期任务 id (任务绑定联系人必须给)',
|
|
99
|
+
runId: '当前 Run id (可选; 通信证据会写进这个 Run)',
|
|
100
|
+
requestId: '幂等 id (可选; 同一个 requestId 绝不会重复发送)',
|
|
101
|
+
replyExpected: '是否等待回复 (默认 true; goalId 存在时会绑定外部等待)',
|
|
102
|
+
};
|
|
103
|
+
ctx.tools.set('contact.send', {
|
|
104
|
+
name: 'contact.send',
|
|
105
|
+
description: '联系一个人 (手机号/邮箱): 经策略判定 —— 首次联系/敏感内容需要用户批准, 批量永远禁止, 未验证/已撤销一律拒绝。发送成功后若等待回复, 任务会进入 awaiting_external。',
|
|
106
|
+
parameters: sendParams,
|
|
107
|
+
execute: sendLike('contact.send', ''),
|
|
108
|
+
});
|
|
109
|
+
ctx.tools.set('contact.request_consent', {
|
|
110
|
+
name: 'contact.request_consent',
|
|
111
|
+
description: '就某次联系向用户请求授权 (不发送): 生成待批准请求 + 可审计预览, 用户批准后才发送。',
|
|
112
|
+
parameters: sendParams,
|
|
113
|
+
execute: sendLike('contact.request_consent', ''),
|
|
114
|
+
});
|
|
115
|
+
ctx.tools.set('contact.await_reply', {
|
|
116
|
+
name: 'contact.await_reply',
|
|
117
|
+
description: '查看某次联系是否在等待回复 / 是否已收到回复 / 是否超时 (只读)。',
|
|
118
|
+
parameters: { requestId: '发送时拿到的 requestId (必填)' },
|
|
119
|
+
execute: async (args) => {
|
|
120
|
+
const requestId = text(args.requestId);
|
|
121
|
+
if (!requestId)
|
|
122
|
+
return { success: false, error: 'requestId 必填' };
|
|
123
|
+
const rec = await chain.store.findSend(requestId);
|
|
124
|
+
if (!rec)
|
|
125
|
+
return { success: false, error: `没有 requestId=${requestId} 的发送记录` };
|
|
126
|
+
const ledger = await chain.store.readLedger({ limit: 200 });
|
|
127
|
+
const mine = ledger.filter((l) => l.detail.includes(requestId) || (l.contactId === rec.contactId && l.goalId === rec.goalId));
|
|
128
|
+
return {
|
|
129
|
+
success: true,
|
|
130
|
+
status: rec.status,
|
|
131
|
+
goalId: rec.goalId,
|
|
132
|
+
sentAt: rec.sentAt,
|
|
133
|
+
replied: mine.some((l) => l.activity === 'contact.reply_received'),
|
|
134
|
+
timedOut: mine.some((l) => l.activity === 'contact.wait_expired'),
|
|
135
|
+
provider: rec.provider,
|
|
136
|
+
evidence: mine.slice(-5).map((l) => ({ activity: l.activity, ts: l.ts, detail: l.detail, evidenceRef: l.evidenceRef })),
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
ctx.tools.set('contact.revoke', {
|
|
141
|
+
name: 'contact.revoke',
|
|
142
|
+
description: '撤销某个联系方式的授权 (用户级动作; 撤销后历史证据保留但后续调用一律拒绝)。',
|
|
143
|
+
parameters: { contactId: '联系人 id (必填)', reason: '撤销原因 (可选)' },
|
|
144
|
+
execute: async (args) => {
|
|
145
|
+
const contactId = text(args.contactId);
|
|
146
|
+
if (!contactId)
|
|
147
|
+
return { success: false, error: 'contactId 必填' };
|
|
148
|
+
const r = await chain.revoke({ contactId, by: 'agent_request', reason: text(args.reason) || undefined });
|
|
149
|
+
return { success: r.ok, error: r.error, affectedGoals: r.affectedGoals, evidenceRef: r.evidenceRef };
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
registered.push(...CONTACT_TOOL_NAMES);
|
|
153
|
+
return registered;
|
|
154
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* contacts/types.ts — 社交身份模型 (2026-09-19, Phase 0/1)
|
|
3
|
+
*
|
|
4
|
+
* 核心定义 (leo 冻结):
|
|
5
|
+
* Bolloon 的社交身份 = **DID 主身份 + 已验证联系方式 + 联系能力 Skill + 调用权限 + 可恢复任务证据**,
|
|
6
|
+
* 不是"公开手机号/邮箱"。外部只看到四类状态: 已验证 / 可联系 / 不可联系 / 需要重新授权。
|
|
7
|
+
*
|
|
8
|
+
* 硬规则 (贯穿本目录所有文件):
|
|
9
|
+
* 1. 明文手机号/邮箱**不进**普通 Run step、不进 prompt、不进 Git; 只有 displayValue(脱敏) 可以。
|
|
10
|
+
* 2. 密钥 (API key / OAuth refresh / SMTP 密码) 只存 Secret Store, 记录里只留 secretRef。
|
|
11
|
+
* 3. Goal/Run 只保存 contactId / provider / 动作 / 状态 / 证据引用。
|
|
12
|
+
* 4. 未验证的联系方式**任何情况下**不能被用于真实发送。
|
|
13
|
+
* 5. 撤销后历史证据保留, 但后续调用一律拒绝。
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_LIMITS = { dailyMax: 5, perTaskMax: 3, requireApprovalEachTime: false };
|
|
16
|
+
// ── 规范化 ──────────────────────────────────────────────────────────────────
|
|
17
|
+
const CC = {
|
|
18
|
+
CN: '86', US: '1', CA: '1', JP: '81', GB: '44', DE: '49', FR: '33', IN: '91', AU: '61', SG: '65', KR: '82', RU: '7',
|
|
19
|
+
};
|
|
20
|
+
export function normalizePhone(input, defaultRegion = '') {
|
|
21
|
+
const raw = String(input || '').trim();
|
|
22
|
+
if (!raw)
|
|
23
|
+
return { ok: false, error: 'empty' };
|
|
24
|
+
const plus = raw.startsWith('+');
|
|
25
|
+
const digits = raw.replace(/[^\d]/g, '');
|
|
26
|
+
if (digits.length < 4)
|
|
27
|
+
return { ok: false, error: 'too_short' };
|
|
28
|
+
let e164;
|
|
29
|
+
if (plus) {
|
|
30
|
+
e164 = `+${digits}`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const cc = CC[(defaultRegion || '').toUpperCase()];
|
|
34
|
+
if (!cc)
|
|
35
|
+
return { ok: false, error: 'region_required' };
|
|
36
|
+
const local = digits.replace(/^0+/, '');
|
|
37
|
+
e164 = `+${cc}${local}`;
|
|
38
|
+
}
|
|
39
|
+
const numDigits = e164.length - 1;
|
|
40
|
+
if (numDigits < 8 || numDigits > 15)
|
|
41
|
+
return { ok: false, error: 'invalid_length' };
|
|
42
|
+
return { ok: true, value: e164 };
|
|
43
|
+
}
|
|
44
|
+
export function normalizeEmail(input) {
|
|
45
|
+
const raw = String(input || '').trim().toLowerCase();
|
|
46
|
+
if (!raw)
|
|
47
|
+
return { ok: false, error: 'empty' };
|
|
48
|
+
if (/\s/.test(raw))
|
|
49
|
+
return { ok: false, error: 'contains_space' };
|
|
50
|
+
const m = raw.match(/^([^@]+)@([^@]+\.[^@.]+)$/);
|
|
51
|
+
if (!m)
|
|
52
|
+
return { ok: false, error: 'invalid_format' };
|
|
53
|
+
if (m[1].length > 64)
|
|
54
|
+
return { ok: false, error: 'local_part_too_long' };
|
|
55
|
+
return { ok: true, value: `${m[1]}@${m[2]}` };
|
|
56
|
+
}
|
|
57
|
+
/** 脱敏展示值 —— 唯一允许出现在 prompt / evidence / Web UI 的形态 */
|
|
58
|
+
export function maskPhone(e164) {
|
|
59
|
+
const digits = e164.replace(/[^\d]/g, '');
|
|
60
|
+
if (digits.length <= 6)
|
|
61
|
+
return `+${'*'.repeat(Math.max(0, digits.length - 2))}${digits.slice(-2)}`;
|
|
62
|
+
return `+${digits.slice(0, 2)}******${digits.slice(-4)}`;
|
|
63
|
+
}
|
|
64
|
+
export function maskEmail(email) {
|
|
65
|
+
const [local, domain] = String(email).split('@');
|
|
66
|
+
if (!domain)
|
|
67
|
+
return '***';
|
|
68
|
+
const head = local.slice(0, 1);
|
|
69
|
+
return `${head}${'*'.repeat(Math.max(1, Math.min(6, local.length - 1)))}@${domain}`;
|
|
70
|
+
}
|
|
71
|
+
export function displayFor(kind, normalized) {
|
|
72
|
+
return kind === 'phone' ? maskPhone(normalized) : maskEmail(normalized);
|
|
73
|
+
}
|
|
74
|
+
/** 内部状态 → 外部四类状态 (Phase 0: 外部只看到这四个) */
|
|
75
|
+
export function externalStatusOf(c) {
|
|
76
|
+
if (c.revokedAt || c.verificationStatus === 'revoked')
|
|
77
|
+
return 'reauth_required';
|
|
78
|
+
if (c.verificationStatus === 'blocked' || c.verificationStatus === 'expired')
|
|
79
|
+
return 'not_contactable';
|
|
80
|
+
if (c.verificationStatus === 'verified') {
|
|
81
|
+
return c.capabilities.includes('send') && c.policy !== 'draft_only' ? 'contactable' : 'verified';
|
|
82
|
+
}
|
|
83
|
+
return 'not_contactable';
|
|
84
|
+
}
|
|
85
|
+
export function scanSensitive(text) {
|
|
86
|
+
const out = [];
|
|
87
|
+
const s = String(text || '');
|
|
88
|
+
const push = (kind, hint) => {
|
|
89
|
+
if (!out.some((f) => f.kind === kind && f.hint === hint))
|
|
90
|
+
out.push({ kind, hint });
|
|
91
|
+
};
|
|
92
|
+
// 卡号: 13-19 位连续数字 (允许空格/横线分隔)
|
|
93
|
+
for (const m of s.matchAll(/\b(?:\d[ -]?){13,19}\b/g)) {
|
|
94
|
+
const digits = m[0].replace(/[^\d]/g, '');
|
|
95
|
+
if (digits.length >= 13 && digits.length <= 19)
|
|
96
|
+
push('card_number', `${digits.slice(0, 4)}…${digits.slice(-4)}`);
|
|
97
|
+
}
|
|
98
|
+
// 中国大陆身份证: 17 位 + 数字/X
|
|
99
|
+
for (const m of s.matchAll(/\b\d{17}[\dXx]\b/g))
|
|
100
|
+
push('id_number_cn', `${m[0].slice(0, 4)}…${m[0].slice(-2)}`);
|
|
101
|
+
// API key / token
|
|
102
|
+
for (const m of s.matchAll(/\b(sk-[A-Za-z0-9]{12,}|AKIA[0-9A-Z]{12,}|ghp_[A-Za-z0-9]{20,}|npm_[A-Za-z0-9]{20,})\b/g)) {
|
|
103
|
+
push('api_key', `${m[0].slice(0, 6)}…`);
|
|
104
|
+
}
|
|
105
|
+
if (/(密码|password|passwd|pwd)\s*[::=]\s*\S+/i.test(s))
|
|
106
|
+
push('password', '疑似密码明文');
|
|
107
|
+
// 一次性验证码: 只在出现"验证码/otp/code"上下文时才算
|
|
108
|
+
if (/(验证码|动态码|one[-\s]?time|otp)\D{0,8}\d{4,8}/i.test(s))
|
|
109
|
+
push('otp_code', '疑似一次性验证码');
|
|
110
|
+
// 银行账号: 10-17 位且上下文含"账号/account"
|
|
111
|
+
if (/(账号|账户|account|iban)\D{0,6}\d{10,17}/i.test(s))
|
|
112
|
+
push('bank_account', '疑似银行账号');
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 永不由联系方式授权放行的内容类别 (2026-09-19, Phase 6):
|
|
117
|
+
* 凭证 / 资金指令 / 合同承诺 —— 即使 full_contact_access 也拒绝, 它们属于另一类高风险能力。
|
|
118
|
+
*/
|
|
119
|
+
export function scanForbidden(text) {
|
|
120
|
+
const s = String(text || '');
|
|
121
|
+
const out = new Set();
|
|
122
|
+
if (/\b(sk-[A-Za-z0-9]{12,}|AKIA[0-9A-Z]{12,}|ghp_[A-Za-z0-9]{20,}|npm_[A-Za-z0-9]{20,})\b/.test(s))
|
|
123
|
+
out.add('api_key');
|
|
124
|
+
if (/(密码|password|passwd|pwd)\s*[::=]\s*\S+/i.test(s))
|
|
125
|
+
out.add('password');
|
|
126
|
+
if (/(账号|账户|account|iban)\D{0,6}\d{10,17}/i.test(s))
|
|
127
|
+
out.add('bank_account');
|
|
128
|
+
if (/(转账|打款|汇款|付款指令|支付授权|remit|wire transfer|pay\s+to|send\s+funds)/i.test(s))
|
|
129
|
+
out.add('payment_instruction');
|
|
130
|
+
if (/(签署合同|签订合同|签合同|同意采购|承诺下单|sign\s+(the\s+)?(contract|agreement)|binding\s+commitment)/i.test(s))
|
|
131
|
+
out.add('contract_commitment');
|
|
132
|
+
return [...out];
|
|
133
|
+
}
|
|
134
|
+
/** 发送前把正文里明显的口令类内容打码 (预览与证据都走这个) */
|
|
135
|
+
export function redactForEvidence(text) {
|
|
136
|
+
let s = String(text || '');
|
|
137
|
+
s = s.replace(/\b\d[ -]?(?:\d[ -]?){12,18}\d\b/g, (m) => `${m.replace(/[^\d]/g, '').slice(0, 4)}…<卡号已打码>`);
|
|
138
|
+
s = s.replace(/\b(sk-|AKIA|ghp_|npm_)[A-Za-z0-9_-]{8,}\b/g, '<密钥已打码>');
|
|
139
|
+
s = s.replace(/\b\d{17}[\dXx]\b/g, '<身份证已打码>');
|
|
140
|
+
return s;
|
|
141
|
+
}
|
|
142
|
+
// ── id 生成 ─────────────────────────────────────────────────────────────────
|
|
143
|
+
const rid = (n = 8) => Math.random().toString(36).slice(2, 2 + n);
|
|
144
|
+
export const newContactId = (kind) => `ct-${kind}-${Date.now().toString(36)}-${rid(4)}`;
|
|
145
|
+
export const newIdentityId = () => `sid-${Date.now().toString(36)}-${rid(4)}`;
|
|
146
|
+
export const newRequestId = () => `creq-${Date.now().toString(36)}-${rid(6)}`;
|
|
147
|
+
export const newThreadToken = () => `thr-${rid(20)}`;
|
|
148
|
+
export const newEventId = () => `cev-${Date.now().toString(36)}-${rid(6)}`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
import * as fsSync from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { currentPackageRoot } from '../utils/version-info.js';
|
|
4
5
|
import { documentReader } from '../documents/reader.js';
|
|
5
6
|
import { p2pNetwork } from '../network/p2p.js';
|
|
6
7
|
import { shellExec } from './shell-tool.js';
|
|
@@ -2453,7 +2454,8 @@ export function registerBuiltinTools(ctx) {
|
|
|
2453
2454
|
try {
|
|
2454
2455
|
// fs 读 manifests/mcp-catalog.json — 构建后 dist/agents/../../manifests = 仓库根/manifests
|
|
2455
2456
|
const { readFileSync } = await import('fs');
|
|
2456
|
-
|
|
2457
|
+
// 2026-09-19: 原为 new URL('../../manifests/...', import.meta.url) —— electron 构建(CommonJS)下 TS1343。
|
|
2458
|
+
const raw = readFileSync(path.join(currentPackageRoot(), 'manifests', 'mcp-catalog.json'), 'utf-8');
|
|
2457
2459
|
const catalog = JSON.parse(raw);
|
|
2458
2460
|
const entries = (catalog?.entries ?? []);
|
|
2459
2461
|
if (entries.length === 0) {
|