@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.
Files changed (341) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +38 -30
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +49 -0
  5. package/config/signer-policies/agent.json.template +32 -0
  6. package/config/signer-policies/mining.json.template +69 -0
  7. package/config/signer-policies/network.json.template +5 -0
  8. package/config/signer-policies/vault.json.template +70 -0
  9. package/config/signer-protocol-v2.json +76 -0
  10. package/config/typescript-noemit-baseline.json +680 -0
  11. package/dist/agents/auth-profiles/store.js +267 -31
  12. package/dist/agents/bash-tools.exec.js +10 -4
  13. package/dist/agents/current-model-catalog.js +3 -3
  14. package/dist/agents/memory-search.js +7 -1
  15. package/dist/agents/model-catalog-access.js +1 -2
  16. package/dist/agents/model-catalog-snapshot.js +1 -1
  17. package/dist/agents/model-catalog-source.js +1 -1
  18. package/dist/agents/model-metadata.js +1 -1
  19. package/dist/agents/model-selection.js +2 -28
  20. package/dist/agents/models-config.providers.js +6 -6
  21. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  22. package/dist/agents/pi-embedded-runner/model.js +1 -1
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  24. package/dist/agents/pi-embedded-runner/run.js +2 -0
  25. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  26. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  27. package/dist/agents/pi-tools.js +2 -1
  28. package/dist/agents/sandbox/config.js +1 -1
  29. package/dist/agents/sandbox/context.js +27 -2
  30. package/dist/agents/skills/env-overrides.js +38 -28
  31. package/dist/agents/skills/trust.js +93 -0
  32. package/dist/agents/skills/workspace.js +128 -0
  33. package/dist/agents/skills-clawhub.js +36 -11
  34. package/dist/agents/skills-marketplace-scan.js +49 -0
  35. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  36. package/dist/agents/tools/mining-tool.js +1 -1
  37. package/dist/agents/tools/session-status-tool.js +1 -1
  38. package/dist/agents/tools/wallet-action-tool.js +172 -36
  39. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  40. package/dist/agents/tools/wallet-tool.js +7 -11
  41. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  42. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  43. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  44. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  45. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  46. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  47. package/dist/auto-reply/reply/model-selection.js +7 -4
  48. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  49. package/dist/brand.js +1 -1
  50. package/dist/build-info.json +3 -3
  51. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  52. package/dist/channel-web.js +2 -2
  53. package/dist/cli/gateway-cli/run.js +8 -0
  54. package/dist/cli/program/command-registry.js +1 -1
  55. package/dist/cli/program/register.onboard.js +2 -3
  56. package/dist/cli/program/register.wallet.js +16 -123
  57. package/dist/cli/providers-cli.js +1 -1
  58. package/dist/cli/sat-cli.js +129 -2
  59. package/dist/cli/update-cli/update-command.js +260 -11
  60. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  61. package/dist/commands/doctor-config-flow.js +1 -1
  62. package/dist/commands/doctor-legacy-config.js +2 -13
  63. package/dist/commands/model-picker.js +6 -6
  64. package/dist/commands/models/auth.js +1 -1
  65. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  66. package/dist/commands/onboard-auth.credentials.js +32 -8
  67. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  68. package/dist/commands/onboard-non-interactive/local.js +5 -1
  69. package/dist/commands/wallet.js +568 -1911
  70. package/dist/config/config.js +2 -2
  71. package/dist/config/io.js +64 -2
  72. package/dist/config/schema.help.js +8 -7
  73. package/dist/config/schema.labels.js +5 -4
  74. package/dist/config/zod-schema.agent-runtime.js +1 -0
  75. package/dist/config/zod-schema.js +5 -0
  76. package/dist/control-ui/assets/{app-DLil9VO1.js → app-bR-fO5ty.js} +1511 -1555
  77. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  78. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  79. package/dist/control-ui/assets/{index-DdE_NIXo.js → index-ckCxHwjy.js} +3 -3
  80. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
  81. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  82. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  83. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  84. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/control-ui/version.json +1 -1
  87. package/dist/daemon/systemd-system.js +56 -50
  88. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  89. package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
  90. package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
  91. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  92. package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
  93. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  94. package/dist/federation/auto-connect.js +98 -8
  95. package/dist/federation/marketplace-capability-adapter.js +33 -7
  96. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  97. package/dist/federation/marketplace-delivery.js +351 -215
  98. package/dist/federation/marketplace-direct-payment.js +272 -141
  99. package/dist/federation/marketplace-escrow.js +607 -249
  100. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  101. package/dist/federation/offers.js +9 -7
  102. package/dist/federation/peer-auth-v2.js +529 -0
  103. package/dist/gateway/a2a-http.js +425 -96
  104. package/dist/gateway/a2a-settlement.js +259 -153
  105. package/dist/gateway/a2a-task-store.js +524 -0
  106. package/dist/gateway/auth.js +38 -2
  107. package/dist/gateway/config-reload.js +46 -33
  108. package/dist/gateway/durable-capacity.js +31 -0
  109. package/dist/gateway/federation-http.js +540 -135
  110. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  111. package/dist/gateway/federation-marketplace.js +535 -230
  112. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  113. package/dist/gateway/security-path.js +1 -1
  114. package/dist/gateway/server-http.js +1084 -1205
  115. package/dist/gateway/server-methods/models.js +1 -1
  116. package/dist/gateway/server-methods/secrets.js +40 -0
  117. package/dist/gateway/server-methods.js +1 -2
  118. package/dist/gateway/server-reload-handlers.js +196 -66
  119. package/dist/gateway/server-runtime-config.js +1 -1
  120. package/dist/gateway/server-secrets-runtime.js +288 -0
  121. package/dist/gateway/server.impl.js +73 -42
  122. package/dist/gateway/sessions-patch.js +3 -5
  123. package/dist/index.js +4 -2
  124. package/dist/infra/fasedhub.js +64 -1
  125. package/dist/infra/local-source-paired-update.js +538 -0
  126. package/dist/infra/restart.js +41 -10
  127. package/dist/infra/update-runner.js +96 -0
  128. package/dist/light-update-status.js +11 -11
  129. package/dist/memory/backend-config.js +2 -1
  130. package/dist/memory/session-files.js +16 -2
  131. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  132. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  133. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  134. package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-BYxAt775.js} +27 -27
  135. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  136. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  137. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  138. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  139. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  140. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  141. package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DIRHG2gJ.js} +1 -1
  142. package/dist/plugin-sdk/command-status.d.ts +2 -2
  143. package/dist/plugin-sdk/command-status.js +27 -27
  144. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  145. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  146. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  147. package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-BOT7kHb6.js} +6779 -3696
  148. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  149. package/dist/plugin-sdk/discord.d.ts +6 -6
  150. package/dist/plugin-sdk/discord.js +19 -19
  151. package/dist/plugin-sdk/file-lock.js +35 -4
  152. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  153. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  154. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  155. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  156. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  157. package/dist/plugin-sdk/index.d.ts +21 -39
  158. package/dist/plugin-sdk/index.js +29 -29
  159. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  160. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  161. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  162. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  163. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  164. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  165. package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-BCFDaqJ-.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.js} +27 -27
  168. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  169. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  170. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  171. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
  172. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  173. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  174. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  175. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  176. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  177. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  178. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  179. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  180. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  181. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  182. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  183. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  184. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  185. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  186. package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
  187. package/dist/plugin-sdk/sat-runtime.js +29 -29
  188. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  189. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  190. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  191. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  192. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  193. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  194. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  195. package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BUTt8cxK.js} +39 -39
  196. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  197. package/dist/plugin-sdk/slack.d.ts +6 -6
  198. package/dist/plugin-sdk/slack.js +9 -9
  199. package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-D0wHVqjt.js} +3 -3
  200. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  201. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  202. package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-CC_qN4v0.js} +30 -30
  203. package/dist/plugin-sdk/telegram.d.ts +6 -6
  204. package/dist/plugin-sdk/telegram.js +8 -8
  205. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  206. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  207. package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
  209. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  210. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -2
  211. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  212. package/dist/plugin-sdk/{web-CInY-lCv.js → web-BXsJ1vqe.js} +32 -32
  213. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  214. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  215. package/dist/plugin-sdk/whatsapp.d.ts +13 -13
  216. package/dist/plugin-sdk/whatsapp.js +12 -12
  217. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  218. package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
  219. package/dist/providers/refresh.js +1 -1
  220. package/dist/providers/registry.js +1 -1
  221. package/dist/secrets/apply.js +1 -1
  222. package/dist/secrets/runtime.js +1 -1
  223. package/dist/wallet/external-submission-ledger.js +376 -0
  224. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  225. package/dist/wallet/local-socket-signer-archive.js +30 -0
  226. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  227. package/dist/wallet/local-socket-signer-policy.js +166 -0
  228. package/dist/wallet/local-socket-signer-protocol.js +561 -118
  229. package/dist/wallet/native-signer-wallet-id.js +25 -0
  230. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  231. package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
  232. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  233. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  234. package/dist/wallet/signer-network-admin.js +184 -0
  235. package/dist/wallet/signer-protocol-v2.generated.js +90 -0
  236. package/dist/wallet/solana-bond-signing.js +157 -69
  237. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  238. package/dist/wallet/solana-swap.js +520 -64
  239. package/dist/wallet/solana-transaction-inspection.js +106 -4
  240. package/dist/wallet/solana-trigger.js +658 -320
  241. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  242. package/dist/wallet/wallet-approval-auth.js +17 -28
  243. package/dist/wallet/wallet-atomic-state.js +53 -0
  244. package/dist/wallet/wallet-canary.js +0 -1
  245. package/dist/wallet/wallet-inbound-events.js +16 -11
  246. package/dist/wallet/wallet-policy-simulation.js +1 -1
  247. package/dist/wallet/wallet-policy.js +90 -36
  248. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  249. package/dist/wallet/wallet-provider-registry.js +57 -44
  250. package/dist/wallet/wallet-provider-resolver.js +62 -63
  251. package/dist/wallet/wallet-runtime-config.js +28 -41
  252. package/dist/wallet/wallet-secrets-store.js +22 -0
  253. package/dist/wallet/wallet-send-approvals.js +1891 -589
  254. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  255. package/dist/wallet/wallet-settlement-links.js +14 -13
  256. package/dist/wallet/wallet-standard-review.js +353 -0
  257. package/dist/wallet/wallet-status.js +0 -9
  258. package/dist/wallet/wallet-task-ledger.js +16 -2
  259. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  260. package/dist/web/auto-reply/monitor.js +2 -2
  261. package/dist/wizard/host-security-capability.js +14 -23
  262. package/dist/wizard/onboarding.finalize.js +63 -184
  263. package/dist/wizard/onboarding.host-security.js +117 -1367
  264. package/dist/wizard/onboarding.js +172 -217
  265. package/dist/wizard/onboarding.wallet.js +232 -785
  266. package/extensions/acpx/package.json +1 -1
  267. package/extensions/bluebubbles/package.json +1 -1
  268. package/extensions/copilot-proxy/package.json +1 -1
  269. package/extensions/diagnostics-otel/package.json +1 -1
  270. package/extensions/fased-federation/package.json +1 -1
  271. package/extensions/google-gemini-cli-auth/package.json +1 -1
  272. package/extensions/imessage/package.json +1 -1
  273. package/extensions/irc/package.json +1 -1
  274. package/extensions/line/package.json +1 -1
  275. package/extensions/llm-task/package.json +1 -1
  276. package/extensions/lobster/package.json +1 -1
  277. package/extensions/matrix/CHANGELOG.md +12 -0
  278. package/extensions/matrix/package.json +1 -1
  279. package/extensions/mattermost/package.json +1 -1
  280. package/extensions/memory-core/package.json +2 -2
  281. package/extensions/memory-lancedb/package.json +1 -1
  282. package/extensions/minimax-portal-auth/package.json +1 -1
  283. package/extensions/msteams/CHANGELOG.md +12 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +12 -0
  287. package/extensions/nostr/package.json +1 -1
  288. package/extensions/open-prose/package.json +1 -1
  289. package/extensions/sat-mining/index.ts +498 -153
  290. package/extensions/sat-mining/package.json +1 -1
  291. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  292. package/extensions/sat-mining/src/audit-store.ts +50 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/config.ts +9 -0
  295. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  296. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  297. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  298. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  299. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  300. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  301. package/extensions/sat-mining/src/rpc-read.ts +330 -89
  302. package/extensions/sat-mining/src/runtime.ts +14 -0
  303. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  304. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  305. package/extensions/sat-mining/src/solana-submit.ts +1199 -428
  306. package/extensions/sat-mining/src/submission-ledger.ts +433 -0
  307. package/extensions/signal/package.json +1 -1
  308. package/extensions/synology-chat/package.json +1 -1
  309. package/extensions/tlon/package.json +1 -1
  310. package/extensions/twitch/CHANGELOG.md +12 -0
  311. package/extensions/twitch/package.json +1 -1
  312. package/extensions/voice-call/CHANGELOG.md +12 -0
  313. package/extensions/voice-call/package.json +1 -1
  314. package/extensions/zalo/CHANGELOG.md +12 -0
  315. package/extensions/zalo/package.json +1 -1
  316. package/extensions/zalouser/CHANGELOG.md +12 -0
  317. package/extensions/zalouser/package.json +1 -1
  318. package/install.sh +4955 -0
  319. package/package.json +23 -5
  320. package/scripts/fased-host-updater.mjs +1421 -0
  321. package/scripts/fased-host-updaterctl.mjs +186 -0
  322. package/scripts/fased-managed-service.sh +36 -0
  323. package/scripts/fased-managed-updater.mjs +3065 -156
  324. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  325. package/scripts/fased-signer-network-hosting.sh +143 -0
  326. package/scripts/fased-signer-owner-policy.mjs +1430 -0
  327. package/scripts/fased-signer-policy-hosting.sh +50 -0
  328. package/scripts/fased-signer-policy-local.sh +26 -0
  329. package/scripts/hosted-release-manifest.mjs +185 -0
  330. package/scripts/install-fased-signerd.sh +183 -108
  331. package/scripts/install-managed-runtime.mjs +212 -10
  332. package/scripts/managed-runtime-layout.mjs +75 -3
  333. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  334. package/scripts/start-managed.sh +169 -360
  335. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  336. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  337. package/dist/wallet/local-socket-signer-broker.js +0 -224
  338. package/dist/wallet/local-socket-signer-custody.js +0 -42
  339. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  340. package/dist/wallet/providers/privy-adapter.js +0 -80
  341. package/dist/wallet/wallet-custody.js +0 -1836
