@fased/fased 0.1.62 → 0.1.64
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/CHANGELOG.md +32 -0
- package/README.md +38 -30
- package/config/dependency-ownership.json +1 -1
- package/config/signer-policies/README.md +49 -0
- package/config/signer-policies/agent.json.template +32 -0
- package/config/signer-policies/mining.json.template +69 -0
- package/config/signer-policies/network.json.template +5 -0
- package/config/signer-policies/vault.json.template +70 -0
- package/config/signer-protocol-v2.json +76 -0
- package/config/typescript-noemit-baseline.json +680 -0
- package/dist/agents/auth-profiles/store.js +267 -31
- package/dist/agents/bash-tools.exec.js +10 -4
- package/dist/agents/current-model-catalog.js +3 -3
- package/dist/agents/memory-search.js +7 -1
- package/dist/agents/model-catalog-access.js +1 -2
- package/dist/agents/model-catalog-snapshot.js +1 -1
- package/dist/agents/model-catalog-source.js +1 -1
- package/dist/agents/model-metadata.js +1 -1
- package/dist/agents/model-selection.js +2 -28
- package/dist/agents/models-config.providers.js +6 -6
- package/dist/agents/pi-embedded-runner/compact.js +15 -7
- package/dist/agents/pi-embedded-runner/model.js +1 -1
- package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
- package/dist/agents/pi-embedded-runner/run.js +2 -0
- package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
- package/dist/agents/pi-tool-definition-adapter.js +16 -1
- package/dist/agents/pi-tools.js +2 -1
- package/dist/agents/sandbox/config.js +1 -1
- package/dist/agents/sandbox/context.js +27 -2
- package/dist/agents/skills/env-overrides.js +38 -28
- package/dist/agents/skills/trust.js +93 -0
- package/dist/agents/skills/workspace.js +128 -0
- package/dist/agents/skills-clawhub.js +36 -11
- package/dist/agents/skills-marketplace-scan.js +49 -0
- package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
- package/dist/agents/tools/mining-tool.js +1 -1
- package/dist/agents/tools/session-status-tool.js +1 -1
- package/dist/agents/tools/wallet-action-tool.js +172 -36
- package/dist/agents/tools/wallet-skill-policy.js +65 -23
- package/dist/agents/tools/wallet-tool.js +7 -11
- package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
- package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
- package/dist/auto-reply/reply/directive-handling.model.js +2 -1
- package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
- package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
- package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
- package/dist/auto-reply/reply/model-selection.js +7 -4
- package/dist/auto-reply/reply/session-reset-model.js +4 -4
- package/dist/brand.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/channel-web.js +2 -2
- package/dist/cli/gateway-cli/run.js +8 -0
- package/dist/cli/program/command-registry.js +1 -1
- package/dist/cli/program/register.onboard.js +2 -3
- package/dist/cli/program/register.wallet.js +16 -123
- package/dist/cli/providers-cli.js +1 -1
- package/dist/cli/sat-cli.js +129 -2
- package/dist/cli/update-cli/update-command.js +260 -11
- package/dist/commands/auth-choice.apply.api-providers.js +3 -3
- package/dist/commands/doctor-config-flow.js +1 -1
- package/dist/commands/doctor-legacy-config.js +2 -13
- package/dist/commands/model-picker.js +6 -6
- package/dist/commands/models/auth.js +1 -1
- package/dist/commands/onboard-auth.config-gateways.js +1 -1
- package/dist/commands/onboard-auth.credentials.js +32 -8
- package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
- package/dist/commands/onboard-non-interactive/local.js +5 -1
- package/dist/commands/wallet.js +568 -1911
- package/dist/config/config.js +2 -2
- package/dist/config/io.js +64 -2
- package/dist/config/schema.help.js +8 -7
- package/dist/config/schema.labels.js +5 -4
- package/dist/config/zod-schema.agent-runtime.js +1 -0
- package/dist/config/zod-schema.js +5 -0
- package/dist/control-ui/assets/{app-DLil9VO1.js → app-bR-fO5ty.js} +1511 -1555
- package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
- package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
- package/dist/control-ui/assets/{index-DdE_NIXo.js → index-ckCxHwjy.js} +3 -3
- package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
- package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
- package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
- package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
- package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/daemon/systemd-system.js +56 -50
- package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
- package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
- package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
- package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
- package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
- package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
- package/dist/federation/auto-connect.js +98 -8
- package/dist/federation/marketplace-capability-adapter.js +33 -7
- package/dist/federation/marketplace-delivery-outbox.js +196 -0
- package/dist/federation/marketplace-delivery.js +351 -215
- package/dist/federation/marketplace-direct-payment.js +272 -141
- package/dist/federation/marketplace-escrow.js +607 -249
- package/dist/federation/marketplace-settlement-ledger.js +352 -0
- package/dist/federation/offers.js +9 -7
- package/dist/federation/peer-auth-v2.js +529 -0
- package/dist/gateway/a2a-http.js +425 -96
- package/dist/gateway/a2a-settlement.js +259 -153
- package/dist/gateway/a2a-task-store.js +524 -0
- package/dist/gateway/auth.js +38 -2
- package/dist/gateway/config-reload.js +46 -33
- package/dist/gateway/durable-capacity.js +31 -0
- package/dist/gateway/federation-http.js +540 -135
- package/dist/gateway/federation-marketplace-run-store.js +397 -0
- package/dist/gateway/federation-marketplace.js +535 -230
- package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
- package/dist/gateway/security-path.js +1 -1
- package/dist/gateway/server-http.js +1084 -1205
- package/dist/gateway/server-methods/models.js +1 -1
- package/dist/gateway/server-methods/secrets.js +40 -0
- package/dist/gateway/server-methods.js +1 -2
- package/dist/gateway/server-reload-handlers.js +196 -66
- package/dist/gateway/server-runtime-config.js +1 -1
- package/dist/gateway/server-secrets-runtime.js +288 -0
- package/dist/gateway/server.impl.js +73 -42
- package/dist/gateway/sessions-patch.js +3 -5
- package/dist/index.js +4 -2
- package/dist/infra/fasedhub.js +64 -1
- package/dist/infra/local-source-paired-update.js +538 -0
- package/dist/infra/restart.js +41 -10
- package/dist/infra/update-runner.js +96 -0
- package/dist/light-update-status.js +11 -11
- package/dist/memory/backend-config.js +2 -1
- package/dist/memory/session-files.js +16 -2
- package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
- package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
- package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-BYxAt775.js} +27 -27
- package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
- package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
- package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
- package/dist/plugin-sdk/channel-plugin-common.js +4 -4
- package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DIRHG2gJ.js} +1 -1
- package/dist/plugin-sdk/command-status.d.ts +2 -2
- package/dist/plugin-sdk/command-status.js +27 -27
- package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
- package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
- package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
- package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-BOT7kHb6.js} +6779 -3696
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/discord.d.ts +6 -6
- package/dist/plugin-sdk/discord.js +19 -19
- package/dist/plugin-sdk/file-lock.js +35 -4
- package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
- package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
- package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
- package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
- package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
- package/dist/plugin-sdk/index.d.ts +21 -39
- package/dist/plugin-sdk/index.js +29 -29
- package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
- package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
- package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
- package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
- package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
- package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
- package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-BCFDaqJ-.js} +31 -31
- package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
- package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.js} +27 -27
- package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
- package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
- package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
- package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
- package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
- package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
- package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
- package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
- package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
- package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
- package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
- package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
- package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
- package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
- package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
- package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
- package/dist/plugin-sdk/sat-runtime.js +29 -29
- package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
- package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
- package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
- package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
- package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
- package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
- package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
- package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BUTt8cxK.js} +39 -39
- package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
- package/dist/plugin-sdk/slack.d.ts +6 -6
- package/dist/plugin-sdk/slack.js +9 -9
- package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-D0wHVqjt.js} +3 -3
- package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
- package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
- package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-CC_qN4v0.js} +30 -30
- package/dist/plugin-sdk/telegram.d.ts +6 -6
- package/dist/plugin-sdk/telegram.js +8 -8
- package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
- package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
- package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
- package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
- package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
- package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -2
- package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
- package/dist/plugin-sdk/{web-CInY-lCv.js → web-BXsJ1vqe.js} +32 -32
- package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
- package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
- package/dist/plugin-sdk/whatsapp.d.ts +13 -13
- package/dist/plugin-sdk/whatsapp.js +12 -12
- package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
- package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
- package/dist/providers/refresh.js +1 -1
- package/dist/providers/registry.js +1 -1
- package/dist/secrets/apply.js +1 -1
- package/dist/secrets/runtime.js +1 -1
- package/dist/wallet/external-submission-ledger.js +376 -0
- package/dist/wallet/legacy-embedded-keystore.js +40 -0
- package/dist/wallet/local-socket-signer-archive.js +30 -0
- package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
- package/dist/wallet/local-socket-signer-policy.js +166 -0
- package/dist/wallet/local-socket-signer-protocol.js +561 -118
- package/dist/wallet/native-signer-wallet-id.js +25 -0
- package/dist/wallet/providers/alchemy-adapter.js +3 -0
- package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
- package/dist/wallet/providers/turnkey-adapter.js +292 -34
- package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
- package/dist/wallet/signer-network-admin.js +184 -0
- package/dist/wallet/signer-protocol-v2.generated.js +90 -0
- package/dist/wallet/solana-bond-signing.js +157 -69
- package/dist/wallet/solana-reviewed-transaction.js +375 -0
- package/dist/wallet/solana-swap.js +520 -64
- package/dist/wallet/solana-transaction-inspection.js +106 -4
- package/dist/wallet/solana-trigger.js +658 -320
- package/dist/wallet/turnkey-reviewed-state.js +370 -0
- package/dist/wallet/wallet-approval-auth.js +17 -28
- package/dist/wallet/wallet-atomic-state.js +53 -0
- package/dist/wallet/wallet-canary.js +0 -1
- package/dist/wallet/wallet-inbound-events.js +16 -11
- package/dist/wallet/wallet-policy-simulation.js +1 -1
- package/dist/wallet/wallet-policy.js +90 -36
- package/dist/wallet/wallet-provider-capabilities.js +28 -4
- package/dist/wallet/wallet-provider-registry.js +57 -44
- package/dist/wallet/wallet-provider-resolver.js +62 -63
- package/dist/wallet/wallet-runtime-config.js +28 -41
- package/dist/wallet/wallet-secrets-store.js +22 -0
- package/dist/wallet/wallet-send-approvals.js +1891 -589
- package/dist/wallet/wallet-send-execution-ledger.js +292 -0
- package/dist/wallet/wallet-settlement-links.js +14 -13
- package/dist/wallet/wallet-standard-review.js +353 -0
- package/dist/wallet/wallet-status.js +0 -9
- package/dist/wallet/wallet-task-ledger.js +16 -2
- package/dist/web/auto-reply/heartbeat-runner.js +1 -1
- package/dist/web/auto-reply/monitor.js +2 -2
- package/dist/wizard/host-security-capability.js +14 -23
- package/dist/wizard/onboarding.finalize.js +63 -184
- package/dist/wizard/onboarding.host-security.js +117 -1367
- package/dist/wizard/onboarding.js +172 -217
- package/dist/wizard/onboarding.wallet.js +232 -785
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +12 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +12 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +12 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/index.ts +498 -153
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
- package/extensions/sat-mining/src/audit-store.ts +50 -5
- package/extensions/sat-mining/src/claim-service.ts +85 -14
- package/extensions/sat-mining/src/config.ts +9 -0
- package/extensions/sat-mining/src/cycle-progress.ts +16 -8
- package/extensions/sat-mining/src/epoch-service.ts +9 -5
- package/extensions/sat-mining/src/gateway-runner.ts +21 -1
- package/extensions/sat-mining/src/protocol-contract.ts +45 -1
- package/extensions/sat-mining/src/recovery-service.ts +312 -0
- package/extensions/sat-mining/src/round-watcher.ts +391 -81
- package/extensions/sat-mining/src/rpc-read.ts +330 -89
- package/extensions/sat-mining/src/runtime.ts +14 -0
- package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
- package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
- package/extensions/sat-mining/src/solana-submit.ts +1199 -428
- package/extensions/sat-mining/src/submission-ledger.ts +433 -0
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +12 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +12 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +12 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +12 -0
- package/extensions/zalouser/package.json +1 -1
- package/install.sh +4955 -0
- package/package.json +23 -5
- package/scripts/fased-host-updater.mjs +1421 -0
- package/scripts/fased-host-updaterctl.mjs +186 -0
- package/scripts/fased-managed-service.sh +36 -0
- package/scripts/fased-managed-updater.mjs +3065 -156
- package/scripts/fased-signer-enroll-hosting.sh +275 -0
- package/scripts/fased-signer-network-hosting.sh +143 -0
- package/scripts/fased-signer-owner-policy.mjs +1430 -0
- package/scripts/fased-signer-policy-hosting.sh +50 -0
- package/scripts/fased-signer-policy-local.sh +26 -0
- package/scripts/hosted-release-manifest.mjs +185 -0
- package/scripts/install-fased-signerd.sh +183 -108
- package/scripts/install-managed-runtime.mjs +212 -10
- package/scripts/managed-runtime-layout.mjs +75 -3
- package/scripts/migrate-hosted-signer-v2.mjs +58 -0
- package/scripts/start-managed.sh +169 -360
- package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
- package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
- package/dist/wallet/local-socket-signer-broker.js +0 -224
- package/dist/wallet/local-socket-signer-custody.js +0 -42
- package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
- package/dist/wallet/providers/privy-adapter.js +0 -80
- package/dist/wallet/wallet-custody.js +0 -1836
package/dist/cli/sat-cli.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { resolveStateDir } from "../config/paths.js";
|
|
1
2
|
import { theme } from "../terminal/theme.js";
|
|
2
3
|
import { defaultRuntime } from "../runtime.js";
|
|
3
4
|
import { formatCliCommand } from "./command-format.js";
|
|
5
|
+
import { withFileLock } from "../plugin-sdk/file-lock.js";
|
|
6
|
+
import { serializeWalletState, writeWalletStateFileAtomically } from "../wallet/wallet-atomic-state.js";
|
|
4
7
|
import { runCommandWithRuntime } from "./cli-utils.js";
|
|
5
8
|
import { formatHelpExamples } from "./help-format.js";
|
|
6
9
|
import { addGatewayClientOptions, callGatewayFromCli } from "./gateway-rpc.js";
|
|
7
10
|
import { tmpdir } from "node:os";
|
|
8
11
|
import { dirname, join } from "node:path";
|
|
9
12
|
import { appendFile, mkdir, open, readFile, rm, stat } from "node:fs/promises";
|
|
13
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
10
14
|
import { setTimeout } from "node:timers/promises";
|
|
11
15
|
|
|
12
16
|
//#region src/cli/sat-cli.ts
|
|
@@ -14,6 +18,18 @@ const LAMPORTS_PER_SOL = 1000000000n;
|
|
|
14
18
|
const DEFAULT_MAINTAIN_INTERVAL_SECONDS = 300;
|
|
15
19
|
const DEFAULT_MAINTAIN_JITTER_SECONDS = 30;
|
|
16
20
|
const DEFAULT_STALE_LOCK_SECONDS = 900;
|
|
21
|
+
const SAT_MAINTENANCE_IDEMPOTENCY_VERSION = 1;
|
|
22
|
+
const SAT_MAINTENANCE_IDEMPOTENCY_LIMIT = 64;
|
|
23
|
+
const SAT_MAINTENANCE_IDEMPOTENCY_LOCK_OPTIONS = {
|
|
24
|
+
retries: {
|
|
25
|
+
retries: 120,
|
|
26
|
+
factor: 1.15,
|
|
27
|
+
minTimeout: 10,
|
|
28
|
+
maxTimeout: 100,
|
|
29
|
+
randomize: true
|
|
30
|
+
},
|
|
31
|
+
stale: 12e4
|
|
32
|
+
};
|
|
17
33
|
function runSatCommand(action, label) {
|
|
18
34
|
return runCommandWithRuntime(defaultRuntime, action, (err) => {
|
|
19
35
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -113,6 +129,107 @@ function parseOptionalPositiveInteger(raw, label) {
|
|
|
113
129
|
}
|
|
114
130
|
return value;
|
|
115
131
|
}
|
|
132
|
+
function normalizeMaintenanceIdempotencyKey(raw) {
|
|
133
|
+
const value = raw.trim();
|
|
134
|
+
if (!value || value.length > 160 || /[^\x20-\x7e]/u.test(value)) {
|
|
135
|
+
throw new Error("--idempotency-key must contain 1-160 printable characters");
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
function maintenanceParamsDigest(params) {
|
|
140
|
+
const canonical = Object.fromEntries(Object.entries(params).toSorted(([left], [right]) => left.localeCompare(right)));
|
|
141
|
+
return createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
142
|
+
}
|
|
143
|
+
function maintenanceIdempotencyPath() {
|
|
144
|
+
return join(resolveStateDir(process.env), "sat-mining", "maintenance-cli-idempotency.json");
|
|
145
|
+
}
|
|
146
|
+
async function readMaintenanceIdempotencyFile(filePath) {
|
|
147
|
+
try {
|
|
148
|
+
const parsed = JSON.parse(await readFile(filePath, "utf8"));
|
|
149
|
+
if (parsed.version !== SAT_MAINTENANCE_IDEMPOTENCY_VERSION || !parsed.pending || typeof parsed.pending !== "object" || Array.isArray(parsed.pending)) {
|
|
150
|
+
throw new Error(`invalid SAT maintenance idempotency state at ${filePath}`);
|
|
151
|
+
}
|
|
152
|
+
const pending = {};
|
|
153
|
+
for (const [digest, value] of Object.entries(parsed.pending)) {
|
|
154
|
+
if (!/^[0-9a-f]{64}$/u.test(digest) || !value || typeof value.idempotencyKey !== "string" || value.paramsDigest !== digest || typeof value.createdAt !== "string") {
|
|
155
|
+
throw new Error(`invalid SAT maintenance idempotency record ${digest}`);
|
|
156
|
+
}
|
|
157
|
+
pending[digest] = {
|
|
158
|
+
idempotencyKey: normalizeMaintenanceIdempotencyKey(value.idempotencyKey),
|
|
159
|
+
paramsDigest: digest,
|
|
160
|
+
createdAt: value.createdAt
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
version: SAT_MAINTENANCE_IDEMPOTENCY_VERSION,
|
|
165
|
+
pending
|
|
166
|
+
};
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (error.code === "ENOENT") {
|
|
169
|
+
return {
|
|
170
|
+
version: SAT_MAINTENANCE_IDEMPOTENCY_VERSION,
|
|
171
|
+
pending: {}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function trimMaintenanceIdempotencyEntries(pending) {
|
|
178
|
+
return Object.fromEntries(Object.entries(pending).toSorted(([, left], [, right]) => left.createdAt.localeCompare(right.createdAt)).slice(-SAT_MAINTENANCE_IDEMPOTENCY_LIMIT));
|
|
179
|
+
}
|
|
180
|
+
async function claimMaintenanceIdempotency(params, explicitKey) {
|
|
181
|
+
const paramsDigest = maintenanceParamsDigest(params);
|
|
182
|
+
if (explicitKey?.trim()) {
|
|
183
|
+
return {
|
|
184
|
+
idempotencyKey: normalizeMaintenanceIdempotencyKey(explicitKey),
|
|
185
|
+
paramsDigest,
|
|
186
|
+
managed: false
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const filePath = maintenanceIdempotencyPath();
|
|
190
|
+
return await withFileLock(filePath, SAT_MAINTENANCE_IDEMPOTENCY_LOCK_OPTIONS, async () => {
|
|
191
|
+
const state = await readMaintenanceIdempotencyFile(filePath);
|
|
192
|
+
const existing = state.pending[paramsDigest];
|
|
193
|
+
if (existing) {
|
|
194
|
+
return {
|
|
195
|
+
...existing,
|
|
196
|
+
managed: true
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const pending = {
|
|
200
|
+
idempotencyKey: `sat-maintain-${randomUUID()}`,
|
|
201
|
+
paramsDigest,
|
|
202
|
+
createdAt: new Date().toISOString()
|
|
203
|
+
};
|
|
204
|
+
state.pending[paramsDigest] = pending;
|
|
205
|
+
await mkdir(dirname(filePath), {
|
|
206
|
+
recursive: true,
|
|
207
|
+
mode: 448
|
|
208
|
+
});
|
|
209
|
+
writeWalletStateFileAtomically(filePath, serializeWalletState({
|
|
210
|
+
version: SAT_MAINTENANCE_IDEMPOTENCY_VERSION,
|
|
211
|
+
pending: trimMaintenanceIdempotencyEntries(state.pending)
|
|
212
|
+
}));
|
|
213
|
+
return {
|
|
214
|
+
...pending,
|
|
215
|
+
managed: true
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async function completeMaintenanceIdempotency(claim) {
|
|
220
|
+
if (!claim.managed) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const filePath = maintenanceIdempotencyPath();
|
|
224
|
+
await withFileLock(filePath, SAT_MAINTENANCE_IDEMPOTENCY_LOCK_OPTIONS, async () => {
|
|
225
|
+
const state = await readMaintenanceIdempotencyFile(filePath);
|
|
226
|
+
if (state.pending[claim.paramsDigest]?.idempotencyKey !== claim.idempotencyKey) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
delete state.pending[claim.paramsDigest];
|
|
230
|
+
writeWalletStateFileAtomically(filePath, serializeWalletState(state));
|
|
231
|
+
});
|
|
232
|
+
}
|
|
116
233
|
function renderSatResult(result, opts, successText) {
|
|
117
234
|
if (opts.json || successText === undefined) {
|
|
118
235
|
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
@@ -260,7 +377,14 @@ async function withMaintenanceLock(opts, action) {
|
|
|
260
377
|
}
|
|
261
378
|
}
|
|
262
379
|
async function callMaintenancePass(opts) {
|
|
263
|
-
|
|
380
|
+
const params = buildMaintenanceParams(opts);
|
|
381
|
+
const claim = await claimMaintenanceIdempotency(params, opts.idempotencyKey);
|
|
382
|
+
const result = await callGatewayFromCli("sat.runProtocolMaintenanceOnce", opts, {
|
|
383
|
+
...params,
|
|
384
|
+
idempotencyKey: claim.idempotencyKey
|
|
385
|
+
});
|
|
386
|
+
await completeMaintenanceIdempotency(claim);
|
|
387
|
+
return result;
|
|
264
388
|
}
|
|
265
389
|
function summarizeMaintenanceResult(result) {
|
|
266
390
|
if (!result || typeof result !== "object") {
|
|
@@ -291,6 +415,9 @@ function maintenanceDelayMs(intervalSeconds, jitterSeconds) {
|
|
|
291
415
|
return baseMs + Math.floor(Math.random() * (jitterSeconds * 1e3 + 1));
|
|
292
416
|
}
|
|
293
417
|
async function runMaintenanceLoop(opts) {
|
|
418
|
+
if (opts.idempotencyKey?.trim()) {
|
|
419
|
+
throw new Error("--idempotency-key is for one maintenance pass; loop mode manages a durable key per pass");
|
|
420
|
+
}
|
|
294
421
|
const intervalSeconds = parseNonNegativeIntegerNumber(opts.intervalSeconds, "--interval-seconds", DEFAULT_MAINTAIN_INTERVAL_SECONDS);
|
|
295
422
|
const jitterSeconds = parseNonNegativeIntegerNumber(opts.jitterSeconds, "--jitter-seconds", DEFAULT_MAINTAIN_JITTER_SECONDS);
|
|
296
423
|
const maxIterations = parseOptionalPositiveInteger(opts.maxIterations, "--max-iterations");
|
|
@@ -351,7 +478,7 @@ function registerSatCli(program) {
|
|
|
351
478
|
renderSatMainnetSyncResult(result, opts);
|
|
352
479
|
}, "SAT mainnet sync failed");
|
|
353
480
|
});
|
|
354
|
-
addGatewayClientOptions(sat.command("maintain").description("Run one safe SAT protocol maintenance pass: reserve refill, fixed-recipient protocol claims, and bounded cleanup").option("--target-reserve-sol <amount>", "Reserve target in SOL").option("--target-reserve-lamports <amount>", "Reserve target in lamports").option("--min-sol <amount>", "Minimum pending SOL lane to submit").option("--min-sol-lamports <amount>", "Minimum pending SOL lane in lamports").option("--min-sat-raw <amount>", "Minimum pending SAT raw units to submit").option("--loop", "Run continuously with interval, jitter, and a local lock", false).option("--interval-seconds <seconds>", "Loop interval before jitter", `${DEFAULT_MAINTAIN_INTERVAL_SECONDS}`).option("--jitter-seconds <seconds>", "Random extra loop delay", `${DEFAULT_MAINTAIN_JITTER_SECONDS}`).option("--max-iterations <count>", "Stop after N loop passes; useful for tests and smoke runs").option("--cleanup-max-cycles <count>", "Maximum settled cycles to cleanup per maintenance pass").option("--cleanup-budget-ms <ms>", "Cleanup time budget per maintenance pass; remaining cleanup is deferred").option("--cleanup-max-transactions <count>", "Maximum cleanup transactions to submit per maintenance pass").option("--cleanup-batch-mode <mode>", "Cleanup batching mode: off or auto").option("--cleanup-max-batch-instructions <count>", "Maximum cleanup close instructions per batch transaction").option("--cleanup-scan-mode <mode>", "Cleanup discovery mode: recent, scan, or auto").option("--status-mode <mode>", "Response status mode: compact, ui, debug, or none").option("--log-file <path>", "Append JSONL audit records").option("--lock-file <path>", "Local lock file for the loop").option("--stale-lock-seconds <seconds>", "Remove a stale loop lock after this age", `${DEFAULT_STALE_LOCK_SECONDS}`).option("--json", "Output JSON", false)).action(async (opts) => {
|
|
481
|
+
addGatewayClientOptions(sat.command("maintain").description("Run one safe SAT protocol maintenance pass: reserve refill, fixed-recipient protocol claims, and bounded cleanup").option("--target-reserve-sol <amount>", "Reserve target in SOL").option("--target-reserve-lamports <amount>", "Reserve target in lamports").option("--min-sol <amount>", "Minimum pending SOL lane to submit").option("--min-sol-lamports <amount>", "Minimum pending SOL lane in lamports").option("--min-sat-raw <amount>", "Minimum pending SAT raw units to submit").option("--loop", "Run continuously with interval, jitter, and a local lock", false).option("--interval-seconds <seconds>", "Loop interval before jitter", `${DEFAULT_MAINTAIN_INTERVAL_SECONDS}`).option("--jitter-seconds <seconds>", "Random extra loop delay", `${DEFAULT_MAINTAIN_JITTER_SECONDS}`).option("--max-iterations <count>", "Stop after N loop passes; useful for tests and smoke runs").option("--cleanup-max-cycles <count>", "Maximum settled cycles to cleanup per maintenance pass").option("--cleanup-budget-ms <ms>", "Cleanup time budget per maintenance pass; remaining cleanup is deferred").option("--cleanup-max-transactions <count>", "Maximum cleanup transactions to submit per maintenance pass").option("--cleanup-batch-mode <mode>", "Cleanup batching mode: off or auto").option("--cleanup-max-batch-instructions <count>", "Maximum cleanup close instructions per batch transaction").option("--cleanup-scan-mode <mode>", "Cleanup discovery mode: recent, scan, or auto").option("--status-mode <mode>", "Response status mode: compact, ui, debug, or none").option("--idempotency-key <key>", "Retry key for one pass; reuse the same key after an ambiguous result").option("--log-file <path>", "Append JSONL audit records").option("--lock-file <path>", "Local lock file for the loop").option("--stale-lock-seconds <seconds>", "Remove a stale loop lock after this age", `${DEFAULT_STALE_LOCK_SECONDS}`).option("--json", "Output JSON", false)).action(async (opts) => {
|
|
355
482
|
await runSatCommand(async () => {
|
|
356
483
|
if (opts.loop) {
|
|
357
484
|
await runMaintenanceLoop(opts);
|
|
@@ -23,6 +23,7 @@ import "../../daemon-cli.js";
|
|
|
23
23
|
import { installCompletion } from "../completion-cli.js";
|
|
24
24
|
import { readPackageName, readPackageVersion } from "../../infra/package-json.js";
|
|
25
25
|
import { finalizeUpdateTransaction, rollbackUpdateTransaction, runGatewayUpdate } from "../../infra/update-runner.js";
|
|
26
|
+
import { activateLocalSourceSigner, commitLocalSourcePairedUpdate, isLocalSourceSignerConfigured, markLocalSourceAppActive, markLocalSourceGatewayVerified, prepareLocalSourcePairedUpdate, readLocalSourcePairedUpdateJournal, recoverLocalSourcePairedUpdate, rollbackLocalSourcePairedUpdate, verifyLocalSourceSigner } from "../../infra/local-source-paired-update.js";
|
|
26
27
|
import { checkShellCompletionStatus, ensureCompletionCacheExists } from "../../commands/doctor-completion.js";
|
|
27
28
|
import { runPostUpdateDoctorRepair } from "../../commands/doctor-update.js";
|
|
28
29
|
import { doctorCommand } from "../../commands/doctor.js";
|
|
@@ -755,6 +756,7 @@ async function updateCommand(opts) {
|
|
|
755
756
|
const updateInstallKind = switchToGit ? "git" : switchToPackage ? "package" : installKind;
|
|
756
757
|
const defaultChannel = updateInstallKind === "git" ? DEFAULT_GIT_CHANNEL : DEFAULT_PACKAGE_CHANNEL;
|
|
757
758
|
const channel = requestedChannel ?? storedChannel ?? defaultChannel;
|
|
759
|
+
const sourceSignerConfigured = installKind === "git" && await isLocalSourceSignerConfigured(process.env);
|
|
758
760
|
const explicitTag = normalizeTag(opts.tag);
|
|
759
761
|
let tag = explicitTag ?? channelToNpmTag(channel);
|
|
760
762
|
let installTag = tag;
|
|
@@ -808,6 +810,9 @@ async function updateCommand(opts) {
|
|
|
808
810
|
actions.push("Run plugin update sync after core update");
|
|
809
811
|
actions.push("Refresh shell completion cache (if needed)");
|
|
810
812
|
actions.push(shouldRestart ? "Restart gateway service and run doctor checks" : "Skip restart (because --no-restart is set)");
|
|
813
|
+
if (sourceSignerConfigured) {
|
|
814
|
+
actions.push("Snapshot the built source runtime, activate the exact version-matched native signer, and commit both only after Gateway and signer health");
|
|
815
|
+
}
|
|
811
816
|
const notes = [];
|
|
812
817
|
if (opts.tag && updateInstallKind === "git") {
|
|
813
818
|
notes.push("--tag applies to npm installs only; git updates ignore it.");
|
|
@@ -836,6 +841,21 @@ async function updateCommand(opts) {
|
|
|
836
841
|
}, Boolean(opts.json));
|
|
837
842
|
return;
|
|
838
843
|
}
|
|
844
|
+
if (sourceSignerConfigured && switchToPackage) {
|
|
845
|
+
defaultRuntime.error("A source checkout with a Local signer cannot switch install modes inside one update transaction. Omit --channel to perform a tagged source update, or use the verified installer migration procedure.");
|
|
846
|
+
defaultRuntime.exit(1);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
if (sourceSignerConfigured && channel === "dev") {
|
|
850
|
+
defaultRuntime.error("A Local signer can pair only with an exact tagged stable/beta source release; untagged dev commits fail closed.");
|
|
851
|
+
defaultRuntime.exit(1);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
if (sourceSignerConfigured && !shouldRestart) {
|
|
855
|
+
defaultRuntime.error("A source checkout with a Local signer requires Gateway restart and exact health verification; --no-restart is not allowed.");
|
|
856
|
+
defaultRuntime.exit(1);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
839
859
|
if (downgradeRisk && !opts.yes) {
|
|
840
860
|
if (!process.stdin.isTTY || opts.json) {
|
|
841
861
|
defaultRuntime.error(["Downgrade confirmation required.", "Downgrading can break configuration. Re-run in a TTY to confirm."].join("\n"));
|
|
@@ -1010,6 +1030,136 @@ async function updateCommand(opts) {
|
|
|
1010
1030
|
}
|
|
1011
1031
|
} catch {}
|
|
1012
1032
|
}
|
|
1033
|
+
if (sourceSignerConfigured && !serviceLoaded) {
|
|
1034
|
+
try {
|
|
1035
|
+
await refreshGatewayServiceEnv({
|
|
1036
|
+
root,
|
|
1037
|
+
jsonMode: Boolean(opts.json)
|
|
1038
|
+
});
|
|
1039
|
+
serviceLoaded = await serviceTarget.service.isLoaded({ env: process.env });
|
|
1040
|
+
if (!serviceLoaded) {
|
|
1041
|
+
throw new Error("the Local Gateway service is still not loaded");
|
|
1042
|
+
}
|
|
1043
|
+
if (serviceTarget.scope === "platform") {
|
|
1044
|
+
restartScriptPath = await prepareRestartScript(process.env);
|
|
1045
|
+
}
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
stop();
|
|
1048
|
+
defaultRuntime.error(`A paired source app/signer update requires a managed Local Gateway service: ${String(error)}. Run ${formatCliCommand("fased gateway install --force")}, then retry.`);
|
|
1049
|
+
defaultRuntime.exit(1);
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
const gatewayPort = resolveGatewayPort(configSnapshot.valid ? configSnapshot.config : undefined);
|
|
1054
|
+
const gatewayConfig = configSnapshot.valid ? configSnapshot.config.gateway : undefined;
|
|
1055
|
+
const tlsRuntime = await loadGatewayTlsRuntime(gatewayConfig?.tls);
|
|
1056
|
+
const restartRpc = {
|
|
1057
|
+
url: `${tlsRuntime.enabled ? "wss" : "ws"}://127.0.0.1:${gatewayPort}`,
|
|
1058
|
+
token: gatewayConfig?.auth?.token,
|
|
1059
|
+
password: gatewayConfig?.auth?.password,
|
|
1060
|
+
tlsFingerprint: tlsRuntime.enabled ? tlsRuntime.fingerprintSha256 : undefined,
|
|
1061
|
+
timeoutMs: 1500
|
|
1062
|
+
};
|
|
1063
|
+
const restoreSourcePairAfterFailure = async (journal) => {
|
|
1064
|
+
await rollbackLocalSourcePairedUpdate({
|
|
1065
|
+
journal,
|
|
1066
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1067
|
+
env: process.env
|
|
1068
|
+
});
|
|
1069
|
+
if (!serviceLoaded) {
|
|
1070
|
+
return true;
|
|
1071
|
+
}
|
|
1072
|
+
const rollbackRestartScript = serviceTarget.scope === "platform" ? await prepareRestartScript(process.env) : null;
|
|
1073
|
+
const restored = await maybeRestartService({
|
|
1074
|
+
shouldRestart: true,
|
|
1075
|
+
result: {
|
|
1076
|
+
status: "ok",
|
|
1077
|
+
mode: "git",
|
|
1078
|
+
root: journal.sourceRoot,
|
|
1079
|
+
after: { version: journal.previous.version },
|
|
1080
|
+
steps: [],
|
|
1081
|
+
durationMs: 0
|
|
1082
|
+
},
|
|
1083
|
+
opts,
|
|
1084
|
+
refreshServiceEnv: true,
|
|
1085
|
+
gatewayPort,
|
|
1086
|
+
restartScriptPath: rollbackRestartScript,
|
|
1087
|
+
serviceTarget,
|
|
1088
|
+
serviceLoaded,
|
|
1089
|
+
expectedVersion: journal.previous.version,
|
|
1090
|
+
rpc: restartRpc
|
|
1091
|
+
});
|
|
1092
|
+
return restored.healthy;
|
|
1093
|
+
};
|
|
1094
|
+
let interruptedSourcePair = null;
|
|
1095
|
+
if (installKind === "git") {
|
|
1096
|
+
try {
|
|
1097
|
+
interruptedSourcePair = await readLocalSourcePairedUpdateJournal(process.env);
|
|
1098
|
+
} catch (error) {
|
|
1099
|
+
stop();
|
|
1100
|
+
defaultRuntime.error(`Local source transaction journal is invalid: ${String(error)}`);
|
|
1101
|
+
defaultRuntime.exit(1);
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
if (interruptedSourcePair) {
|
|
1106
|
+
try {
|
|
1107
|
+
const recovery = await recoverLocalSourcePairedUpdate({
|
|
1108
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1109
|
+
env: process.env
|
|
1110
|
+
});
|
|
1111
|
+
if (recovery === "rolled-back" && serviceLoaded) {
|
|
1112
|
+
const restored = await maybeRestartService({
|
|
1113
|
+
shouldRestart: true,
|
|
1114
|
+
result: {
|
|
1115
|
+
status: "ok",
|
|
1116
|
+
mode: "git",
|
|
1117
|
+
root: interruptedSourcePair.sourceRoot,
|
|
1118
|
+
after: { version: interruptedSourcePair.previous.version },
|
|
1119
|
+
steps: [],
|
|
1120
|
+
durationMs: 0
|
|
1121
|
+
},
|
|
1122
|
+
opts,
|
|
1123
|
+
refreshServiceEnv: true,
|
|
1124
|
+
gatewayPort,
|
|
1125
|
+
restartScriptPath,
|
|
1126
|
+
serviceTarget,
|
|
1127
|
+
serviceLoaded,
|
|
1128
|
+
expectedVersion: interruptedSourcePair.previous.version,
|
|
1129
|
+
rpc: restartRpc
|
|
1130
|
+
});
|
|
1131
|
+
if (!restored.healthy) {
|
|
1132
|
+
throw new Error("the previous Gateway did not become healthy after source recovery");
|
|
1133
|
+
}
|
|
1134
|
+
if (serviceTarget.scope === "platform") {
|
|
1135
|
+
restartScriptPath = await prepareRestartScript(process.env);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (!opts.json) {
|
|
1139
|
+
defaultRuntime.log(theme.muted(recovery === "committed" ? "Completed the previously verified Local source app/signer commit." : "Recovered the interrupted Local source app/signer transaction."));
|
|
1140
|
+
}
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
stop();
|
|
1143
|
+
defaultRuntime.error(`Local source app/signer recovery failed: ${String(error)}`);
|
|
1144
|
+
defaultRuntime.exit(1);
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
let sourcePair = null;
|
|
1149
|
+
if (sourceSignerConfigured) {
|
|
1150
|
+
try {
|
|
1151
|
+
sourcePair = await prepareLocalSourcePairedUpdate({
|
|
1152
|
+
sourceRoot: root,
|
|
1153
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1154
|
+
env: process.env
|
|
1155
|
+
});
|
|
1156
|
+
} catch (error) {
|
|
1157
|
+
stop();
|
|
1158
|
+
defaultRuntime.error(`Could not prepare Local source rollback: ${String(error)}`);
|
|
1159
|
+
defaultRuntime.exit(1);
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1013
1163
|
const result = switchToPackage ? await runPackageInstallUpdate({
|
|
1014
1164
|
root,
|
|
1015
1165
|
installKind,
|
|
@@ -1030,6 +1180,55 @@ async function updateCommand(opts) {
|
|
|
1030
1180
|
opts,
|
|
1031
1181
|
stop
|
|
1032
1182
|
});
|
|
1183
|
+
if (sourcePair && result.status === "ok") {
|
|
1184
|
+
try {
|
|
1185
|
+
if (!result.after?.sha || !result.after.version) {
|
|
1186
|
+
throw new Error("source update did not report an exact target Git SHA and version");
|
|
1187
|
+
}
|
|
1188
|
+
sourcePair = await markLocalSourceAppActive({
|
|
1189
|
+
journal: sourcePair,
|
|
1190
|
+
targetSha: result.after.sha,
|
|
1191
|
+
targetVersion: result.after.version,
|
|
1192
|
+
env: process.env
|
|
1193
|
+
});
|
|
1194
|
+
sourcePair = await activateLocalSourceSigner({
|
|
1195
|
+
journal: sourcePair,
|
|
1196
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1197
|
+
env: process.env
|
|
1198
|
+
});
|
|
1199
|
+
} catch (error) {
|
|
1200
|
+
try {
|
|
1201
|
+
await rollbackLocalSourcePairedUpdate({
|
|
1202
|
+
journal: sourcePair,
|
|
1203
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1204
|
+
env: process.env
|
|
1205
|
+
});
|
|
1206
|
+
} catch (rollbackError) {
|
|
1207
|
+
stop();
|
|
1208
|
+
defaultRuntime.error(`Local source signer activation failed and rollback is incomplete: ${String(error)}; ${String(rollbackError)}`);
|
|
1209
|
+
defaultRuntime.exit(1);
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
stop();
|
|
1213
|
+
defaultRuntime.error(`Local source update restored the previous app and signer: ${String(error)}`);
|
|
1214
|
+
defaultRuntime.exit(1);
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
} else if (sourcePair) {
|
|
1218
|
+
try {
|
|
1219
|
+
await rollbackLocalSourcePairedUpdate({
|
|
1220
|
+
journal: sourcePair,
|
|
1221
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1222
|
+
env: process.env
|
|
1223
|
+
});
|
|
1224
|
+
} catch (error) {
|
|
1225
|
+
stop();
|
|
1226
|
+
defaultRuntime.error(`Source update failed and exact rollback is incomplete: ${String(error)}`);
|
|
1227
|
+
defaultRuntime.exit(1);
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
sourcePair = null;
|
|
1231
|
+
}
|
|
1033
1232
|
stop();
|
|
1034
1233
|
printResult(result, {
|
|
1035
1234
|
...opts,
|
|
@@ -1050,16 +1249,6 @@ async function updateCommand(opts) {
|
|
|
1050
1249
|
defaultRuntime.exit(0);
|
|
1051
1250
|
return;
|
|
1052
1251
|
}
|
|
1053
|
-
const gatewayPort = resolveGatewayPort(configSnapshot.valid ? configSnapshot.config : undefined);
|
|
1054
|
-
const gatewayConfig = configSnapshot.valid ? configSnapshot.config.gateway : undefined;
|
|
1055
|
-
const tlsRuntime = await loadGatewayTlsRuntime(gatewayConfig?.tls);
|
|
1056
|
-
const restartRpc = {
|
|
1057
|
-
url: `${tlsRuntime.enabled ? "wss" : "ws"}://127.0.0.1:${gatewayPort}`,
|
|
1058
|
-
token: gatewayConfig?.auth?.token,
|
|
1059
|
-
password: gatewayConfig?.auth?.password,
|
|
1060
|
-
tlsFingerprint: tlsRuntime.enabled ? tlsRuntime.fingerprintSha256 : undefined,
|
|
1061
|
-
timeoutMs: 1500
|
|
1062
|
-
};
|
|
1063
1252
|
const restartResult = await maybeRestartService({
|
|
1064
1253
|
shouldRestart,
|
|
1065
1254
|
result,
|
|
@@ -1073,7 +1262,19 @@ async function updateCommand(opts) {
|
|
|
1073
1262
|
rpc: restartRpc
|
|
1074
1263
|
});
|
|
1075
1264
|
if (!restartResult.healthy) {
|
|
1076
|
-
if (
|
|
1265
|
+
if (sourcePair) {
|
|
1266
|
+
if (!opts.json) {
|
|
1267
|
+
defaultRuntime.log(theme.warn("Gateway verification failed; restoring the exact source app and signer."));
|
|
1268
|
+
}
|
|
1269
|
+
try {
|
|
1270
|
+
const restored = await restoreSourcePairAfterFailure(sourcePair);
|
|
1271
|
+
if (!restored) {
|
|
1272
|
+
defaultRuntime.error("Previous source Gateway was restored, but it is not healthy.");
|
|
1273
|
+
}
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
defaultRuntime.error(`Automatic source app/signer rollback failed: ${String(error)}`);
|
|
1276
|
+
}
|
|
1277
|
+
} else if (result.transaction) {
|
|
1077
1278
|
if (!opts.json) {
|
|
1078
1279
|
defaultRuntime.log(theme.warn("Gateway verification failed; restoring the previous runtime."));
|
|
1079
1280
|
}
|
|
@@ -1098,6 +1299,54 @@ async function updateCommand(opts) {
|
|
|
1098
1299
|
defaultRuntime.exit(1);
|
|
1099
1300
|
return;
|
|
1100
1301
|
}
|
|
1302
|
+
if (sourcePair) {
|
|
1303
|
+
try {
|
|
1304
|
+
await verifyLocalSourceSigner({
|
|
1305
|
+
journal: sourcePair,
|
|
1306
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1307
|
+
env: process.env
|
|
1308
|
+
});
|
|
1309
|
+
} catch (error) {
|
|
1310
|
+
try {
|
|
1311
|
+
const restored = await restoreSourcePairAfterFailure(sourcePair);
|
|
1312
|
+
if (!restored) {
|
|
1313
|
+
throw new Error("the previous source Gateway did not become healthy", { cause: error });
|
|
1314
|
+
}
|
|
1315
|
+
} catch (rollbackError) {
|
|
1316
|
+
defaultRuntime.error(`Signer verification failed and exact source rollback is incomplete: ${String(error)}; ${String(rollbackError)}`);
|
|
1317
|
+
defaultRuntime.exit(1);
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
defaultRuntime.error(`Signer verification failed; restored the previous source app and signer: ${String(error)}`);
|
|
1321
|
+
defaultRuntime.exit(1);
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
try {
|
|
1325
|
+
sourcePair = await markLocalSourceGatewayVerified(sourcePair, process.env);
|
|
1326
|
+
} catch (error) {
|
|
1327
|
+
try {
|
|
1328
|
+
await restoreSourcePairAfterFailure(sourcePair);
|
|
1329
|
+
} catch (rollbackError) {
|
|
1330
|
+
defaultRuntime.error(`Could not record paired health and rollback is incomplete: ${String(error)}; ${String(rollbackError)}`);
|
|
1331
|
+
defaultRuntime.exit(1);
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
defaultRuntime.error(`Could not durably record paired health: ${String(error)}`);
|
|
1335
|
+
defaultRuntime.exit(1);
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
try {
|
|
1339
|
+
await commitLocalSourcePairedUpdate({
|
|
1340
|
+
journal: sourcePair,
|
|
1341
|
+
timeoutMs: timeoutMs ?? 20 * 6e4,
|
|
1342
|
+
env: process.env
|
|
1343
|
+
});
|
|
1344
|
+
} catch (error) {
|
|
1345
|
+
defaultRuntime.error(`The source Gateway and signer passed exact health, but commit cleanup is pending: ${String(error)}. Re-run fased update to finish forward recovery; do not downgrade manually.`);
|
|
1346
|
+
defaultRuntime.exit(1);
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1101
1350
|
const lifecycleTimings = [...restartResult.timings];
|
|
1102
1351
|
await measureUpdateStage(lifecycleTimings, "transaction cleanup", () => finalizeUpdateTransaction(result.transaction));
|
|
1103
1352
|
const pluginResult = await measureUpdateStage(lifecycleTimings, "plugin updates", () => updatePluginsAfterCoreUpdate({
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { ensureAuthProfileStore } from "../agents/auth-profiles/store.js";
|
|
2
|
+
import { resolveAuthProfileOrder } from "../agents/auth-profiles/order.js";
|
|
3
|
+
import "../agents/auth-profiles.js";
|
|
1
4
|
import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF } from "../providers/cloudflare-ai-gateway-shared.js";
|
|
2
5
|
import { SYNTHETIC_DEFAULT_MODEL_REF } from "../providers/synthetic-models.js";
|
|
3
6
|
import { TOGETHER_DEFAULT_MODEL_REF } from "../providers/together-models.js";
|
|
4
7
|
import { VENICE_DEFAULT_MODEL_REF } from "../providers/venice-models.js";
|
|
5
8
|
import { VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF } from "../providers/vercel-ai-gateway-models.js";
|
|
6
|
-
import { ensureAuthProfileStore } from "../agents/auth-profiles/store.js";
|
|
7
|
-
import { resolveAuthProfileOrder } from "../agents/auth-profiles/order.js";
|
|
8
|
-
import "../agents/auth-profiles.js";
|
|
9
9
|
import { CHUTES_DEFAULT_MODEL_REF } from "../agents/chutes-models.js";
|
|
10
10
|
import { QWEN_CODING_PLAN_DEFAULT_MODEL_REF, QWEN_DEFAULT_MODEL_REF } from "../agents/models-config.providers.js";
|
|
11
11
|
import { normalizeApiKeyInput, validateApiKeyInput } from "./auth-choice.api-key.js";
|
|
@@ -14,12 +14,12 @@ import "../config/config.js";
|
|
|
14
14
|
import { listTelegramAccountIds, resolveTelegramAccount } from "../telegram/accounts.js";
|
|
15
15
|
import "../channels/registry.js";
|
|
16
16
|
import { readChannelAllowFromStore } from "../pairing/pairing-store.js";
|
|
17
|
-
import { readWalletApprovalAuthSnapshot } from "../wallet/wallet-approval-auth.js";
|
|
18
17
|
import { listInterpreterLikeSafeBins, resolveMergedSafeBinProfileFixtures } from "../infra/exec-safe-bin-runtime-policy.js";
|
|
19
18
|
import { applyPluginAutoEnable } from "../config/plugin-auto-enable.js";
|
|
20
19
|
import { isNumericTelegramUserId, normalizeTelegramAllowFromEntry } from "../channels/telegram/allow-from.js";
|
|
21
20
|
import { collectProviderDangerousNameMatchingScopes } from "../config/dangerous-name-matching.js";
|
|
22
21
|
import { isDiscordMutableAllowEntry, isGoogleChatMutableAllowEntry, isIrcMutableAllowEntry, isMSTeamsMutableAllowEntry, isMattermostMutableAllowEntry, isSlackMutableAllowEntry } from "../security/mutable-allowlist-detectors.js";
|
|
22
|
+
import { readWalletApprovalAuthSnapshot } from "../wallet/wallet-approval-auth.js";
|
|
23
23
|
import { fetchTelegramChatId } from "../channels/telegram/api.js";
|
|
24
24
|
import { note } from "../terminal/note.js";
|
|
25
25
|
import { normalizeLegacyConfigValues } from "./doctor-legacy-config.js";
|
|
@@ -329,25 +329,14 @@ function normalizeLegacyConfigValues(cfg) {
|
|
|
329
329
|
normalizeProvider("discord");
|
|
330
330
|
const rawWalletProviderId = String(cfg.wallet?.provider?.id ?? "").trim();
|
|
331
331
|
const allowedProviderIds = new Set([
|
|
332
|
-
"embedded-keystore",
|
|
333
332
|
"local-socket-signer",
|
|
334
333
|
"alchemy",
|
|
335
334
|
"turnkey",
|
|
335
|
+
"wallet-standard",
|
|
336
336
|
"privy"
|
|
337
337
|
]);
|
|
338
338
|
if (rawWalletProviderId && !allowedProviderIds.has(rawWalletProviderId)) {
|
|
339
|
-
|
|
340
|
-
next = {
|
|
341
|
-
...next,
|
|
342
|
-
wallet: {
|
|
343
|
-
...next.wallet,
|
|
344
|
-
provider: {
|
|
345
|
-
...next.wallet?.provider,
|
|
346
|
-
id: mappedProviderId
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
changes.push("Normalized unsupported wallet.provider.id to embedded-keystore.");
|
|
339
|
+
changes.push(`Wallet provider ${rawWalletProviderId} is unsupported and was left unchanged for explicit operator repair.`);
|
|
351
340
|
}
|
|
352
341
|
const legacyAckReaction = cfg.messages?.ackReaction?.trim();
|
|
353
342
|
const hasWhatsAppConfig = cfg.channels?.whatsapp !== undefined;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { resolveAgentModelPrimaryValue } from "../config/model-input.js";
|
|
2
|
+
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
|
3
|
+
import { ensureAuthProfileStore } from "../agents/auth-profiles/store.js";
|
|
4
|
+
import { listProfilesForProvider } from "../agents/auth-profiles/profiles.js";
|
|
5
|
+
import "../agents/auth-profiles.js";
|
|
2
6
|
import { CLOUDFLARE_AI_GATEWAY_MODEL_REFS } from "../providers/cloudflare-ai-gateway-shared.js";
|
|
3
7
|
import { HUGGINGFACE_MODEL_REFS } from "../providers/huggingface-models.js";
|
|
4
8
|
import { OPENCODE_ZEN_MODEL_REFS } from "../providers/opencode-zen-shared.js";
|
|
@@ -7,10 +11,6 @@ import { VENICE_MODEL_REFS } from "../providers/venice-models.js";
|
|
|
7
11
|
import { VERCEL_AI_GATEWAY_MODEL_REFS } from "../providers/vercel-ai-gateway-models.js";
|
|
8
12
|
import { LITELLM_MODEL_REFS } from "../providers/litellm-models.js";
|
|
9
13
|
import { BYTEPLUS_CODING_MODEL_REFS, BYTEPLUS_MODEL_REFS, COPILOT_PROXY_MODEL_REFS, GITHUB_COPILOT_MODEL_REFS, GOOGLE_API_MODEL_REFS, GOOGLE_GEMINI_CLI_MODEL_REFS, MISTRAL_MODEL_REFS, OPENAI_API_MODEL_REFS, OPENAI_SIGN_IN_MODEL_REFS, OPENROUTER_MODEL_REFS, QIANFAN_MODEL_REFS, SYNTHETIC_MODEL_REFS, VOLCENGINE_CODING_MODEL_REFS, VOLCENGINE_MODEL_REFS, XAI_MODEL_REFS, XIAOMI_MODEL_REFS, ZAI_MODEL_REFS, isStandardProviderCatalogEntry, isStandardProviderModelRef } from "../providers/registry.js";
|
|
10
|
-
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
|
11
|
-
import { ensureAuthProfileStore } from "../agents/auth-profiles/store.js";
|
|
12
|
-
import { listProfilesForProvider } from "../agents/auth-profiles/profiles.js";
|
|
13
|
-
import "../agents/auth-profiles.js";
|
|
14
14
|
import { getCustomProviderApiKey, resolveEnvApiKey } from "../agents/model-auth.js";
|
|
15
15
|
import { buildAllowedModelSet, buildModelAliasIndex, modelKey, normalizeProviderId, resolveConfiguredModelRef } from "../agents/model-selection.js";
|
|
16
16
|
import { formatModelFeatureList } from "../agents/model-metadata.js";
|
|
@@ -284,8 +284,8 @@ async function promptDefaultModel(params) {
|
|
|
284
284
|
defaultProvider: DEFAULT_PROVIDER,
|
|
285
285
|
store: ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false })
|
|
286
286
|
}) : null;
|
|
287
|
-
if (scoped
|
|
288
|
-
models = scoped.
|
|
287
|
+
if (scoped) {
|
|
288
|
+
models = scoped.allowAny ? scoped.usableCatalog : scoped.allowedCatalog;
|
|
289
289
|
} else {
|
|
290
290
|
const { allowedCatalog } = buildAllowedModelSet({
|
|
291
291
|
cfg,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
|
|
2
2
|
import { resolveAgentDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
|
3
|
-
import { ANTHROPIC_PROVIDER_MANIFEST } from "../../providers/registry.js";
|
|
4
3
|
import { formatCliCommand } from "../../cli/command-format.js";
|
|
5
4
|
import { upsertAuthProfile } from "../../agents/auth-profiles/profiles.js";
|
|
6
5
|
import { parseDurationMs } from "../../cli/parse-duration.js";
|
|
7
6
|
import "../../agents/auth-profiles.js";
|
|
7
|
+
import { ANTHROPIC_PROVIDER_MANIFEST } from "../../providers/registry.js";
|
|
8
8
|
import { normalizeProviderId } from "../../agents/model-selection.js";
|
|
9
9
|
import { stylePromptHint, stylePromptMessage } from "../../terminal/prompt-style.js";
|
|
10
10
|
import { openUrl } from "../onboard-helpers.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, CLOUDFLARE_AI_GATEWAY_MODEL_CATALOG, buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl } from "../providers/cloudflare-ai-gateway-shared.js";
|
|
2
|
-
import { VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF } from "../providers/vercel-ai-gateway-models.js";
|
|
3
2
|
import "../agents/cloudflare-ai-gateway.js";
|
|
3
|
+
import { VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF } from "../providers/vercel-ai-gateway-models.js";
|
|
4
4
|
import { applyAgentDefaultModelPrimary, applyProviderConfigWithDefaultModels } from "./onboard-auth.config-shared.js";
|
|
5
5
|
import "./onboard-auth.credentials.js";
|
|
6
6
|
|