@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/gateway/a2a-http.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { loadConfig } from "../config/io.js";
|
|
2
2
|
import "../config/config.js";
|
|
3
|
+
import { resolveWalletRuntimeConfig } from "../wallet/wallet-runtime-config.js";
|
|
4
|
+
import { readWalletProviderRegistry, resolveWalletUserRole } from "../wallet/wallet-provider-registry.js";
|
|
3
5
|
import { buildPublishedFederationOffers } from "../federation/offers.js";
|
|
4
6
|
import { normalizeHandle, resolveFederationBaseUrl, resolveFederationHandle } from "../federation/runtime.js";
|
|
7
|
+
import { createOrExecuteWalletSend, getWalletSendApprovalRequest } from "../wallet/wallet-send-approvals.js";
|
|
8
|
+
import { FEDERATION_A2A_RPC_PATH, FEDERATION_PEER_HEADERS, authorizeFederationPeerRequestV2 } from "../federation/peer-auth-v2.js";
|
|
5
9
|
import { orchestrateA2aTaskSettlement } from "./a2a-settlement.js";
|
|
6
|
-
import {
|
|
10
|
+
import { authorizeDurableA2aTask, claimDurableA2aPaymentChallenge, claimDurableA2aTaskExecution, issueDurableA2aPaymentChallenge, readDurableA2aPaymentChallenge, readDurableA2aTask, reserveDurableA2aTask, updateDurableA2aTask } from "./a2a-task-store.js";
|
|
11
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
7
12
|
|
|
8
13
|
//#region src/gateway/a2a-http.ts
|
|
9
14
|
const OFFER_SCHEMA_ID = "https://schemas.fased.ai/fased-agent-offer-v0.json";
|
|
@@ -105,18 +110,15 @@ async function readJsonBody(req, maxBytes) {
|
|
|
105
110
|
});
|
|
106
111
|
});
|
|
107
112
|
}
|
|
108
|
-
function extractSenderHandle(req, params, domain) {
|
|
109
|
-
const fromHeader = typeof req.headers["x-fased-sender-handle"] === "string" ? req.headers["x-fased-sender-handle"] : "";
|
|
110
|
-
const fromParams = typeof params?.senderHandle === "string" ? params.senderHandle : isRecord(params?.sender) && typeof params.sender.handle === "string" ? params.sender.handle : "";
|
|
111
|
-
const handle = fromHeader || fromParams;
|
|
112
|
-
return normalizeHandle(handle, domain);
|
|
113
|
-
}
|
|
114
113
|
function taskHasPaidReferences(task) {
|
|
115
114
|
if (!isRecord(task)) {
|
|
116
115
|
return false;
|
|
117
116
|
}
|
|
118
117
|
return task.invoice !== undefined || task.invoiceRef !== undefined || task.receipt !== undefined || task.receiptRef !== undefined;
|
|
119
118
|
}
|
|
119
|
+
function requestHasPaidReferences(task, params) {
|
|
120
|
+
return taskHasPaidReferences(task) || params?.invoice !== undefined || params?.receipt !== undefined;
|
|
121
|
+
}
|
|
120
122
|
function extractOfferId(taskInput, params) {
|
|
121
123
|
if (isRecord(taskInput) && typeof taskInput.offerId === "string") {
|
|
122
124
|
return taskInput.offerId.trim();
|
|
@@ -361,9 +363,21 @@ function extractMarketplacePaymentSummary(taskInput, params) {
|
|
|
361
363
|
...payer ? { payer } : {},
|
|
362
364
|
...payee ? { payee } : {},
|
|
363
365
|
...typeof receipt?.txRef === "string" && receipt.txRef.trim() ? { txRef: receipt.txRef.trim() } : {},
|
|
364
|
-
...typeof receipt?.settledAt === "string" && receipt.settledAt.trim() ? { settledAt: receipt.settledAt.trim() } : {}
|
|
366
|
+
...typeof receipt?.settledAt === "string" && receipt.settledAt.trim() ? { settledAt: receipt.settledAt.trim() } : {},
|
|
367
|
+
...typeof receipt?.challengeId === "string" && receipt.challengeId.trim() ? { challengeId: receipt.challengeId.trim() } : {},
|
|
368
|
+
...typeof receipt?.paymentMemo === "string" && receipt.paymentMemo.trim() ? { paymentMemo: receipt.paymentMemo.trim() } : {}
|
|
365
369
|
};
|
|
366
370
|
}
|
|
371
|
+
function fixedOfferAmountBaseUnits(offer) {
|
|
372
|
+
const amount = offer.pricing.amount;
|
|
373
|
+
const decimals = offer.paymentDefaults?.assetDecimals;
|
|
374
|
+
if (typeof amount !== "number" || !Number.isFinite(amount) || amount <= 0 || typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0 || decimals > 18) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
const scaled = amount * 10 ** decimals;
|
|
378
|
+
const rounded = Math.round(scaled);
|
|
379
|
+
return Number.isSafeInteger(rounded) && Math.abs(scaled - rounded) < 1e-6 ? rounded : null;
|
|
380
|
+
}
|
|
367
381
|
function buildCanonicalResultPayload(task, actor) {
|
|
368
382
|
const input = isRecord(task.input) ? task.input : null;
|
|
369
383
|
const prompt = input && typeof input.prompt === "string" ? input.prompt.trim() : "";
|
|
@@ -417,19 +431,15 @@ function toTaskSnapshot(task) {
|
|
|
417
431
|
createdAt: task.createdAt,
|
|
418
432
|
updatedAt: task.updatedAt,
|
|
419
433
|
output: task.output,
|
|
420
|
-
error: task.error
|
|
434
|
+
error: task.error,
|
|
435
|
+
settlement: task.settlement,
|
|
436
|
+
paymentRecovery: task.paymentRecovery
|
|
421
437
|
};
|
|
422
438
|
}
|
|
423
439
|
function writeSseEvent(res, event, data) {
|
|
424
440
|
res.write(`event: ${event}\n`);
|
|
425
441
|
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
426
442
|
}
|
|
427
|
-
function buildAuthHeaders(apiToken) {
|
|
428
|
-
if (!apiToken) {
|
|
429
|
-
return {};
|
|
430
|
-
}
|
|
431
|
-
return { Authorization: `Bearer ${apiToken}` };
|
|
432
|
-
}
|
|
433
443
|
function headerValue(value) {
|
|
434
444
|
if (Array.isArray(value)) {
|
|
435
445
|
return typeof value[0] === "string" ? value[0] : "";
|
|
@@ -487,7 +497,6 @@ function createA2aHandler(opts) {
|
|
|
487
497
|
const profileVersion = opts.profileVersion ?? "v0.2";
|
|
488
498
|
const rpcPath = opts.rpcPath ?? "/a2a";
|
|
489
499
|
const streamPath = opts.streamPath ?? "/a2a/stream";
|
|
490
|
-
const tierCacheTtlMs = opts.tierCacheTtlMs ?? 3e4;
|
|
491
500
|
const url = new URL(opts.origin);
|
|
492
501
|
const domain = url.hostname;
|
|
493
502
|
const federationBaseUrl = resolveFederationBaseUrl(process.env);
|
|
@@ -499,26 +508,187 @@ function createA2aHandler(opts) {
|
|
|
499
508
|
});
|
|
500
509
|
const agentId = opts.agentId?.trim() || process.env.FASED_A2A_AGENT_ID?.trim() || handle;
|
|
501
510
|
const tasks = new Map();
|
|
502
|
-
const tierCache = new Map();
|
|
503
511
|
const federationBaseUrlResolved = opts.federationBaseUrl?.trim() || process.env.FASED_FEDERATION_BASE_URL?.trim() || federationBaseUrl;
|
|
504
512
|
const federationApiToken = opts.federationApiToken?.trim() || process.env.FASED_FEDERATION_API_TOKEN?.trim();
|
|
505
513
|
const settlementOrchestrator = opts.settlementOrchestrator ?? (async (params) => await orchestrateA2aTaskSettlement({
|
|
506
514
|
taskId: params.taskId,
|
|
507
515
|
taskInput: params.taskInput,
|
|
516
|
+
invoice: params.invoice,
|
|
517
|
+
receipt: params.receipt,
|
|
518
|
+
offer: params.offer,
|
|
519
|
+
challenge: params.challenge,
|
|
508
520
|
senderHandle: params.senderHandle,
|
|
509
521
|
env: params.env
|
|
510
522
|
}));
|
|
511
|
-
function
|
|
512
|
-
if (
|
|
513
|
-
|
|
523
|
+
async function ensureReviewedRefundApproval(task, recovery) {
|
|
524
|
+
if (recovery.status !== "refund-required" || recovery.approvalRequestId) {
|
|
525
|
+
return recovery;
|
|
526
|
+
}
|
|
527
|
+
const challenge = readDurableA2aPaymentChallenge({
|
|
528
|
+
taskId: task.taskId,
|
|
529
|
+
env: process.env
|
|
530
|
+
});
|
|
531
|
+
if (!challenge || challenge.status !== "claimed") {
|
|
532
|
+
return {
|
|
533
|
+
...recovery,
|
|
534
|
+
reason: `${recovery.reason}; reviewed refund preparation is blocked because the claimed seller challenge is unavailable`,
|
|
535
|
+
updatedAt: new Date().toISOString()
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
const registry = readWalletProviderRegistry(process.env);
|
|
539
|
+
const candidates = registry.wallets.filter((wallet) => resolveWalletUserRole(wallet) === "agent" && wallet.addresses?.solana?.trim() === challenge.payeeAddress);
|
|
540
|
+
if (candidates.length !== 1) {
|
|
541
|
+
return {
|
|
542
|
+
...recovery,
|
|
543
|
+
reason: `${recovery.reason}; reviewed refund preparation requires exactly one Agent wallet matching the paid seller address`,
|
|
544
|
+
updatedAt: new Date().toISOString()
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
const wallet = candidates[0];
|
|
548
|
+
const cfg = loadConfig();
|
|
549
|
+
const created = await createOrExecuteWalletSend({
|
|
550
|
+
payload: {
|
|
551
|
+
actionKind: "send",
|
|
552
|
+
chain: "solana",
|
|
553
|
+
to: challenge.payerAddress,
|
|
554
|
+
amount: String(challenge.amount),
|
|
555
|
+
...challenge.asset.kind === "spl-token" ? { program: challenge.asset.address } : {},
|
|
556
|
+
memo: `fased:a2a-refund:v1:${challenge.challengeId}`,
|
|
557
|
+
walletId: wallet.id,
|
|
558
|
+
walletName: wallet.name,
|
|
559
|
+
providerId: wallet.providerId
|
|
560
|
+
},
|
|
561
|
+
requestedBy: "a2a-refund",
|
|
562
|
+
executionIntentId: `a2a-refund:${challenge.challengeId}`,
|
|
563
|
+
sendPath: "reviewed",
|
|
564
|
+
settlementContext: {
|
|
565
|
+
taskId: task.taskId,
|
|
566
|
+
invoiceId: challenge.invoiceId,
|
|
567
|
+
senderHandle: challenge.senderHandle
|
|
568
|
+
},
|
|
569
|
+
config: resolveWalletRuntimeConfig(cfg, process.env),
|
|
570
|
+
runtimeConfig: cfg,
|
|
571
|
+
providerIdOverride: wallet.providerId,
|
|
572
|
+
env: process.env
|
|
573
|
+
});
|
|
574
|
+
if (!created.ok) {
|
|
575
|
+
return {
|
|
576
|
+
...recovery,
|
|
577
|
+
reason: `${recovery.reason}; reviewed refund preparation failed: ${created.message ?? created.code ?? "unknown error"}`,
|
|
578
|
+
updatedAt: new Date().toISOString()
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
if (created.mode !== "manual") {
|
|
582
|
+
return {
|
|
583
|
+
...recovery,
|
|
584
|
+
reason: `${recovery.reason}; reviewed refund preparation failed closed because the reviewed path did not return a manual approval`,
|
|
585
|
+
updatedAt: new Date().toISOString()
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
...recovery,
|
|
590
|
+
approvalRequestId: created.request.id,
|
|
591
|
+
reason: `${recovery.reason}; reviewed refund approval ${created.request.id} is pending operator and signer-owned WebAuthn authorization`,
|
|
592
|
+
updatedAt: new Date().toISOString()
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
async function reconcileReviewedRefund(task) {
|
|
596
|
+
const recovery = task.paymentRecovery;
|
|
597
|
+
if (recovery?.status !== "refund-required" || !recovery.approvalRequestId) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
const challenge = readDurableA2aPaymentChallenge({
|
|
601
|
+
taskId: task.taskId,
|
|
602
|
+
env: process.env
|
|
603
|
+
});
|
|
604
|
+
const approval = getWalletSendApprovalRequest({
|
|
605
|
+
requestId: recovery.approvalRequestId,
|
|
606
|
+
env: process.env
|
|
607
|
+
});
|
|
608
|
+
if (!challenge || approval?.status !== "executed" || !approval.result?.txHash || approval.payload.to !== challenge.payerAddress || approval.payload.amount !== String(challenge.amount) || approval.payload.memo !== `fased:a2a-refund:v1:${challenge.challengeId}` || (challenge.asset.kind === "spl-token" ? approval.payload.program !== challenge.asset.address : Boolean(approval.payload.program))) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const refunded = {
|
|
612
|
+
...recovery,
|
|
613
|
+
status: "refunded",
|
|
614
|
+
refundTxRef: approval.result.txHash,
|
|
615
|
+
reason: `reviewed refund ${approval.result.txHash} executed through signer-owned authorization`,
|
|
616
|
+
updatedAt: new Date().toISOString()
|
|
617
|
+
};
|
|
618
|
+
const durable = await updateDurableA2aTask({
|
|
619
|
+
taskId: task.taskId,
|
|
620
|
+
paymentRecovery: refunded,
|
|
621
|
+
env: process.env
|
|
622
|
+
});
|
|
623
|
+
task.paymentRecovery = durable.paymentRecovery;
|
|
624
|
+
task.updatedAt = durable.updatedAt;
|
|
625
|
+
}
|
|
626
|
+
function taskFromDurable(record) {
|
|
627
|
+
return {
|
|
628
|
+
taskId: record.taskId,
|
|
629
|
+
status: record.status,
|
|
630
|
+
createdAt: record.createdAt,
|
|
631
|
+
updatedAt: record.updatedAt,
|
|
632
|
+
input: record.input,
|
|
633
|
+
output: record.output,
|
|
634
|
+
error: record.error,
|
|
635
|
+
marketplacePayment: record.marketplacePayment,
|
|
636
|
+
settlement: record.settlement,
|
|
637
|
+
paymentRecovery: record.paymentRecovery,
|
|
638
|
+
timers: [],
|
|
639
|
+
subscribers: new Set()
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function resolveTask(taskId) {
|
|
643
|
+
const active = tasks.get(taskId);
|
|
644
|
+
if (active) {
|
|
645
|
+
return active;
|
|
514
646
|
}
|
|
515
|
-
|
|
516
|
-
|
|
647
|
+
const durable = readDurableA2aTask({
|
|
648
|
+
taskId,
|
|
649
|
+
env: process.env
|
|
650
|
+
});
|
|
651
|
+
if (!durable) {
|
|
652
|
+
return undefined;
|
|
517
653
|
}
|
|
518
|
-
|
|
519
|
-
|
|
654
|
+
const task = taskFromDurable(durable);
|
|
655
|
+
tasks.set(taskId, task);
|
|
656
|
+
return task;
|
|
657
|
+
}
|
|
658
|
+
async function updateTask(task, patch) {
|
|
659
|
+
const paymentRecovery = patch.paymentRecovery ?? ((patch.status === "failed" || patch.status === "canceled") && task.settlement?.status === "executed" && task.settlement.txHash ? {
|
|
660
|
+
status: "refund-required",
|
|
661
|
+
paymentTxRef: task.settlement.txHash,
|
|
662
|
+
reason: patch.error ?? `paid task entered terminal state ${patch.status}; seller must refund or resolve the dispute`,
|
|
663
|
+
updatedAt: new Date().toISOString()
|
|
664
|
+
} : undefined);
|
|
665
|
+
const durable = await updateDurableA2aTask({
|
|
666
|
+
taskId: task.taskId,
|
|
667
|
+
...patch.status ? { status: patch.status } : {},
|
|
668
|
+
...patch.output !== undefined ? { output: patch.output } : {},
|
|
669
|
+
...patch.error !== undefined ? { error: patch.error } : {},
|
|
670
|
+
...patch.settlement !== undefined ? { settlement: patch.settlement } : {},
|
|
671
|
+
...paymentRecovery !== undefined ? { paymentRecovery } : {},
|
|
672
|
+
env: process.env
|
|
673
|
+
});
|
|
674
|
+
if (durable.paymentRecovery?.status === "refund-required" && !durable.paymentRecovery.approvalRequestId) {
|
|
675
|
+
const reviewedRecovery = await ensureReviewedRefundApproval(task, durable.paymentRecovery);
|
|
676
|
+
if (reviewedRecovery !== durable.paymentRecovery) {
|
|
677
|
+
const refreshed = await updateDurableA2aTask({
|
|
678
|
+
taskId: task.taskId,
|
|
679
|
+
paymentRecovery: reviewedRecovery,
|
|
680
|
+
env: process.env
|
|
681
|
+
});
|
|
682
|
+
durable.paymentRecovery = refreshed.paymentRecovery;
|
|
683
|
+
durable.updatedAt = refreshed.updatedAt;
|
|
684
|
+
}
|
|
520
685
|
}
|
|
521
|
-
task.
|
|
686
|
+
task.status = durable.status;
|
|
687
|
+
task.output = durable.output;
|
|
688
|
+
task.error = durable.error;
|
|
689
|
+
task.settlement = durable.settlement;
|
|
690
|
+
task.paymentRecovery = durable.paymentRecovery;
|
|
691
|
+
task.updatedAt = durable.updatedAt;
|
|
522
692
|
const snapshot = toTaskSnapshot(task);
|
|
523
693
|
for (const subscriber of task.subscribers) {
|
|
524
694
|
if (subscriber.writableEnded || subscriber.destroyed) {
|
|
@@ -538,81 +708,74 @@ function createA2aHandler(opts) {
|
|
|
538
708
|
}
|
|
539
709
|
task.timers = [];
|
|
540
710
|
}
|
|
541
|
-
async function
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
const cached = tierCache.get(senderHandle);
|
|
546
|
-
if (cached && cached.expiresAt > Date.now()) {
|
|
547
|
-
return cached.tier;
|
|
548
|
-
}
|
|
549
|
-
if (!federationBaseUrlResolved) {
|
|
550
|
-
return "unverified";
|
|
551
|
-
}
|
|
552
|
-
const endpoint = new URL(`/api/federation/directory/${encodeURIComponent(senderHandle)}`, federationBaseUrlResolved);
|
|
553
|
-
try {
|
|
554
|
-
const res = await fetch(endpoint, { headers: {
|
|
555
|
-
...buildAuthHeaders(federationApiToken),
|
|
556
|
-
accept: "application/json"
|
|
557
|
-
} });
|
|
558
|
-
let tier = "unverified";
|
|
559
|
-
if (res.ok) {
|
|
560
|
-
const body = await res.json();
|
|
561
|
-
if (isRecord(body)) {
|
|
562
|
-
const status = typeof body.status === "string" ? body.status : "";
|
|
563
|
-
if (status === "verified") {
|
|
564
|
-
tier = "verified";
|
|
565
|
-
} else if (status === "revoked") {
|
|
566
|
-
tier = "blocked";
|
|
567
|
-
} else {
|
|
568
|
-
tier = "unverified";
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
} else if (res.status === 404) {
|
|
572
|
-
tier = "unverified";
|
|
573
|
-
}
|
|
574
|
-
tierCache.set(senderHandle, {
|
|
575
|
-
tier,
|
|
576
|
-
expiresAt: Date.now() + tierCacheTtlMs
|
|
577
|
-
});
|
|
578
|
-
return tier;
|
|
579
|
-
} catch {
|
|
580
|
-
return "unverified";
|
|
581
|
-
}
|
|
711
|
+
async function releaseTaskExecution(task) {
|
|
712
|
+
const release = task.executionRelease;
|
|
713
|
+
task.executionRelease = undefined;
|
|
714
|
+
await release?.();
|
|
582
715
|
}
|
|
583
|
-
function createTask(
|
|
584
|
-
const
|
|
585
|
-
const
|
|
586
|
-
const
|
|
587
|
-
const task = {
|
|
716
|
+
async function createTask(params) {
|
|
717
|
+
const requestedTaskId = isRecord(params.input) && typeof params.input.taskId === "string" ? params.input.taskId.trim() : "";
|
|
718
|
+
const taskId = requestedTaskId || randomUUID();
|
|
719
|
+
const reserved = await reserveDurableA2aTask({
|
|
588
720
|
taskId,
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
721
|
+
senderHandle: params.senderHandle,
|
|
722
|
+
input: params.input,
|
|
723
|
+
marketplacePayment: params.marketplacePayment,
|
|
724
|
+
accessToken: params.accessToken,
|
|
725
|
+
env: process.env
|
|
726
|
+
});
|
|
727
|
+
const existing = tasks.get(taskId);
|
|
728
|
+
const task = existing ?? taskFromDurable(reserved.record);
|
|
729
|
+
if (!existing) {
|
|
730
|
+
tasks.set(task.taskId, task);
|
|
731
|
+
}
|
|
732
|
+
return {
|
|
733
|
+
task,
|
|
734
|
+
created: reserved.created,
|
|
735
|
+
accessToken: reserved.accessToken
|
|
596
736
|
};
|
|
737
|
+
}
|
|
738
|
+
function requestTaskAccessToken(req, params) {
|
|
739
|
+
const header = headerValue(req.headers["x-fased-task-token"]).trim();
|
|
740
|
+
const param = typeof params?.taskAccessToken === "string" ? params.taskAccessToken.trim() : "";
|
|
741
|
+
return header || param;
|
|
742
|
+
}
|
|
743
|
+
function anonymousSenderKey(req) {
|
|
744
|
+
const client = opts.peerAuthClientIp ?? req.socket?.remoteAddress ?? "unknown";
|
|
745
|
+
const digest = createHash("sha256").update(client, "utf8").digest("hex").slice(0, 24);
|
|
746
|
+
return `anonymous:${digest}`;
|
|
747
|
+
}
|
|
748
|
+
function scheduleTaskExecution(task) {
|
|
749
|
+
if (isTerminal(task.status) || task.timers.length > 0) {
|
|
750
|
+
void releaseTaskExecution(task);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
597
753
|
const queuedToRunning = setTimeout(() => {
|
|
598
754
|
if (task.status !== "queued") {
|
|
599
755
|
return;
|
|
600
756
|
}
|
|
601
|
-
updateTask(task, { status: "running" })
|
|
757
|
+
void updateTask(task, { status: "running" }).catch(async (error) => {
|
|
758
|
+
task.error = error instanceof Error ? error.message : String(error);
|
|
759
|
+
clearTaskTimers(task);
|
|
760
|
+
await releaseTaskExecution(task);
|
|
761
|
+
});
|
|
602
762
|
}, 10);
|
|
603
763
|
const runningToDone = setTimeout(() => {
|
|
604
764
|
if (task.status === "canceled") {
|
|
765
|
+
void releaseTaskExecution(task);
|
|
605
766
|
return;
|
|
606
767
|
}
|
|
607
|
-
updateTask(task, {
|
|
768
|
+
void updateTask(task, {
|
|
608
769
|
status: "succeeded",
|
|
609
770
|
output: buildCanonicalResultPayload(task, handle)
|
|
771
|
+
}).catch((error) => {
|
|
772
|
+
task.error = error instanceof Error ? error.message : String(error);
|
|
773
|
+
}).finally(async () => {
|
|
774
|
+
clearTaskTimers(task);
|
|
775
|
+
await releaseTaskExecution(task);
|
|
610
776
|
});
|
|
611
|
-
clearTaskTimers(task);
|
|
612
777
|
}, 50);
|
|
613
778
|
task.timers.push(queuedToRunning, runningToDone);
|
|
614
|
-
tasks.set(task.taskId, task);
|
|
615
|
-
return task;
|
|
616
779
|
}
|
|
617
780
|
return async (req, res) => {
|
|
618
781
|
const parsed = new URL(req.url ?? "/", opts.origin);
|
|
@@ -640,7 +803,11 @@ function createA2aHandler(opts) {
|
|
|
640
803
|
"payments",
|
|
641
804
|
"service-offers"
|
|
642
805
|
],
|
|
643
|
-
auth: {
|
|
806
|
+
auth: {
|
|
807
|
+
type: "task-capability-and-federation-peer-v2",
|
|
808
|
+
paidTasks: "signed-federation-peer-v2-required",
|
|
809
|
+
taskAccess: "x-fased-task-token-header-or-json-rpc-taskAccessToken-required"
|
|
810
|
+
},
|
|
644
811
|
metadata: {
|
|
645
812
|
apBridgeEnabled: opts.includeApBridgeMetadata ?? true,
|
|
646
813
|
supportedObjects: [
|
|
@@ -669,7 +836,20 @@ function createA2aHandler(opts) {
|
|
|
669
836
|
});
|
|
670
837
|
return true;
|
|
671
838
|
}
|
|
672
|
-
const
|
|
839
|
+
const accessToken = requestTaskAccessToken(req);
|
|
840
|
+
const authorized = authorizeDurableA2aTask({
|
|
841
|
+
taskId,
|
|
842
|
+
accessToken,
|
|
843
|
+
env: process.env
|
|
844
|
+
});
|
|
845
|
+
if (!authorized) {
|
|
846
|
+
sendJson(res, 404, {
|
|
847
|
+
status: "not_found",
|
|
848
|
+
reason: "task not found"
|
|
849
|
+
});
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
const task = resolveTask(taskId);
|
|
673
853
|
if (!task) {
|
|
674
854
|
sendJson(res, 404, {
|
|
675
855
|
status: "not_found",
|
|
@@ -682,6 +862,7 @@ function createA2aHandler(opts) {
|
|
|
682
862
|
res.setHeader("Cache-Control", "no-cache, no-transform");
|
|
683
863
|
res.setHeader("Connection", "keep-alive");
|
|
684
864
|
res.setHeader("X-Accel-Buffering", "no");
|
|
865
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
685
866
|
writeSseEvent(res, "task.snapshot", toTaskSnapshot(task));
|
|
686
867
|
if (isTerminal(task.status)) {
|
|
687
868
|
res.end();
|
|
@@ -718,11 +899,31 @@ function createA2aHandler(opts) {
|
|
|
718
899
|
return true;
|
|
719
900
|
}
|
|
720
901
|
const params = isRecord(rpc.params) ? rpc.params : undefined;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
902
|
+
let senderHandle = anonymousSenderKey(req);
|
|
903
|
+
let senderTier = "unverified";
|
|
904
|
+
const signedProtocolHeader = headerValue(req.headers[FEDERATION_PEER_HEADERS.protocolVersion]);
|
|
905
|
+
if (signedProtocolHeader) {
|
|
906
|
+
if (rpcPath !== FEDERATION_A2A_RPC_PATH) {
|
|
907
|
+
sendRpcError(res, id, -32040, "signed A2A requires the canonical /a2a endpoint");
|
|
908
|
+
return true;
|
|
909
|
+
}
|
|
910
|
+
const peerAuth = await authorizeFederationPeerRequestV2({
|
|
911
|
+
req,
|
|
912
|
+
body: body.value,
|
|
913
|
+
recipientHandle: handle,
|
|
914
|
+
expectedPath: FEDERATION_A2A_RPC_PATH,
|
|
915
|
+
directoryBaseUrl: federationBaseUrlResolved,
|
|
916
|
+
directoryApiToken: federationApiToken,
|
|
917
|
+
clientIp: opts.peerAuthClientIp,
|
|
918
|
+
env: process.env,
|
|
919
|
+
deps: opts.peerAuthDeps
|
|
920
|
+
});
|
|
921
|
+
if (!peerAuth.ok) {
|
|
922
|
+
sendRpcError(res, id, -32040, peerAuth.reason, peerAuth.statusCode, { code: peerAuth.code });
|
|
923
|
+
return true;
|
|
924
|
+
}
|
|
925
|
+
senderHandle = peerAuth.senderHandle;
|
|
926
|
+
senderTier = "verified";
|
|
726
927
|
}
|
|
727
928
|
if (rpc.method === "a2a.ping" || rpc.method === "ping") {
|
|
728
929
|
sendRpcResult(res, id, {
|
|
@@ -750,9 +951,45 @@ function createA2aHandler(opts) {
|
|
|
750
951
|
sendRpcResult(res, id, { offer });
|
|
751
952
|
return true;
|
|
752
953
|
}
|
|
954
|
+
if (rpc.method === "payments.prepare" || rpc.method === "payment.prepare" || rpc.method === "payments/prepare") {
|
|
955
|
+
if (senderTier !== "verified") {
|
|
956
|
+
sendRpcError(res, id, -32041, "payment challenge requires verified sender");
|
|
957
|
+
return true;
|
|
958
|
+
}
|
|
959
|
+
const taskId = typeof params?.taskId === "string" ? params.taskId.trim() : "";
|
|
960
|
+
const offerId = typeof params?.offerId === "string" ? params.offerId.trim() : "";
|
|
961
|
+
const payerAddress = typeof params?.payerAddress === "string" ? params.payerAddress.trim() : "";
|
|
962
|
+
const offer = findOfferById(offerId, offers);
|
|
963
|
+
const payment = offer?.paymentDefaults;
|
|
964
|
+
const amount = offer ? fixedOfferAmountBaseUnits(offer) : null;
|
|
965
|
+
const payer = normalizeAddressForChain("solana", payerAddress);
|
|
966
|
+
const payee = normalizeAddressForChain("solana", payment?.payee.address);
|
|
967
|
+
const asset = payment ? extractCanonicalAsset(payment.asset, "solana") : null;
|
|
968
|
+
if (!taskId || !offer || !payment || !amount || !payer || !payee || !asset) {
|
|
969
|
+
sendRpcError(res, id, -32602, "invalid fixed-price Solana payment challenge request");
|
|
970
|
+
return true;
|
|
971
|
+
}
|
|
972
|
+
try {
|
|
973
|
+
const challenge = await issueDurableA2aPaymentChallenge({
|
|
974
|
+
taskId,
|
|
975
|
+
senderHandle,
|
|
976
|
+
offerId: offer.id,
|
|
977
|
+
payerAddress: payer,
|
|
978
|
+
payeeAddress: payee,
|
|
979
|
+
amount,
|
|
980
|
+
currency: payment.currency,
|
|
981
|
+
asset,
|
|
982
|
+
env: process.env
|
|
983
|
+
});
|
|
984
|
+
sendRpcResult(res, id, challenge);
|
|
985
|
+
} catch (error) {
|
|
986
|
+
sendRpcError(res, id, -32055, error instanceof Error ? error.message : String(error));
|
|
987
|
+
}
|
|
988
|
+
return true;
|
|
989
|
+
}
|
|
753
990
|
if (rpc.method === "tasks.create" || rpc.method === "task.create" || rpc.method === "tasks/create") {
|
|
754
991
|
const taskInput = params && "task" in params ? params.task : params;
|
|
755
|
-
const hasPaidReferences =
|
|
992
|
+
const hasPaidReferences = requestHasPaidReferences(taskInput, params);
|
|
756
993
|
const offerIssue = validateOfferReference(taskInput, params, offers);
|
|
757
994
|
if (offerIssue) {
|
|
758
995
|
sendRpcError(res, id, offerIssue.code, offerIssue.message, 200, offerIssue.data);
|
|
@@ -772,13 +1009,39 @@ function createA2aHandler(opts) {
|
|
|
772
1009
|
sendRpcError(res, id, -32041, "paid task requires verified sender");
|
|
773
1010
|
return true;
|
|
774
1011
|
}
|
|
775
|
-
|
|
1012
|
+
let taskResult;
|
|
1013
|
+
try {
|
|
1014
|
+
taskResult = await createTask({
|
|
1015
|
+
input: taskInput,
|
|
1016
|
+
marketplacePayment: extractMarketplacePaymentSummary(taskInput, params),
|
|
1017
|
+
senderHandle,
|
|
1018
|
+
accessToken: requestTaskAccessToken(req, params)
|
|
1019
|
+
});
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
sendRpcError(res, id, -32054, error instanceof Error ? error.message : String(error));
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
1024
|
+
const task = taskResult.task;
|
|
776
1025
|
let settlement;
|
|
777
|
-
|
|
1026
|
+
const executionRelease = isTerminal(task.status) ? null : await claimDurableA2aTaskExecution({
|
|
1027
|
+
taskId: task.taskId,
|
|
1028
|
+
env: process.env
|
|
1029
|
+
});
|
|
1030
|
+
if (executionRelease) {
|
|
1031
|
+
task.executionRelease = executionRelease;
|
|
1032
|
+
}
|
|
1033
|
+
if (hasPaidReferences && executionRelease && (!task.settlement || task.settlement.status !== "executed")) {
|
|
778
1034
|
try {
|
|
779
1035
|
settlement = await settlementOrchestrator({
|
|
780
1036
|
taskId: task.taskId,
|
|
781
1037
|
taskInput,
|
|
1038
|
+
invoice: params?.invoice,
|
|
1039
|
+
receipt: params?.receipt,
|
|
1040
|
+
offer: findOfferById(extractOfferId(taskInput, params), offers),
|
|
1041
|
+
challenge: readDurableA2aPaymentChallenge({
|
|
1042
|
+
taskId: task.taskId,
|
|
1043
|
+
env: process.env
|
|
1044
|
+
}),
|
|
782
1045
|
senderHandle,
|
|
783
1046
|
senderTier,
|
|
784
1047
|
env: process.env
|
|
@@ -789,10 +1052,37 @@ function createA2aHandler(opts) {
|
|
|
789
1052
|
reason: `settlement orchestration error: ${String(err)}`
|
|
790
1053
|
};
|
|
791
1054
|
}
|
|
1055
|
+
if (settlement.status === "executed") {
|
|
1056
|
+
try {
|
|
1057
|
+
await claimDurableA2aPaymentChallenge({
|
|
1058
|
+
taskId: task.taskId,
|
|
1059
|
+
challengeId: settlement.challengeId ?? "",
|
|
1060
|
+
senderHandle,
|
|
1061
|
+
payerAddress: settlement.payerAddress ?? "",
|
|
1062
|
+
txRef: settlement.txHash ?? "",
|
|
1063
|
+
env: process.env
|
|
1064
|
+
});
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
settlement = {
|
|
1067
|
+
status: "failed",
|
|
1068
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
await updateTask(task, { settlement });
|
|
1073
|
+
} else {
|
|
1074
|
+
settlement = task.settlement;
|
|
1075
|
+
}
|
|
1076
|
+
const settlementAllowsExecution = !hasPaidReferences || task.settlement?.status === "executed";
|
|
1077
|
+
if (executionRelease && settlementAllowsExecution) {
|
|
1078
|
+
scheduleTaskExecution(task);
|
|
1079
|
+
} else if (executionRelease) {
|
|
1080
|
+
await releaseTaskExecution(task);
|
|
792
1081
|
}
|
|
793
1082
|
sendRpcResult(res, id, {
|
|
794
1083
|
taskId: task.taskId,
|
|
795
1084
|
status: task.status,
|
|
1085
|
+
...taskResult.accessToken ? { taskAccessToken: taskResult.accessToken } : {},
|
|
796
1086
|
streamUrl: `${new URL(streamPath, visibleOrigin).toString()}?taskId=${encodeURIComponent(task.taskId)}`,
|
|
797
1087
|
...settlement ? { settlement } : {}
|
|
798
1088
|
});
|
|
@@ -804,11 +1094,44 @@ function createA2aHandler(opts) {
|
|
|
804
1094
|
sendRpcError(res, id, -32602, "missing taskId");
|
|
805
1095
|
return true;
|
|
806
1096
|
}
|
|
807
|
-
const
|
|
1097
|
+
const authorized = authorizeDurableA2aTask({
|
|
1098
|
+
taskId,
|
|
1099
|
+
accessToken: requestTaskAccessToken(req, params),
|
|
1100
|
+
env: process.env
|
|
1101
|
+
});
|
|
1102
|
+
const task = authorized ? resolveTask(taskId) : undefined;
|
|
808
1103
|
if (!task) {
|
|
809
1104
|
sendRpcError(res, id, -32044, "task not found");
|
|
810
1105
|
return true;
|
|
811
1106
|
}
|
|
1107
|
+
await reconcileReviewedRefund(task);
|
|
1108
|
+
sendRpcResult(res, id, toTaskSnapshot(task));
|
|
1109
|
+
return true;
|
|
1110
|
+
}
|
|
1111
|
+
if (rpc.method === "tasks.refund.prepare" || rpc.method === "task.refund.prepare" || rpc.method === "tasks/refund/prepare") {
|
|
1112
|
+
if (senderTier !== "verified") {
|
|
1113
|
+
sendRpcError(res, id, -32041, "refund preparation requires the verified paying peer");
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
const taskId = typeof params?.taskId === "string" ? params.taskId.trim() : "";
|
|
1117
|
+
const authorized = taskId ? authorizeDurableA2aTask({
|
|
1118
|
+
taskId,
|
|
1119
|
+
accessToken: requestTaskAccessToken(req, params),
|
|
1120
|
+
env: process.env
|
|
1121
|
+
}) : false;
|
|
1122
|
+
const task = authorized ? resolveTask(taskId) : undefined;
|
|
1123
|
+
if (!task?.paymentRecovery || task.paymentRecovery.status !== "refund-required") {
|
|
1124
|
+
sendRpcError(res, id, -32044, "refund-required task not found");
|
|
1125
|
+
return true;
|
|
1126
|
+
}
|
|
1127
|
+
const recovery = await ensureReviewedRefundApproval(task, task.paymentRecovery);
|
|
1128
|
+
const durable = await updateDurableA2aTask({
|
|
1129
|
+
taskId,
|
|
1130
|
+
paymentRecovery: recovery,
|
|
1131
|
+
env: process.env
|
|
1132
|
+
});
|
|
1133
|
+
task.paymentRecovery = durable.paymentRecovery;
|
|
1134
|
+
task.updatedAt = durable.updatedAt;
|
|
812
1135
|
sendRpcResult(res, id, toTaskSnapshot(task));
|
|
813
1136
|
return true;
|
|
814
1137
|
}
|
|
@@ -818,14 +1141,20 @@ function createA2aHandler(opts) {
|
|
|
818
1141
|
sendRpcError(res, id, -32602, "missing taskId");
|
|
819
1142
|
return true;
|
|
820
1143
|
}
|
|
821
|
-
const
|
|
1144
|
+
const authorized = authorizeDurableA2aTask({
|
|
1145
|
+
taskId,
|
|
1146
|
+
accessToken: requestTaskAccessToken(req, params),
|
|
1147
|
+
env: process.env
|
|
1148
|
+
});
|
|
1149
|
+
const task = authorized ? resolveTask(taskId) : undefined;
|
|
822
1150
|
if (!task) {
|
|
823
1151
|
sendRpcError(res, id, -32044, "task not found");
|
|
824
1152
|
return true;
|
|
825
1153
|
}
|
|
826
1154
|
if (!isTerminal(task.status)) {
|
|
827
1155
|
clearTaskTimers(task);
|
|
828
|
-
updateTask(task, { status: "canceled" });
|
|
1156
|
+
await updateTask(task, { status: "canceled" });
|
|
1157
|
+
await releaseTaskExecution(task);
|
|
829
1158
|
}
|
|
830
1159
|
sendRpcResult(res, id, toTaskSnapshot(task));
|
|
831
1160
|
return true;
|