@@ -6,10 +6,15 @@ import { resolveFederationBaseUrl } from "../federation/runtime.js";
6
6
  import { loadPersistedFederationToken } from "../federation/access-token.js";
7
7
  import { publishFederationSettlementEvidence } from "../federation/settlement-evidence.js";
8
8
  import { createOrExecuteWalletSend } from "../wallet/wallet-send-approvals.js";
9
- import { randomUUID } from "node:crypto";
9
+ import { FEDERATION_A2A_RPC_PATH, buildSignedFederationPeerRequest } from "../federation/peer-auth-v2.js";
10
+ import { createMarketplaceTaskAccessToken, withDurableMarketplaceRun } from "./federation-marketplace-run-store.js";
11
+ import { createHash } from "node:crypto";
10
12
  import { setTimeout } from "node:timers/promises";
11
13
 
12
14
  //#region src/gateway/federation-marketplace.ts
15
+ function stableMarketplaceRunId(prefix, executionIntentId) {
16
+ return `${prefix}-${createHash("sha256").update(executionIntentId).digest("hex").slice(0, 24)}`;
17
+ }
13
18
  const TASK_SCHEMA = "https://schemas.fased.ai/fased-agent-task-v0.json";
14
19
  const INVOICE_SCHEMA = "https://schemas.fased.ai/fased-invoice-v0.json";
15
20
  const RECEIPT_SCHEMA = "https://schemas.fased.ai/fased-receipt-v0.json";
@@ -50,9 +55,6 @@ function offerIdsMatch(left, right) {
50
55
  const rightCanonical = canonicalizeOfferReference(right);
51
56
  return !!leftCanonical && leftCanonical === rightCanonical;
52
57
  }
53
- function createDefaultId(prefix) {
54
- return `${prefix}-${Date.now()}-${randomUUID().slice(0, 8)}`;
55
- }
56
58
  function parseAssetDecimals(raw) {
57
59
  if (!Number.isFinite(raw)) {
58
60
  return null;
@@ -67,10 +69,7 @@ function resolvePaymentWallet(registry, walletId) {
67
69
  const requestedWalletId = trimString(walletId);
68
70
  if (requestedWalletId) {
69
71
  const requested = registry.wallets.find((wallet) => wallet.id === requestedWalletId);
70
- if (!requested) {
71
- return null;
72
- }
73
- if (resolveWalletUserRole(requested) !== "agent" && requested.id !== registry.defaultWalletId) {
72
+ if (!requested || resolveWalletUserRole(requested) !== "agent") {
74
73
  return null;
75
74
  }
76
75
  return requested;
@@ -78,7 +77,7 @@ function resolvePaymentWallet(registry, walletId) {
78
77
  const defaultWalletId = trimString(registry.defaultWalletId);
79
78
  if (defaultWalletId) {
80
79
  const fallback = registry.wallets.find((wallet) => wallet.id === defaultWalletId);
81
- if (fallback && resolveWalletUserRole(fallback) !== "mining") {
80
+ if (fallback && resolveWalletUserRole(fallback) === "agent") {
82
81
  return fallback;
83
82
  }
84
83
  }
@@ -86,7 +85,7 @@ function resolvePaymentWallet(registry, walletId) {
86
85
  if (agentWallet) {
87
86
  return agentWallet;
88
87
  }
89
- return registry.wallets.length === 1 ? registry.wallets[0] ?? null : null;
88
+ return null;
90
89
  }
91
90
  function parseHumanAmountToOnChainInteger(amountInput, decimals) {
92
91
  const normalized = amountInput.trim();
@@ -108,14 +107,6 @@ function parseHumanAmountToOnChainInteger(amountInput, decimals) {
108
107
  }
109
108
  function normalizeMarketplacePaymentFailure(message) {
110
109
  const normalized = message.trim();
111
- const lower = normalized.toLowerCase();
112
- if (lower.includes("split-key custody requires an active unlock session") || lower.includes("custody_unlock_required")) {
113
- return [
114
- "Buyer Agent wallet is locked by split-key custody.",
115
- "Open Wallet, select the Agent wallet, unlock custody with passkey/device share, then retry Pay.",
116
- "No funds were moved."
117
- ].join(" ");
118
- }
119
110
  return normalized || "wallet payment failed";
120
111
  }
121
112
  function toMarketplaceAsset(kind, address) {
@@ -155,18 +146,27 @@ async function fetchJson(fetchImpl, input, init) {
155
146
  }
156
147
  }
157
148
  async function rpcCall(params) {
149
+ const body = {
150
+ jsonrpc: "2.0",
151
+ id: "marketplace-ui",
152
+ method: params.method,
153
+ params: params.rpcParams
154
+ };
155
+ const signed = params.peerAuth ? buildSignedFederationPeerRequest({
156
+ senderHandle: params.peerAuth.senderHandle,
157
+ recipientHandle: params.peerAuth.recipientHandle,
158
+ path: FEDERATION_A2A_RPC_PATH,
159
+ body,
160
+ env: params.peerAuth.env
161
+ }) : undefined;
158
162
  return await fetchJson(params.fetchImpl, new URL("/a2a", params.origin), {
159
163
  method: "POST",
160
164
  headers: {
161
165
  "content-type": "application/json",
162
- ...params.headers
166
+ ...params.headers,
167
+ ...signed?.headers
163
168
  },
164
- body: JSON.stringify({
165
- jsonrpc: "2.0",
166
- id: "marketplace-ui",
167
- method: params.method,
168
- params: params.rpcParams
169
- })
169
+ body: signed?.body ?? JSON.stringify(body)
170
170
  });
171
171
  }
172
172
  function selectContentSummarizeOffer(params) {
@@ -217,7 +217,10 @@ async function waitForTaskCompletion(params) {
217
217
  fetchImpl: params.fetchImpl,
218
218
  origin: params.federationOrigin,
219
219
  method: "tasks.get",
220
- rpcParams: { taskId: params.taskId },
220
+ rpcParams: {
221
+ taskId: params.taskId,
222
+ taskAccessToken: params.taskAccessToken
223
+ },
221
224
  headers: params.headers
222
225
  });
223
226
  if (response.error) {
@@ -232,17 +235,35 @@ async function waitForTaskCompletion(params) {
232
235
  }
233
236
  throw new Error("timed out waiting for paid summarize result");
234
237
  }
235
- async function runPaidFederatedContentSummarize(request, deps = {}) {
238
+ async function runPaidFederatedContentSummarizeLocked(params) {
239
+ const { request, deps, executionIntentId, durable } = params;
240
+ const env = deps.env ?? process.env;
236
241
  const fetchImpl = deps.fetchImpl ?? fetch;
237
242
  const sleep = deps.sleep ?? (async (ms) => await setTimeout(ms));
238
243
  const now = deps.now ?? (() => new Date());
239
- const createId = deps.createId ?? createDefaultId;
240
244
  const loadConfigImpl = deps.loadConfig ?? loadConfig;
241
245
  const readWalletProviderRegistryImpl = deps.readWalletProviderRegistry ?? readWalletProviderRegistry;
242
246
  const resolveWalletRuntimeConfigImpl = deps.resolveWalletRuntimeConfig ?? resolveWalletRuntimeConfig;
243
247
  const loadPersistedFederationTokenImpl = deps.loadPersistedFederationToken ?? loadPersistedFederationToken;
244
248
  const createOrExecuteWalletSendImpl = deps.createOrExecuteWalletSend ?? createOrExecuteWalletSend;
245
249
  const publishFederationSettlementEvidenceImpl = deps.publishFederationSettlementEvidence ?? publishFederationSettlementEvidence;
250
+ if (durable.record.status === "completed") {
251
+ return durable.record.result;
252
+ }
253
+ if (durable.record.status === "failed" || durable.record.status === "refund_required") {
254
+ return {
255
+ status: "rejected",
256
+ reason: durable.record.reason ?? (durable.record.status === "refund_required" ? "Marketplace payment requires a refund or operator review" : "Marketplace run failed"),
257
+ handle: durable.record.prepared?.handle,
258
+ endpoint: durable.record.prepared?.endpoint,
259
+ offerId: durable.record.prepared?.offerId,
260
+ taskId: durable.record.prepared?.taskId,
261
+ invoiceId: durable.record.prepared?.invoiceId,
262
+ receiptId: durable.record.prepared?.receiptId,
263
+ txRef: durable.record.txRef,
264
+ payerAddress: durable.record.payerAddress
265
+ };
266
+ }
246
267
  const handle = trimString(request.handle);
247
268
  const offerId = trimString(request.offerId);
248
269
  const sourceText = trimString(request.sourceText);
@@ -270,16 +291,14 @@ async function runPaidFederatedContentSummarize(request, deps = {}) {
270
291
  }
271
292
  const quote = asRecord(request.quote);
272
293
  const amountInput = trimString(quote?.amountInput);
273
- const expiresInMinutesRaw = Number(quote?.expiresInMinutes ?? 5);
274
- const expiresInMinutes = Number.isFinite(expiresInMinutesRaw) && expiresInMinutesRaw >= 1 && expiresInMinutesRaw <= 60 ? Math.trunc(expiresInMinutesRaw) : 5;
275
- const federationOrigin = resolveFederationBaseUrl(process.env);
294
+ const federationOrigin = resolveFederationBaseUrl(env);
276
295
  if (!federationOrigin) {
277
296
  return {
278
297
  status: "rejected",
279
298
  reason: "federation base URL not configured"
280
299
  };
281
300
  }
282
- const token = await loadPersistedFederationTokenImpl(process.env);
301
+ const token = await loadPersistedFederationTokenImpl(env);
283
302
  if (!token?.tokenId || !token.handle) {
284
303
  return {
285
304
  status: "rejected",
@@ -299,156 +318,348 @@ async function runPaidFederatedContentSummarize(request, deps = {}) {
299
318
  reason: "paid marketplace run requires a verified federation token"
300
319
  };
301
320
  }
321
+ let prepared = durable.record.prepared;
302
322
  let selectedEntry = null;
303
- try {
304
- selectedEntry = await fetchContentSummarizeOfferFromDirectory({
305
- fetchImpl,
306
- federationOrigin,
307
- handle,
308
- offerId
309
- }) ?? await fetchContentSummarizeOfferFromMarketplaceIndex({
323
+ if (!prepared) {
324
+ try {
325
+ selectedEntry = await fetchContentSummarizeOfferFromDirectory({
326
+ fetchImpl,
327
+ federationOrigin,
328
+ handle,
329
+ offerId
330
+ }) ?? await fetchContentSummarizeOfferFromMarketplaceIndex({
331
+ fetchImpl,
332
+ federationOrigin,
333
+ handle,
334
+ offerId
335
+ });
336
+ } catch (error) {
337
+ return {
338
+ status: "rejected",
339
+ reason: `offer lookup failed: ${error instanceof Error ? error.message : String(error)}`
340
+ };
341
+ }
342
+ if (!selectedEntry?.endpoint) {
343
+ return {
344
+ status: "rejected",
345
+ reason: "content.summarize offer not found for verified handle in live offers or Marketplace index"
346
+ };
347
+ }
348
+ const offerPaymentDefaults = asRecord(selectedEntry.offer.paymentDefaults);
349
+ const offerPaymentAsset = asRecord(offerPaymentDefaults?.asset);
350
+ const offerPaymentPayee = asRecord(offerPaymentDefaults?.payee);
351
+ const currency = trimString(offerPaymentDefaults?.currency);
352
+ const offeredChain = trimString(offerPaymentDefaults?.chain).toLowerCase();
353
+ const offeredPayeeChain = trimString(offerPaymentPayee?.chain).toLowerCase();
354
+ const assetKindRaw = trimString(offerPaymentAsset?.kind);
355
+ const assetKind = assetKindRaw === "spl-token" ? "spl-token" : "native";
356
+ const payeeAddress = trimString(offerPaymentPayee?.address);
357
+ const offeredAssetAddress = trimString(offerPaymentAsset?.address);
358
+ const offeredDecimals = Number(offerPaymentDefaults?.assetDecimals);
359
+ const assetDecimals = parseAssetDecimals(offeredDecimals);
360
+ if (!currency || offeredChain !== "solana" || offeredPayeeChain !== "solana") {
361
+ return {
362
+ status: "rejected",
363
+ reason: "offer is missing canonical Solana payment defaults"
364
+ };
365
+ }
366
+ if (!payeeAddress) {
367
+ return {
368
+ status: "rejected",
369
+ reason: "offer is missing a canonical payee address"
370
+ };
371
+ }
372
+ if (assetDecimals === null) {
373
+ return {
374
+ status: "rejected",
375
+ reason: "offer asset decimals must be between 0 and 18"
376
+ };
377
+ }
378
+ if (trimString(quote?.currency) && trimString(quote?.currency) !== currency) {
379
+ return {
380
+ status: "rejected",
381
+ reason: "quote currency does not match the selected offer"
382
+ };
383
+ }
384
+ if (trimString(quote?.payeeAddress) && trimString(quote?.payeeAddress) !== payeeAddress) {
385
+ return {
386
+ status: "rejected",
387
+ reason: "quote payee does not match the selected offer"
388
+ };
389
+ }
390
+ if (trimString(quote?.assetKind) && trimString(quote?.assetKind) !== assetKind) {
391
+ return {
392
+ status: "rejected",
393
+ reason: "quote asset kind does not match the selected offer"
394
+ };
395
+ }
396
+ if (trimString(quote?.assetAddress) && trimString(quote?.assetAddress) !== offeredAssetAddress) {
397
+ return {
398
+ status: "rejected",
399
+ reason: "quote asset address does not match the selected offer"
400
+ };
401
+ }
402
+ const requestedDecimals = Number(quote?.assetDecimals);
403
+ if (Number.isFinite(requestedDecimals) && requestedDecimals !== offeredDecimals) {
404
+ return {
405
+ status: "rejected",
406
+ reason: "quote asset decimals do not match the selected offer"
407
+ };
408
+ }
409
+ let amountBaseUnits;
410
+ try {
411
+ amountBaseUnits = parseHumanAmountToOnChainInteger(amountInput, assetDecimals);
412
+ } catch (error) {
413
+ return {
414
+ status: "rejected",
415
+ reason: error instanceof Error ? error.message : String(error)
416
+ };
417
+ }
418
+ const offeredAmount = selectedEntry.offer.pricing?.amount;
419
+ if (typeof offeredAmount === "number" && Number.isFinite(offeredAmount)) {
420
+ let offeredBaseUnits;
421
+ try {
422
+ offeredBaseUnits = parseHumanAmountToOnChainInteger(String(offeredAmount), assetDecimals);
423
+ } catch {
424
+ return {
425
+ status: "rejected",
426
+ reason: "selected offer has an invalid canonical price"
427
+ };
428
+ }
429
+ if (amountBaseUnits !== offeredBaseUnits) {
430
+ return {
431
+ status: "rejected",
432
+ reason: "quote amount does not match the selected offer"
433
+ };
434
+ }
435
+ }
436
+ if (amountBaseUnits > MAX_SAFE_ON_CHAIN_INTEGER) {
437
+ return {
438
+ status: "rejected",
439
+ reason: "quote amount is too large for Invoice v0 / Receipt v0 numeric fields"
440
+ };
441
+ }
442
+ let asset;
443
+ try {
444
+ asset = toMarketplaceAsset(assetKind, offeredAssetAddress);
445
+ } catch (error) {
446
+ return {
447
+ status: "rejected",
448
+ reason: error instanceof Error ? error.message : String(error)
449
+ };
450
+ }
451
+ const registry = readWalletProviderRegistryImpl(env);
452
+ const paymentWallet = resolvePaymentWallet(registry, request.walletId);
453
+ if (!paymentWallet) {
454
+ return {
455
+ status: "rejected",
456
+ reason: "Agent wallet is not configured"
457
+ };
458
+ }
459
+ let walletAddress;
460
+ try {
461
+ walletAddress = resolveWalletAddress({
462
+ wallet: paymentWallet,
463
+ chain: "solana"
464
+ });
465
+ } catch (error) {
466
+ return {
467
+ status: "rejected",
468
+ reason: error instanceof Error ? error.message : String(error)
469
+ };
470
+ }
471
+ const issuedAt = now();
472
+ const taskId = stableMarketplaceRunId("market-summary", executionIntentId);
473
+ const challengeResponse = await rpcCall({
310
474
  fetchImpl,
311
- federationOrigin,
312
- handle,
313
- offerId
475
+ origin: federationOrigin,
476
+ method: "payments.prepare",
477
+ headers: { authorization: `Bearer ${token.tokenId}` },
478
+ peerAuth: {
479
+ senderHandle: token.handle,
480
+ recipientHandle: handle,
481
+ env
482
+ },
483
+ rpcParams: {
484
+ targetHandle: handle,
485
+ taskId,
486
+ offerId: trimString(selectedEntry.offer.id) || offerId,
487
+ payerAddress: walletAddress
488
+ }
314
489
  });
315
- } catch (error) {
316
- return {
317
- status: "rejected",
318
- reason: `offer lookup failed: ${error instanceof Error ? error.message : String(error)}`
319
- };
320
- }
321
- if (!selectedEntry?.endpoint) {
322
- return {
323
- status: "rejected",
324
- reason: "content.summarize offer not found for verified handle in live offers or Marketplace index"
325
- };
326
- }
327
- const offerPaymentDefaults = asRecord(selectedEntry.offer.paymentDefaults);
328
- const offerPaymentAsset = asRecord(offerPaymentDefaults?.asset);
329
- const offerPaymentPayee = asRecord(offerPaymentDefaults?.payee);
330
- const currency = trimString(quote?.currency) || trimString(offerPaymentDefaults?.currency);
331
- const chain = "solana";
332
- const assetKindRaw = trimString(quote?.assetKind) || trimString(offerPaymentAsset?.kind);
333
- const assetKind = assetKindRaw === "spl-token" ? "spl-token" : "native";
334
- const payeeAddress = trimString(quote?.payeeAddress) || trimString(offerPaymentPayee?.address);
335
- const assetDecimals = parseAssetDecimals(Number(quote?.assetDecimals ?? offerPaymentDefaults?.assetDecimals));
336
- if (!currency) {
337
- return {
338
- status: "rejected",
339
- reason: "missing quote currency"
340
- };
341
- }
342
- if (!payeeAddress) {
343
- return {
344
- status: "rejected",
345
- reason: "missing quote payee address"
346
- };
347
- }
348
- if (assetDecimals === null) {
349
- return {
350
- status: "rejected",
351
- reason: "asset decimals must be between 0 and 18"
352
- };
353
- }
354
- let amountBaseUnits;
355
- try {
356
- amountBaseUnits = parseHumanAmountToOnChainInteger(amountInput, assetDecimals);
357
- } catch (error) {
358
- return {
359
- status: "rejected",
360
- reason: error instanceof Error ? error.message : String(error)
361
- };
362
- }
363
- if (amountBaseUnits > MAX_SAFE_ON_CHAIN_INTEGER) {
364
- return {
365
- status: "rejected",
366
- reason: "quote amount is too large for Invoice v0 / Receipt v0 numeric fields"
367
- };
368
- }
369
- const canonicalOfferId = trimString(selectedEntry.offer.id) || offerId;
370
- let asset;
371
- try {
372
- asset = toMarketplaceAsset(assetKind, trimString(quote?.assetAddress) || trimString(offerPaymentAsset?.address));
373
- } catch (error) {
374
- return {
375
- status: "rejected",
376
- reason: error instanceof Error ? error.message : String(error)
490
+ if (challengeResponse.error) {
491
+ return {
492
+ status: "rejected",
493
+ reason: `payment challenge failed: ${formatRpcRejectionDetail(challengeResponse.error)}`
494
+ };
495
+ }
496
+ const challenge = asRecord(challengeResponse.result);
497
+ const challengeId = trimString(challenge?.challengeId);
498
+ const paymentMemo = trimString(challenge?.paymentMemo);
499
+ const challengeInvoiceId = trimString(challenge?.invoiceId);
500
+ const challengeReceiptId = trimString(challenge?.receiptId);
501
+ const challengeIssuedAt = trimString(challenge?.issuedAt);
502
+ const challengeExpiresAt = trimString(challenge?.expiresAt);
503
+ const challengeAsset = asRecord(challenge?.asset);
504
+ if (!/^[0-9a-f]{64}$/u.test(challengeId) || paymentMemo !== `fased:a2a-payment:v1:${challengeId}` || !challengeInvoiceId || !challengeReceiptId || trimString(challenge?.taskId) !== taskId || !offerIdsMatch(trimString(challenge?.offerId), trimString(selectedEntry.offer.id) || offerId) || trimString(challenge?.senderHandle).toLowerCase() !== token.handle.trim().toLowerCase() || trimString(challenge?.payerAddress) !== walletAddress || trimString(challenge?.payeeAddress) !== payeeAddress || Number(challenge?.amount) !== Number(amountBaseUnits) || trimString(challenge?.currency).toUpperCase() !== currency.toUpperCase() || trimString(challengeAsset?.kind) !== asset.kind || trimString(challengeAsset?.address) !== trimString(asset.address) || !Number.isFinite(Date.parse(challengeIssuedAt)) || !Number.isFinite(Date.parse(challengeExpiresAt)) || Date.parse(challengeIssuedAt) > issuedAt.getTime() + 6e4 || Date.parse(challengeExpiresAt) <= issuedAt.getTime()) {
505
+ return {
506
+ status: "rejected",
507
+ reason: "seller returned an invalid payment challenge"
508
+ };
509
+ }
510
+ prepared = {
511
+ handle,
512
+ endpoint: selectedEntry.endpoint,
513
+ offerId: trimString(selectedEntry.offer.id) || offerId,
514
+ walletId: paymentWallet.id,
515
+ walletName: paymentWallet.name,
516
+ providerId: paymentWallet.providerId,
517
+ walletAddress,
518
+ senderHandle: token.handle,
519
+ taskId,
520
+ challengeId,
521
+ paymentMemo,
522
+ invoiceId: challengeInvoiceId,
523
+ receiptId: challengeReceiptId,
524
+ taskAccessToken: createMarketplaceTaskAccessToken(),
525
+ sourceText,
526
+ requestedOutput,
527
+ summaryStyle,
528
+ maxSentences,
529
+ amount: amountBaseUnits.toString(),
530
+ currency,
531
+ asset,
532
+ payeeAddress,
533
+ issuedAt: challengeIssuedAt,
534
+ expiresAt: challengeExpiresAt,
535
+ settledAt: challengeIssuedAt
377
536
  };
537
+ durable.update({
538
+ status: "payment_pending",
539
+ patch: { prepared }
540
+ });
378
541
  }
379
- const registry = readWalletProviderRegistryImpl(process.env);
380
- const defaultWallet = resolvePaymentWallet(registry, request.walletId);
381
- if (!defaultWallet) {
382
- return {
383
- status: "rejected",
384
- reason: "Agent wallet is not configured"
385
- };
542
+ if (durable.record.status === "reserved") {
543
+ durable.update({
544
+ status: "payment_pending",
545
+ patch: { prepared }
546
+ });
386
547
  }
387
- const cfg = loadConfigImpl();
388
- const walletConfig = resolveWalletRuntimeConfigImpl(cfg, process.env);
389
- if (!walletConfig.enabled) {
548
+ if (!prepared) {
390
549
  return {
391
550
  status: "rejected",
392
- reason: "wallet runtime is disabled"
551
+ reason: "durable Marketplace payment state is incomplete; refusing execution"
393
552
  };
394
553
  }
395
- const taskId = createId("market-summary");
396
- const invoiceId = createId("invoice");
397
- const receiptId = createId("receipt");
398
- const send = await createOrExecuteWalletSendImpl({
399
- payload: {
400
- chain,
401
- to: payeeAddress,
402
- amount: amountBaseUnits.toString(),
403
- ...asset.kind === "spl-token" ? { program: asset.address } : {},
404
- walletId: defaultWallet.id,
405
- walletName: defaultWallet.name,
406
- providerId: defaultWallet.providerId,
407
- memo: invoiceId
408
- },
409
- requestedBy: "marketplace-runner",
410
- sendPath: "automation",
411
- settlementContext: {
412
- taskId,
413
- invoiceId,
414
- senderHandle: token.handle
415
- },
416
- config: walletConfig,
417
- runtimeConfig: cfg,
418
- providerIdOverride: defaultWallet.providerId,
419
- env: process.env
420
- });
421
- if (!send.ok) {
422
- return {
423
- status: "rejected",
424
- reason: normalizeMarketplacePaymentFailure(send.message)
554
+ if (durable.record.status === "payment_pending" || durable.record.status === "unknown") {
555
+ const registry = readWalletProviderRegistryImpl(env);
556
+ const preparedWalletId = prepared.walletId;
557
+ const paymentWallet = registry.wallets.find((wallet) => wallet.id === preparedWalletId);
558
+ if (!paymentWallet || resolveWalletUserRole(paymentWallet) !== "agent" || paymentWallet.providerId !== prepared.providerId || paymentWallet.name !== prepared.walletName) {
559
+ return {
560
+ status: "rejected",
561
+ reason: "the prepared Marketplace Agent wallet is no longer available for reconciliation"
562
+ };
563
+ }
564
+ const cfg = loadConfigImpl();
565
+ const walletConfig = resolveWalletRuntimeConfigImpl(cfg, env);
566
+ if (!walletConfig.enabled) {
567
+ return {
568
+ status: "rejected",
569
+ reason: "wallet runtime is disabled"
570
+ };
571
+ }
572
+ const send = await createOrExecuteWalletSendImpl({
573
+ payload: {
574
+ chain: "solana",
575
+ to: prepared.payeeAddress,
576
+ amount: prepared.amount,
577
+ ...prepared.asset.kind === "spl-token" ? { program: prepared.asset.address } : {},
578
+ walletId: prepared.walletId,
579
+ walletName: prepared.walletName,
580
+ providerId: prepared.providerId,
581
+ memo: prepared.paymentMemo
582
+ },
583
+ requestedBy: "marketplace-runner",
584
+ executionIntentId,
585
+ sendPath: "automation",
586
+ settlementContext: {
587
+ taskId: prepared.taskId,
588
+ invoiceId: prepared.invoiceId,
589
+ senderHandle: prepared.senderHandle
590
+ },
591
+ config: walletConfig,
592
+ runtimeConfig: cfg,
593
+ providerIdOverride: prepared.providerId,
594
+ env
595
+ });
596
+ if (!send.ok) {
597
+ const ambiguous = send.code === "wallet_provider_ambiguous" || send.code === "wallet_send_in_progress";
598
+ durable.update({
599
+ status: ambiguous ? "unknown" : "failed",
600
+ patch: { reason: normalizeMarketplacePaymentFailure(send.message) }
601
+ });
602
+ return {
603
+ status: "rejected",
604
+ reason: normalizeMarketplacePaymentFailure(send.message)
605
+ };
606
+ }
607
+ if (send.mode !== "autonomous") {
608
+ const reason = "paid marketplace run requires Payment automation to be enabled";
609
+ durable.update({
610
+ status: "failed",
611
+ patch: { reason }
612
+ });
613
+ return {
614
+ status: "rejected",
615
+ reason
616
+ };
617
+ }
618
+ const txRef = trimString(send.tx.txHash);
619
+ const payerAddress = resolveWalletAddress({
620
+ wallet: paymentWallet,
621
+ chain: "solana",
622
+ txSigner: typeof send.tx.signer === "string" ? send.tx.signer : undefined
623
+ });
624
+ prepared = {
625
+ ...prepared,
626
+ settledAt: now().toISOString()
425
627
  };
628
+ durable.update({
629
+ status: "paid",
630
+ patch: {
631
+ txRef,
632
+ payerAddress,
633
+ prepared,
634
+ reason: undefined
635
+ }
636
+ });
426
637
  }
427
- if (send.mode !== "autonomous") {
638
+ const txRef = trimString(durable.record.txRef);
639
+ const payerAddress = trimString(durable.record.payerAddress);
640
+ if (!txRef || !payerAddress) {
641
+ durable.update({
642
+ status: "unknown",
643
+ patch: { reason: "Marketplace payment state is incomplete and requires reconciliation" }
644
+ });
428
645
  return {
429
646
  status: "rejected",
430
- reason: "paid marketplace run requires Payment automation to be enabled"
647
+ reason: "Marketplace payment state is incomplete and requires reconciliation"
431
648
  };
432
649
  }
433
- const txRef = trimString(send.tx.txHash);
434
- const payerAddress = resolveWalletAddress({
435
- wallet: defaultWallet,
436
- chain,
437
- txSigner: typeof send.tx.signer === "string" ? send.tx.signer : undefined
438
- });
439
650
  const publishSettlement = await publishFederationSettlementEvidenceImpl({
440
- taskId,
441
- invoiceId,
442
- senderHandle: token.handle,
651
+ taskId: prepared.taskId,
652
+ invoiceId: prepared.invoiceId,
653
+ senderHandle: prepared.senderHandle,
443
654
  txRef,
444
- chain,
445
- asset,
446
- amount: amountBaseUnits.toString(),
447
- payeeAddress,
448
- providerId: defaultWallet.providerId,
449
- walletId: defaultWallet.id,
450
- walletName: defaultWallet.name,
451
- env: process.env
655
+ chain: "solana",
656
+ asset: prepared.asset,
657
+ amount: prepared.amount,
658
+ payeeAddress: prepared.payeeAddress,
659
+ providerId: prepared.providerId,
660
+ walletId: prepared.walletId,
661
+ walletName: prepared.walletName,
662
+ env
452
663
  });
453
664
  if (!publishSettlement.ok) {
454
665
  return {
@@ -456,141 +667,235 @@ async function runPaidFederatedContentSummarize(request, deps = {}) {
456
667
  reason: `settlement evidence publish failed: ${publishSettlement.message}`
457
668
  };
458
669
  }
459
- const issuedAt = now();
460
- const expiresAt = new Date(issuedAt.getTime() + expiresInMinutes * 6e4);
461
- const settledAt = now().toISOString();
462
- const headers = {
463
- authorization: `Bearer ${token.tokenId}`,
464
- "x-fased-sender-handle": token.handle,
465
- "x-fased-request-nonce": randomUUID(),
466
- "x-fased-request-ts": String(Date.now())
467
- };
468
- let createdTaskId = taskId;
469
- try {
670
+ const headers = { authorization: `Bearer ${token.tokenId}` };
671
+ if (durable.record.status === "paid") {
470
672
  const createResponse = await rpcCall({
471
673
  fetchImpl,
472
674
  origin: federationOrigin,
473
675
  method: "tasks.create",
474
676
  headers,
677
+ peerAuth: {
678
+ senderHandle: token.handle,
679
+ recipientHandle: handle,
680
+ env
681
+ },
475
682
  rpcParams: {
476
- targetHandle: handle,
683
+ targetHandle: prepared.handle,
684
+ taskAccessToken: prepared.taskAccessToken,
477
685
  task: {
478
686
  schema: TASK_SCHEMA,
479
- taskId,
480
- from: token.handle,
481
- to: handle,
482
- offerId: canonicalOfferId,
687
+ taskId: prepared.taskId,
688
+ from: prepared.senderHandle,
689
+ to: prepared.handle,
690
+ offerId: prepared.offerId,
483
691
  serviceKind: "content.summarize",
484
- prompt: sourceText,
485
- requestedOutput,
692
+ prompt: prepared.sourceText,
693
+ requestedOutput: prepared.requestedOutput,
486
694
  serviceParams: {
487
- summaryStyle,
488
- maxSentences
695
+ summaryStyle: prepared.summaryStyle,
696
+ maxSentences: prepared.maxSentences
489
697
  },
490
- invoice: invoiceId,
491
- receipt: receiptId,
492
- issuedAt: issuedAt.toISOString()
698
+ invoice: prepared.invoiceId,
699
+ receipt: prepared.receiptId,
700
+ issuedAt: prepared.issuedAt,
701
+ challengeId: prepared.challengeId
493
702
  },
494
703
  invoice: {
495
704
  schema: INVOICE_SCHEMA,
496
- invoiceId,
497
- taskId,
498
- offerId: canonicalOfferId,
499
- amount: Number(amountBaseUnits),
500
- currency,
501
- chain,
502
- asset,
705
+ invoiceId: prepared.invoiceId,
706
+ challengeId: prepared.challengeId,
707
+ paymentMemo: prepared.paymentMemo,
708
+ taskId: prepared.taskId,
709
+ offerId: prepared.offerId,
710
+ amount: Number(prepared.amount),
711
+ currency: prepared.currency,
712
+ chain: "solana",
713
+ asset: prepared.asset,
503
714
  payee: {
504
- chain,
505
- address: payeeAddress
715
+ chain: "solana",
716
+ address: prepared.payeeAddress
506
717
  },
507
- issuedAt: issuedAt.toISOString(),
508
- expiresAt: expiresAt.toISOString()
718
+ issuedAt: prepared.issuedAt,
719
+ expiresAt: prepared.expiresAt
509
720
  },
510
721
  receipt: {
511
722
  schema: RECEIPT_SCHEMA,
512
- receiptId,
513
- invoiceId,
514
- taskId,
515
- offerId: canonicalOfferId,
516
- amount: Number(amountBaseUnits),
517
- currency,
518
- chain,
519
- asset,
723
+ receiptId: prepared.receiptId,
724
+ challengeId: prepared.challengeId,
725
+ paymentMemo: prepared.paymentMemo,
726
+ invoiceId: prepared.invoiceId,
727
+ taskId: prepared.taskId,
728
+ offerId: prepared.offerId,
729
+ amount: Number(prepared.amount),
730
+ currency: prepared.currency,
731
+ chain: "solana",
732
+ asset: prepared.asset,
520
733
  payer: {
521
- chain,
734
+ chain: "solana",
522
735
  address: payerAddress
523
736
  },
524
737
  payee: {
525
- chain,
526
- address: payeeAddress
738
+ chain: "solana",
739
+ address: prepared.payeeAddress
527
740
  },
528
741
  txRef,
529
- settledAt
742
+ settledAt: prepared.settledAt
530
743
  }
531
744
  }
532
745
  });
533
746
  if (createResponse.error) {
747
+ const reason = `tasks.create failed after payment: ${formatRpcRejectionDetail(createResponse.error)}`;
748
+ durable.update({
749
+ status: "refund_required",
750
+ patch: { reason }
751
+ });
534
752
  return {
535
753
  status: "rejected",
536
- reason: `tasks.create failed: ${formatRpcRejectionDetail(createResponse.error)}`
754
+ reason
537
755
  };
538
756
  }
539
- createdTaskId = trimString(createResponse.result?.taskId) || taskId;
757
+ const createdTaskId = trimString(createResponse.result?.taskId) || prepared.taskId;
758
+ if (createdTaskId !== prepared.taskId) {
759
+ const reason = "tasks.create returned a different task identity after payment";
760
+ durable.update({
761
+ status: "refund_required",
762
+ patch: { reason }
763
+ });
764
+ return {
765
+ status: "rejected",
766
+ reason
767
+ };
768
+ }
769
+ durable.update({
770
+ status: "task_created",
771
+ patch: { taskCreatedAt: now().toISOString() }
772
+ });
773
+ }
774
+ try {
540
775
  const snapshot = await waitForTaskCompletion({
541
776
  fetchImpl,
542
777
  federationOrigin,
543
- taskId: createdTaskId,
778
+ taskId: prepared.taskId,
544
779
  headers: {
545
780
  authorization: `Bearer ${token.tokenId}`,
546
- "x-fased-sender-handle": token.handle
781
+ "x-fased-task-token": prepared.taskAccessToken
547
782
  },
783
+ taskAccessToken: prepared.taskAccessToken,
548
784
  sleep
549
785
  });
550
786
  const output = asRecord(snapshot?.output) ?? {};
551
787
  const result = asRecord(output.result) ?? {};
552
788
  const payment = asRecord(output.payment) ?? {};
789
+ const paymentProof = asRecord(snapshot?.paymentProof) ?? {};
553
790
  const resultKind = trimString(result.kind);
554
- const paymentStatus = trimString(payment.status) || trimString(asRecord(snapshot?.paymentProof)?.status);
791
+ const paymentStatus = trimString(payment.status) || trimString(paymentProof.status);
555
792
  if (resultKind !== CONTENT_SUMMARIZE_RESULT_KIND) {
793
+ const reason = `unexpected result kind: ${resultKind || "missing"}`;
794
+ durable.update({
795
+ status: "refund_required",
796
+ patch: { reason }
797
+ });
556
798
  return {
557
799
  status: "rejected",
558
- reason: `unexpected result kind: ${resultKind || "missing"}`
800
+ reason
559
801
  };
560
802
  }
561
803
  if (paymentStatus !== "verified") {
804
+ const reason = `paid summarize completed without verified payment: ${paymentStatus || "missing"}`;
805
+ durable.update({
806
+ status: "refund_required",
807
+ patch: { reason }
808
+ });
562
809
  return {
563
810
  status: "rejected",
564
- reason: `paid summarize completed without verified payment: ${paymentStatus || "missing"}`
811
+ reason
565
812
  };
566
813
  }
567
- return {
814
+ const paymentLinkage = {
815
+ offerId: trimString(payment.offerId),
816
+ invoiceId: trimString(payment.invoiceId),
817
+ receiptId: trimString(payment.receiptId),
818
+ txRef: trimString(payment.txRef),
819
+ proofInvoiceId: trimString(paymentProof.invoiceId),
820
+ proofReceiptId: trimString(paymentProof.receiptId),
821
+ proofTxRef: trimString(paymentProof.txRef)
822
+ };
823
+ if (!offerIdsMatch(paymentLinkage.offerId, prepared.offerId) || paymentLinkage.invoiceId !== prepared.invoiceId || paymentLinkage.receiptId !== prepared.receiptId || paymentLinkage.txRef !== txRef || paymentLinkage.proofInvoiceId !== prepared.invoiceId || paymentLinkage.proofReceiptId !== prepared.receiptId || paymentLinkage.proofTxRef !== txRef) {
824
+ const reason = "paid summarize completion did not match the exact offer, invoice, receipt, and transaction";
825
+ durable.update({
826
+ status: "refund_required",
827
+ patch: { reason }
828
+ });
829
+ return {
830
+ status: "rejected",
831
+ reason
832
+ };
833
+ }
834
+ const accepted = {
568
835
  status: "accepted",
569
- handle,
570
- endpoint: selectedEntry.endpoint,
571
- offerId: canonicalOfferId,
572
- taskId: createdTaskId,
573
- invoiceId,
574
- receiptId,
836
+ handle: prepared.handle,
837
+ endpoint: prepared.endpoint,
838
+ offerId: prepared.offerId,
839
+ taskId: prepared.taskId,
840
+ invoiceId: prepared.invoiceId,
841
+ receiptId: prepared.receiptId,
575
842
  txRef,
576
843
  payerAddress,
577
844
  snapshot
578
845
  };
846
+ durable.update({
847
+ status: "completed",
848
+ patch: {
849
+ result: accepted,
850
+ reason: undefined
851
+ }
852
+ });
853
+ return accepted;
579
854
  } catch (error) {
580
855
  return {
581
856
  status: "rejected",
582
857
  reason: error instanceof Error ? error.message : String(error),
583
- handle,
584
- endpoint: selectedEntry.endpoint,
585
- offerId: canonicalOfferId,
586
- taskId: createdTaskId,
587
- invoiceId,
588
- receiptId,
858
+ handle: prepared.handle,
859
+ endpoint: prepared.endpoint,
860
+ offerId: prepared.offerId,
861
+ taskId: prepared.taskId,
862
+ invoiceId: prepared.invoiceId,
863
+ receiptId: prepared.receiptId,
589
864
  txRef,
590
865
  payerAddress
591
866
  };
592
867
  }
593
868
  }
869
+ async function runPaidFederatedContentSummarize(request, deps = {}) {
870
+ const executionIntentId = trimString(request.executionIntentId);
871
+ if (!executionIntentId) {
872
+ return {
873
+ status: "rejected",
874
+ reason: "paid marketplace run requires a stable executionIntentId"
875
+ };
876
+ }
877
+ try {
878
+ return await withDurableMarketplaceRun({
879
+ executionIntentId,
880
+ intent: {
881
+ version: 1,
882
+ request
883
+ },
884
+ env: deps.env,
885
+ run: async (durable) => await runPaidFederatedContentSummarizeLocked({
886
+ request,
887
+ deps,
888
+ executionIntentId,
889
+ durable
890
+ })
891
+ });
892
+ } catch (error) {
893
+ return {
894
+ status: "rejected",
895
+ reason: error instanceof Error ? error.message : String(error)
896
+ };
897
+ }
898
+ }
594
899
 
595
900
  //#endregion
596
901
  export { runPaidFederatedContentSummarize };