@stelis/say-ur-intent 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -39
- package/dist/adapters/adapterLifecycleValidators.js +7 -0
- package/dist/adapters/adapterPromptSurfaces.js +71 -0
- package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +175 -0
- package/dist/adapters/deepbook/deepbookQuotePolicy.js +112 -0
- package/dist/adapters/deepbook/deepbookReviewEvidence.js +507 -0
- package/dist/adapters/deepbook/deepbookReviewLifecycle.js +85 -0
- package/dist/adapters/deepbook/deepbookSwapIntent.js +79 -0
- package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +269 -0
- package/dist/adapters/flowx/flowxSwapHumanReviewProducer.js +176 -0
- package/dist/adapters/flowx/flowxSwapIntent.js +79 -0
- package/dist/adapters/flowx/flowxSwapQuotePolicy.js +104 -0
- package/dist/adapters/flowx/flowxSwapReviewEvidence.js +468 -0
- package/dist/adapters/flowx/flowxSwapReviewLifecycle.js +85 -0
- package/dist/adapters/flowx/flowxSwapTransactionMaterialProducer.js +362 -0
- package/dist/adapters/intentPlanFactories.js +59 -0
- package/dist/adapters/reviewAdapters.js +81 -0
- package/dist/core/action/adapterLifecycleValidation.js +12 -0
- package/dist/core/action/forbiddenFields.js +43 -0
- package/dist/core/action/humanReadableReviewEvidence.js +203 -0
- package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
- package/dist/core/action/ptbVisualizationProducer.js +66 -0
- package/dist/core/action/reviewCheckResults.js +6 -0
- package/dist/core/action/reviewStateValidation.js +11 -0
- package/dist/core/action/reviewTimeSimulationEvidence.js +471 -0
- package/dist/core/action/schemas.js +529 -0
- package/dist/core/action/signableAdapterContract.js +993 -0
- package/dist/core/action/swapHumanReadableReviewProjection.js +124 -0
- package/dist/core/action/swapQuotePolicyEvidence.js +278 -0
- package/dist/core/action/transactionObjectOwnershipEvidence.js +247 -0
- package/dist/core/action/transactionObjectOwnershipProducer.js +329 -0
- package/dist/core/action/types.js +35 -0
- package/dist/core/action/walletReviewContractAssembler.js +282 -0
- package/dist/core/activity/activityStore.js +15 -0
- package/dist/core/activity/localDataService.js +258 -0
- package/dist/core/activity/localDataTypes.js +11 -0
- package/dist/core/activity/localDataValidation.js +396 -0
- package/dist/core/activity/schemaVersion.js +1 -0
- package/dist/core/activity/sqliteActivityStore.js +820 -0
- package/dist/core/activity/sqliteActivityStoreRows.js +430 -0
- package/dist/core/activity/sqliteActivityStoreSchema.js +258 -0
- package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
- package/dist/core/activity/suiFunctionTarget.js +43 -0
- package/dist/core/activity/transactionActivityAccountEffects.js +189 -0
- package/dist/core/activity/transactionActivityAnalysis.js +295 -0
- package/dist/core/activity/transactionActivityClassifier.js +306 -0
- package/dist/core/activity/transactionActivityDetails.js +229 -0
- package/dist/core/activity/transactionActivityProtocolRules.js +218 -0
- package/dist/core/activity/transactionActivityScanPolicy.js +170 -0
- package/dist/core/activity/transactionActivityService.js +379 -0
- package/dist/core/activity/transactionActivityTypes.js +18 -0
- package/dist/core/eventlog/sink.js +35 -0
- package/dist/core/evidence/settlementFamilies.js +87 -0
- package/dist/core/evidence/userAnswerUse.js +1 -0
- package/dist/core/numeric/rawU64.js +63 -0
- package/dist/core/preferences/preferencesStore.js +26 -0
- package/dist/core/preferences/sqlitePreferencesRepository.js +136 -0
- package/dist/core/proposal/externalProposalReview.js +347 -0
- package/dist/core/proposal/schemas.js +208 -0
- package/dist/core/proposal/types.js +35 -0
- package/dist/core/read/amounts.js +14 -0
- package/dist/core/read/coinMetadata.js +60 -0
- package/dist/core/read/deepbookRawQuoteClient.js +86 -0
- package/dist/core/read/deepbookReadHelpers.js +265 -0
- package/dist/core/read/deepbookRegistry.js +133 -0
- package/dist/core/read/flowxQuoteClient.js +117 -0
- package/dist/core/read/flowxReadHelpers.js +145 -0
- package/dist/core/read/flowxRegistry.js +174 -0
- package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
- package/dist/core/read/readResponseGuidance.js +451 -0
- package/dist/core/read/readService.js +1164 -0
- package/dist/core/read/readServiceTypes.js +59 -0
- package/dist/core/read/settlementParityFormatting.js +82 -0
- package/dist/core/read/walletReadHelpers.js +99 -0
- package/dist/core/review/reviewChecks.js +54 -0
- package/dist/core/review/reviewComputation.js +38 -0
- package/dist/core/review/reviewComputationResult.js +87 -0
- package/dist/core/session/localSession.js +31 -0
- package/dist/core/session/privateReviewArtifacts.js +73 -0
- package/dist/core/session/sessionErrors.js +9 -0
- package/dist/core/session/sessionStore.js +821 -0
- package/dist/core/session/settingsSession.js +1 -0
- package/dist/core/session/settingsSessions.js +43 -0
- package/dist/core/session/status.js +86 -0
- package/dist/core/session/transactionMaterialStore.js +205 -0
- package/dist/core/session/wait.js +102 -0
- package/dist/core/session/walletIdentity.js +103 -0
- package/dist/core/session/walletIdentitySessions.js +189 -0
- package/dist/core/suiAddress.js +18 -0
- package/dist/core/suiEndpoint.js +72 -0
- package/dist/mcp/activeAccountResponse.js +24 -0
- package/dist/mcp/prompts.js +146 -0
- package/dist/mcp/registerTool.js +19 -0
- package/dist/mcp/resources.js +72 -0
- package/dist/mcp/responseGuidance.js +381 -0
- package/dist/mcp/result.js +17 -0
- package/dist/mcp/schemas.js +8 -0
- package/dist/mcp/server.js +30 -0
- package/dist/mcp/serverInfo.js +123 -0
- package/dist/mcp/toolErrors.js +105 -0
- package/dist/mcp/toolNames.js +50 -0
- package/dist/mcp/tools/account/index.js +44 -0
- package/dist/mcp/tools/action/prepareSuiActionReview.js +120 -0
- package/dist/mcp/tools/read/commonSchemas.js +43 -0
- package/dist/mcp/tools/read/deepbookReadTools.js +453 -0
- package/dist/mcp/tools/read/flowxReadTools.js +135 -0
- package/dist/mcp/tools/read/index.js +16 -0
- package/dist/mcp/tools/read/readToolHelpers.js +68 -0
- package/dist/mcp/tools/read/reviewActivityTools.js +176 -0
- package/dist/mcp/tools/read/serverStatusTools.js +103 -0
- package/dist/mcp/tools/read/transactionActivityOutput.js +300 -0
- package/dist/mcp/tools/read/transactionActivityTools.js +544 -0
- package/dist/mcp/tools/read/walletReadTools.js +733 -0
- package/dist/mcp/tools/session/executionResultTools.js +92 -0
- package/dist/mcp/tools/session/index.js +8 -0
- package/dist/mcp/tools/session/shared.js +79 -0
- package/dist/mcp/tools/session/statusTools.js +134 -0
- package/dist/mcp/tools/session/walletIdentityTools.js +119 -0
- package/dist/mcp/tools/settings/index.js +64 -0
- package/dist/review-app/analysis.css +1 -0
- package/dist/review-app/analysis.js +1 -0
- package/dist/review-app/arc-BjIacwQm.js +1 -0
- package/dist/review-app/architecture-U656AL7Q-aSB9x1OK.js +1 -0
- package/dist/review-app/architectureDiagram-VXUJARFQ-C5W6re2I.js +36 -0
- package/dist/review-app/array-BmXUUrU6.js +1 -0
- package/dist/review-app/blockDiagram-VD42YOAC-20MLNcUm.js +122 -0
- package/dist/review-app/c4Diagram-YG6GDRKO-BZXRrcck.js +10 -0
- package/dist/review-app/channel-lk2p_CUu.js +1 -0
- package/dist/review-app/chunk-4BX2VUAB-BPITOdjX.js +1 -0
- package/dist/review-app/chunk-55IACEB6-Dz-pyw5k.js +1 -0
- package/dist/review-app/chunk-76Q3JFCE-cK_X1P_l.js +1 -0
- package/dist/review-app/chunk-ABZYJK2D-Dt4W53JI.js +81 -0
- package/dist/review-app/chunk-ATLVNIR6-fZHLXURb.js +1 -0
- package/dist/review-app/chunk-B4BG7PRW-BbgcjusC.js +165 -0
- package/dist/review-app/chunk-BJD4TVEz.js +1 -0
- package/dist/review-app/chunk-CVBHYZKI-CViawAKX.js +1 -0
- package/dist/review-app/chunk-DI55MBZ5-C5aoul-d.js +220 -0
- package/dist/review-app/chunk-FMBD7UC4-Chxmw62A.js +15 -0
- package/dist/review-app/chunk-FPAJGGOC-DDHjQ09H.js +80 -0
- package/dist/review-app/chunk-FWNWRKHM-CVVQUptk.js +1 -0
- package/dist/review-app/chunk-HN2XXSSU-yzNpjaSZ.js +1 -0
- package/dist/review-app/chunk-JA3XYJ7Z-C5ZJdU01.js +70 -0
- package/dist/review-app/chunk-JZLCHNYA-BBST4Cnk.js +54 -0
- package/dist/review-app/chunk-LBM3YZW2-CdwAPuHr.js +1 -0
- package/dist/review-app/chunk-LHMN2FUI-BtB5uDcp.js +1 -0
- package/dist/review-app/chunk-O7ZBX7Z2-pxdK4Sa3.js +1 -0
- package/dist/review-app/chunk-QN33PNHL-CbVv3uGK.js +1 -0
- package/dist/review-app/chunk-QXUST7PY-DKM2-t2c.js +7 -0
- package/dist/review-app/chunk-QZHKN3VN-C5ni2pN_.js +1 -0
- package/dist/review-app/chunk-S3R3BYOJ-BWvOhDs0.js +2 -0
- package/dist/review-app/chunk-S6J4BHB3-D9Fk0YeD.js +1 -0
- package/dist/review-app/chunk-T53DSG4Q-C1qEyzyV.js +1 -0
- package/dist/review-app/chunk-TZMSLE5B-B--7eU69.js +1 -0
- package/dist/review-app/classDiagram-2ON5EDUG-DlL1m2bp.js +1 -0
- package/dist/review-app/classDiagram-v2-WZHVMYZB-FXRskT1j.js +1 -0
- package/dist/review-app/clone-BZZb7gpZ.js +1 -0
- package/dist/review-app/cose-bilkent-S5V4N54A-CRIb8XEO.js +1 -0
- package/dist/review-app/cytoscape.esm-C7jYqDP5.js +321 -0
- package/dist/review-app/dagre-6UL2VRFP-FNCAXbdE.js +4 -0
- package/dist/review-app/dagre-Be46QtUd.js +1 -0
- package/dist/review-app/defaultLocale-BaWNtAUL.js +1 -0
- package/dist/review-app/diagram-PSM6KHXK-ylLWjiNM.js +24 -0
- package/dist/review-app/diagram-QEK2KX5R-BCDcESxs.js +43 -0
- package/dist/review-app/diagram-S2PKOQOG-Vdrc-vrO.js +24 -0
- package/dist/review-app/dist-WPc74x_f.js +1 -0
- package/dist/review-app/erDiagram-Q2GNP2WA-E5ZsUbDF.js +60 -0
- package/dist/review-app/flatten-DHf9IeNI.js +1 -0
- package/dist/review-app/flowDiagram-NV44I4VS-DBSQuj6x.js +162 -0
- package/dist/review-app/ganttDiagram-LVOFAZNH-CKUOsqwl.js +267 -0
- package/dist/review-app/gitGraph-F6HP7TQM-DsAD6qK1.js +1 -0
- package/dist/review-app/gitGraphDiagram-NY62KEGX-BCeIMWdl.js +65 -0
- package/dist/review-app/graphlib-CiX5CXxR.js +1 -0
- package/dist/review-app/http-DMvwuuFk.js +1 -0
- package/dist/review-app/identity-DY8PXc6t.js +1 -0
- package/dist/review-app/info-NVLQJR56-Dlx1nZic.js +1 -0
- package/dist/review-app/infoDiagram-F6ZHWCRC-CAuANIrz.js +2 -0
- package/dist/review-app/init-BvqephKz.js +1 -0
- package/dist/review-app/journeyDiagram-XKPGCS4Q-C-Z9phnx.js +139 -0
- package/dist/review-app/kanban-definition-3W4ZIXB7-DufgZABq.js +89 -0
- package/dist/review-app/katex-B-Z-NXXN.js +257 -0
- package/dist/review-app/line-DiIv3Jgw.js +1 -0
- package/dist/review-app/linear-Cv-UPvo1.js +1 -0
- package/dist/review-app/math-kmyYrkHL.js +1 -0
- package/dist/review-app/mermaid-parser.core-DkwUYTPl.js +4 -0
- package/dist/review-app/mindmap-definition-VGOIOE7T-TM_CqdmV.js +68 -0
- package/dist/review-app/ordinal-BliTlkoG.js +1 -0
- package/dist/review-app/packet-BFZMPI3H-DqbnU92v.js +1 -0
- package/dist/review-app/path-AEo9W6mQ.js +1 -0
- package/dist/review-app/pie-7BOR55EZ-LJzaLkgr.js +1 -0
- package/dist/review-app/pieDiagram-ADFJNKIX-BAs8OfRS.js +30 -0
- package/dist/review-app/quadrantDiagram-AYHSOK5B-CyUDZP5S.js +7 -0
- package/dist/review-app/radar-NHE76QYJ-DBpHc8_Y.js +1 -0
- package/dist/review-app/reduce-B-HuPpdd.js +1 -0
- package/dist/review-app/requirementDiagram-UZGBJVZJ-BEHix78P.js +64 -0
- package/dist/review-app/review.css +1 -0
- package/dist/review-app/review.js +43 -0
- package/dist/review-app/sankeyDiagram-TZEHDZUN-B2bKbmsm.js +10 -0
- package/dist/review-app/sequenceDiagram-WL72ISMW-DVLOORFJ.js +145 -0
- package/dist/review-app/settings.css +1 -0
- package/dist/review-app/settings.js +1 -0
- package/dist/review-app/src-Buml7cM5.js +1 -0
- package/dist/review-app/stateDiagram-FKZM4ZOC-sFGGp2kV.js +1 -0
- package/dist/review-app/stateDiagram-v2-4FDKWEC3-BHfCF4dX.js +1 -0
- package/dist/review-app/timeline-definition-IT6M3QCI-BESnBijC.js +61 -0
- package/dist/review-app/treemap-KMMF4GRG-wnVLBDeQ.js +1 -0
- package/dist/review-app/walletStatus-CcojOdGy.js +7 -0
- package/dist/review-app/xychartDiagram-PRI3JC2R-BGWVfCx4.js +7 -0
- package/dist/review-server/assets.js +48 -0
- package/dist/review-server/html.js +66 -0
- package/dist/review-server/http.js +47 -0
- package/dist/review-server/middleware/hostOrigin.js +48 -0
- package/dist/review-server/middleware/reviewToken.js +7 -0
- package/dist/review-server/reviewServerPolicy.js +10 -0
- package/dist/review-server/server.js +568 -0
- package/dist/review-server/settingsApi.js +182 -0
- package/dist/review-server/walletIdentityResponse.js +13 -0
- package/dist/runtime/config.js +103 -0
- package/dist/runtime/localSettingsService.js +198 -0
- package/dist/runtime/logger.js +50 -0
- package/dist/runtime/reviewServerAcquire.js +128 -0
- package/dist/runtime/smokeMainnetRead.js +529 -0
- package/dist/runtime/smokeMainnetReadAssertions.js +308 -0
- package/dist/runtime/start.js +295 -0
- package/dist/runtime/suiEndpoint.js +97 -0
- package/dist/runtime/suiTransactionGraphqlMapping.js +200 -0
- package/dist/runtime/suiTransactionGraphqlQueries.js +231 -0
- package/dist/runtime/suiTransactionGraphqlSource.js +148 -0
- package/docs/AGENT_BEHAVIOR.md +1 -1
- package/docs/AGENT_DEVELOPMENT_POLICY.md +20 -0
- package/docs/FRONTEND_POLICY.md +4 -3
- package/docs/MCP_SETUP.md +59 -7
- package/docs/MCP_TOOLS.md +1 -1
- package/docs/SDK_API.md +5 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -30,8 +30,8 @@ choices remain with the user, and what claims are unsupported.
|
|
|
30
30
|
|
|
31
31
|
Say Ur Intent is one product, but it must be read at three distinct layers. Do not collapse them:
|
|
32
32
|
|
|
33
|
-
- **Implemented today:** Sui mainnet evidence, local review, and
|
|
34
|
-
- **Deliberately sequenced next (planned order, ships only after verified review):** server-side receipt verification against chain state,
|
|
33
|
+
- **Implemented today:** Sui mainnet evidence, local review, and signable review adapters for the DeepBook and FlowX swap routes. The account-bound DeepBook swap review builds unsigned transaction material into a local in-process material store, internally binds a Sui transaction digest to that stored material, derives object ownership, quote/policy provenance, human-readable review facts, and review-time simulation evidence from the same private review artifacts, emits a schema-validated wallet review contract with a PTB visualization on a `ready_for_wallet_review` state, and serves a digest-gated byte handoff to the same-machine review page for user-controlled wallet signing with execution receipts recorded on the session. MCP responses do not contain transaction bytes, signing data, or signing readiness.
|
|
34
|
+
- **Deliberately sequenced next (planned order, ships only after verified review):** server-side receipt verification against chain state, further protocol adapters beyond DeepBook and FlowX registered through the descriptor contract (protocol names appear only after a concrete support decision), and richer local analysis views. Each step ships only from independently built or verified transaction material with a human-readable local review.
|
|
35
35
|
- **Never (permanently unsupported at every layer):** no private-key custody, no MCP or AI autonomous execution, no forwarding of opaque external transaction bytes to a wallet, no silent settlement-token or route choice, no fiat cash-out, no P&L, no peg guarantee.
|
|
36
36
|
|
|
37
37
|
In one sentence: Say Ur Intent is a local-first Sui intent evidence and review layer that progresses from verified evidence to user-controlled wallet signing only after Say Ur Intent independently builds or verifies the transaction material and shows a human-readable local review.
|
|
@@ -91,42 +91,6 @@ For manual maintainer and developer utilities, see [docs/UTILITY_INDEX.md](docs/
|
|
|
91
91
|
|
|
92
92
|
User-question flows for USD-denominated coverage, balance totals, and shortfall answers live in [docs/AGENT_BEHAVIOR.md](docs/AGENT_BEHAVIOR.md). The response fields for those answers live in [docs/MCP_TOOLS.md](docs/MCP_TOOLS.md).
|
|
93
93
|
|
|
94
|
-
## How Product Quality Improves: Three Axes
|
|
95
|
-
|
|
96
|
-
Future quality work moves along three axes. They multiply rather than add,
|
|
97
|
-
so neglecting any one of them caps the value of the other two:
|
|
98
|
-
|
|
99
|
-
- **Axis 1 - intent, evidence, answer quality.** Understanding what the user
|
|
100
|
-
asked, routing it to the right tool (prompt surfaces, `userAnswerUse`
|
|
101
|
-
response guidance), and answering only from verified mainnet evidence -
|
|
102
|
-
including saying plainly when a question cannot be answered from the
|
|
103
|
-
returned evidence. This axis is never finished; it is sharpened
|
|
104
|
-
continuously.
|
|
105
|
-
- **Axis 2 - protocol breadth.** Additional protocol adapters registered
|
|
106
|
-
through the descriptor contract (protocol names appear only after a
|
|
107
|
-
concrete support decision). Breadth is a multiplier, not a list: with a
|
|
108
|
-
second protocol, action routing starts doing real work (the bare action
|
|
109
|
-
prompt asks the user to choose a venue instead of routing silently), and
|
|
110
|
-
the execution-trust foundation proves it is not single-protocol.
|
|
111
|
-
- **Axis 3 - execution-trust foundation.** The guarantee that what the user
|
|
112
|
-
reviewed is exactly what gets signed, held under any wallet and any signing
|
|
113
|
-
speed: the review-session state machine, the one-transaction-per-session
|
|
114
|
-
handoff lock, sign-only wallets and slow hardware signers, review-page
|
|
115
|
-
security headers, and runtime lifecycle stability. Packaging and runtime
|
|
116
|
-
operability belong here too. This axis is the product differentiator, so
|
|
117
|
-
it is tracked as its own axis rather than as a side effect of feature work.
|
|
118
|
-
|
|
119
|
-
```text
|
|
120
|
-
axis 1 (intent-evidence quality) --+
|
|
121
|
-
+--x axis 2 (protocol breadth) = product value
|
|
122
|
-
axis 3 (execution-trust base) --+
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Work that advances several axes at once - for example, a new adapter that
|
|
126
|
-
forces the intent entry point to generalize and re-proves the trust pipeline
|
|
127
|
-
on a second protocol - is preferred over work that advances one axis in
|
|
128
|
-
isolation.
|
|
129
|
-
|
|
130
94
|
## What Works Today
|
|
131
95
|
|
|
132
96
|
The current release can run as a local stdio MCP server and expose mainnet Sui DeFi evidence:
|
|
@@ -136,10 +100,11 @@ The current release can run as a local stdio MCP server and expose mainnet Sui D
|
|
|
136
100
|
- USD-denominated settlement asset groups derived from pinned DeepBook SDK registry metadata;
|
|
137
101
|
- intent evidence with response summaries for natural-language USD-denominated payment coverage, balance-total, and shortfall questions;
|
|
138
102
|
- DeepBook pools, tokens, mid price, orderbook context, raw quotes, display-amount quotes, and account inventory;
|
|
103
|
+
- FlowX CLMM pools and indicative single-hop swap route quotes from the chain-verified pinned registry;
|
|
139
104
|
- user-requested bounded Sui transaction digest lookup, account activity scans, sent-function activity scans with known-wallet-only persistence, and stored normalized activity summaries;
|
|
140
105
|
- read-only external proposal review sessions that display proposed action, asset flow, recipient or target, freshness, missing evidence, user choices, unsupported claims, and non-signable reason;
|
|
141
106
|
- local Say Ur Intent review evidence and review-session status reads;
|
|
142
|
-
- account-bound DeepBook swap review progress through local unsigned transaction material build, internal Sui transaction digest binding, object ownership evidence, quote/policy provenance binding, human-readable review facts, and review-time simulation evidence; when every stage completes the review reaches `ready_for_wallet_review` and the local review page offers a digest-gated byte handoff, user-controlled wallet signing, and execution-receipt recording. The MCP layer and review API never sign, execute, or return transaction bytes.
|
|
107
|
+
- account-bound DeepBook and FlowX swap review progress through local unsigned transaction material build, internal Sui transaction digest binding, object ownership evidence, quote/policy provenance binding, human-readable review facts, and review-time simulation evidence; when every stage completes the review reaches `ready_for_wallet_review` and the local review page offers a digest-gated byte handoff, user-controlled wallet signing, and execution-receipt recording. The MCP layer and review API never sign, execute, or return transaction bytes.
|
|
143
108
|
|
|
144
109
|
It also includes:
|
|
145
110
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DEEPBOOK_SWAP_REVIEW_LIFECYCLE_STAGE_CATALOG_ID, validateDeepbookSwapReviewLifecycle } from "./deepbook/deepbookReviewLifecycle.js";
|
|
2
|
+
import { FLOWX_SWAP_REVIEW_LIFECYCLE_STAGE_CATALOG_ID, validateFlowxSwapReviewLifecycle } from "./flowx/flowxSwapReviewLifecycle.js";
|
|
3
|
+
import { createAdapterLifecycleValidator } from "../core/action/adapterLifecycleValidation.js";
|
|
4
|
+
export const validateSupportedAdapterLifecycle = createAdapterLifecycleValidator({
|
|
5
|
+
[DEEPBOOK_SWAP_REVIEW_LIFECYCLE_STAGE_CATALOG_ID]: validateDeepbookSwapReviewLifecycle,
|
|
6
|
+
[FLOWX_SWAP_REVIEW_LIFECYCLE_STAGE_CATALOG_ID]: validateFlowxSwapReviewLifecycle
|
|
7
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DEEPBOOK_SWAP_ACTION_KIND, DEEPBOOK_SWAP_ADAPTER_ID } from "./deepbook/deepbookSwapIntent.js";
|
|
3
|
+
import { FLOWX_SWAP_ACTION_KIND, FLOWX_SWAP_ADAPTER_ID } from "./flowx/flowxSwapIntent.js";
|
|
4
|
+
/**
|
|
5
|
+
* One slash-prompt surface contributed by a review adapter.
|
|
6
|
+
*
|
|
7
|
+
* Prompt names follow action-first naming: `<action>-<protocolSlug>`
|
|
8
|
+
* (for example `swap-deep`). Users reach for the verb before the venue, so
|
|
9
|
+
* action-first keeps autocomplete grouped by what the user wants to do. When
|
|
10
|
+
* an action has exactly one registered protocol, the bare action name (for
|
|
11
|
+
* example `swap`) is also registered as a shorthand.
|
|
12
|
+
*
|
|
13
|
+
* The surface carries only protocol-specific copy. Boundary language (no
|
|
14
|
+
* signing data, no transaction bytes, local-review-only signing) is owned by
|
|
15
|
+
* the platform and appended at registration time; adapters cannot weaken it.
|
|
16
|
+
*/
|
|
17
|
+
export const adapterPromptSurfaceSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
adapterId: z.string().min(1),
|
|
20
|
+
action: z
|
|
21
|
+
.string()
|
|
22
|
+
.regex(/^[a-z][a-z0-9]*$/, "action must be a lowercase slug, e.g. swap"),
|
|
23
|
+
protocolSlug: z
|
|
24
|
+
.string()
|
|
25
|
+
.regex(/^[a-z][a-z0-9]*$/, "protocolSlug must be a lowercase slug, e.g. deep"),
|
|
26
|
+
title: z.string().min(1),
|
|
27
|
+
description: z.string().min(1),
|
|
28
|
+
intentArgDescription: z.string().min(1),
|
|
29
|
+
exampleIntents: z.array(z.string().min(1)).min(1),
|
|
30
|
+
toolName: z.string().min(1)
|
|
31
|
+
})
|
|
32
|
+
.strict();
|
|
33
|
+
export function promptNameFor(surface) {
|
|
34
|
+
return `${surface.action}-${surface.protocolSlug}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Bare action prompts (`swap`) are always registered. With a single
|
|
38
|
+
* registered protocol they go straight to that protocol; with several they
|
|
39
|
+
* carry an optional `protocol` argument (completion suggests the slugs) and
|
|
40
|
+
* instruct the model to ask the user which protocol to use - never to pick a
|
|
41
|
+
* venue silently.
|
|
42
|
+
*/
|
|
43
|
+
export function actionGroups(surfaces) {
|
|
44
|
+
const byAction = new Map();
|
|
45
|
+
for (const surface of surfaces) {
|
|
46
|
+
byAction.set(surface.action, [...(byAction.get(surface.action) ?? []), surface]);
|
|
47
|
+
}
|
|
48
|
+
return byAction;
|
|
49
|
+
}
|
|
50
|
+
export const ADAPTER_PROMPT_SURFACES = [
|
|
51
|
+
{
|
|
52
|
+
adapterId: DEEPBOOK_SWAP_ADAPTER_ID,
|
|
53
|
+
action: DEEPBOOK_SWAP_ACTION_KIND,
|
|
54
|
+
protocolSlug: "deep",
|
|
55
|
+
title: "DeepBook Swap Review",
|
|
56
|
+
description: 'Prepare a reviewable DeepBook mainnet swap from a one-line intent, e.g. "10 sui to usdc".',
|
|
57
|
+
intentArgDescription: 'Swap intent in one line, any language, e.g. "10 sui to usdc" or "10 수이 usdc로 환전"',
|
|
58
|
+
exampleIntents: ["10 sui to usdc", "10 수이 usdc로 환전"],
|
|
59
|
+
toolName: "action.prepare_sui_action_review"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
adapterId: FLOWX_SWAP_ADAPTER_ID,
|
|
63
|
+
action: FLOWX_SWAP_ACTION_KIND,
|
|
64
|
+
protocolSlug: "flowx",
|
|
65
|
+
title: "FlowX Swap Review",
|
|
66
|
+
description: 'Prepare a reviewable FlowX CLMM mainnet swap from a one-line intent, e.g. "10 sui to usdc".',
|
|
67
|
+
intentArgDescription: 'Swap intent in one line, any language, e.g. "10 sui to usdc" or "10 수이 usdc로 환전"',
|
|
68
|
+
exampleIntents: ["10 sui to usdc", "10 수이 usdc로 환전"],
|
|
69
|
+
toolName: "action.prepare_sui_action_review"
|
|
70
|
+
}
|
|
71
|
+
];
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createSwapHumanReadableReviewEvidence } from "../../core/action/swapHumanReadableReviewProjection.js";
|
|
2
|
+
import { failReviewCheck, passReviewCheck } from "../../core/review/reviewComputationResult.js";
|
|
3
|
+
export function createDeepbookSwapHumanReadableReviewProducer() {
|
|
4
|
+
return (input) => {
|
|
5
|
+
try {
|
|
6
|
+
assertDeepbookHumanReviewSources(input);
|
|
7
|
+
const review = buildDeepbookHumanReadableReview(input);
|
|
8
|
+
const evidence = createSwapHumanReadableReviewEvidence({
|
|
9
|
+
transactionMaterial: input.transactionMaterial,
|
|
10
|
+
transactionMaterialDigest: input.transactionMaterialDigest,
|
|
11
|
+
swapQuotePolicy: input.swapQuotePolicy,
|
|
12
|
+
transactionObjectOwnership: input.transactionObjectOwnership,
|
|
13
|
+
adapterId: input.plan.adapterId,
|
|
14
|
+
protocol: input.plan.protocol,
|
|
15
|
+
actionKind: input.plan.actionKind,
|
|
16
|
+
review,
|
|
17
|
+
derivedAt: input.now
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
status: "completed",
|
|
21
|
+
evidence,
|
|
22
|
+
checks: [
|
|
23
|
+
passReviewCheck("deepbook_human_readable_review_evidence", "Human-readable review", "Prepared a human-readable account-bound swap review from material-bound quote policy and object ownership evidence. This is not wallet handoff, signing data, signing readiness, or execution readiness.", "adapter")
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return {
|
|
29
|
+
status: "blocked",
|
|
30
|
+
blockedReason: classifyHumanReviewFailure(error),
|
|
31
|
+
checks: [
|
|
32
|
+
failReviewCheck("deepbook_human_readable_review_failed", "Human-readable review", error instanceof Error ? error.message : "DeepBook human-readable review evidence could not be produced.", "adapter")
|
|
33
|
+
]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function buildDeepbookHumanReadableReview(input) {
|
|
39
|
+
const sourceAmount = amountFromQuotePolicy("input", input.swapQuotePolicy.sourceAmount, {
|
|
40
|
+
displayAmount: input.requestedIntent.from.amountDisplay,
|
|
41
|
+
displayAmountSource: "user_display_intent_not_signing_input"
|
|
42
|
+
});
|
|
43
|
+
const expectedOutput = amountFromQuotePolicy("expected_output", input.swapQuotePolicy.expectedOutput);
|
|
44
|
+
const minimumOutput = amountFromQuotePolicy("minimum_output", input.swapQuotePolicy.minimumOutput);
|
|
45
|
+
const protocolFee = amountFromQuotePolicy("fee", input.swapQuotePolicy.protocolFee);
|
|
46
|
+
return {
|
|
47
|
+
kind: "swap_human_readable_review",
|
|
48
|
+
proposedAction: {
|
|
49
|
+
title: input.plan.title,
|
|
50
|
+
summary: input.plan.summary,
|
|
51
|
+
actionKind: input.plan.actionKind,
|
|
52
|
+
adapterId: input.plan.adapterId,
|
|
53
|
+
protocol: input.plan.protocol,
|
|
54
|
+
network: "sui:mainnet"
|
|
55
|
+
},
|
|
56
|
+
assetFlow: {
|
|
57
|
+
outgoing: [sourceAmount],
|
|
58
|
+
expectedIncoming: [expectedOutput],
|
|
59
|
+
minimumIncoming: [minimumOutput],
|
|
60
|
+
fees: [protocolFee]
|
|
61
|
+
},
|
|
62
|
+
recipients: [
|
|
63
|
+
{ role: "connected_account", address: input.account },
|
|
64
|
+
{ role: "output_recipient", address: input.account }
|
|
65
|
+
],
|
|
66
|
+
targets: [
|
|
67
|
+
{
|
|
68
|
+
kind: "swap_output_asset",
|
|
69
|
+
symbol: input.swapQuotePolicy.expectedOutput.asset.symbol,
|
|
70
|
+
coinType: input.swapQuotePolicy.expectedOutput.asset.coinType,
|
|
71
|
+
protocol: input.plan.protocol,
|
|
72
|
+
poolKey: input.swapQuotePolicy.quoteSource.poolKey,
|
|
73
|
+
direction: input.swapQuotePolicy.quoteSource.direction
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
evidenceUsed: [
|
|
77
|
+
{
|
|
78
|
+
id: "deepbook_quote_policy",
|
|
79
|
+
label: "Quote policy",
|
|
80
|
+
source: "quote",
|
|
81
|
+
summary: "Quote policy evidence supplies the input, expected output, minimum output, protocol fee, and slippage policy shown in asset flow; it is not route choice or signing readiness."
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "transaction_material_digest",
|
|
85
|
+
label: "Transaction material digest",
|
|
86
|
+
source: "digest_commitment",
|
|
87
|
+
summary: "The review is bound internally to the stored local unsigned transaction material digest; the digest and transaction bytes are not public review output."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "transaction_object_ownership",
|
|
91
|
+
label: "Object ownership",
|
|
92
|
+
source: "wallet",
|
|
93
|
+
summary: "Object ownership evidence is derived from stored transaction data and Sui mainnet object reads."
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
missingEvidence: [
|
|
97
|
+
{
|
|
98
|
+
id: "review_time_simulation",
|
|
99
|
+
label: "Review-time simulation",
|
|
100
|
+
reason: "The review has not simulated the stored transaction material with required effects, balance changes, object types, and transaction fields."
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
requiredUserChoices: [
|
|
104
|
+
{
|
|
105
|
+
id: "wallet_authorization_later",
|
|
106
|
+
label: "Wallet authorization",
|
|
107
|
+
reason: "The wallet signature request happens on this review page after the digest-gated handoff; nothing is signed without your approval in the wallet."
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
unsupportedClaims: [
|
|
111
|
+
{
|
|
112
|
+
id: "no_signing_readiness",
|
|
113
|
+
label: "No signing readiness",
|
|
114
|
+
reason: "Human-readable review evidence does not prove the action is ready to sign."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "no_execution_readiness",
|
|
118
|
+
label: "No execution readiness",
|
|
119
|
+
reason: "Review-time simulation, wallet handoff, signing, and execution receipt evidence are not complete."
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "no_route_recommendation",
|
|
123
|
+
label: "No route recommendation",
|
|
124
|
+
reason: "The account-bound swap review uses an explicit direct pool path and does not rank venues or recommend routes."
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
freshness: {
|
|
128
|
+
status: "current",
|
|
129
|
+
evaluatedAt: input.now.toISOString(),
|
|
130
|
+
expiresAt: input.transactionMaterial.expiresAt,
|
|
131
|
+
reason: "Human-readable review evidence expires with the stored local transaction material and quote policy."
|
|
132
|
+
},
|
|
133
|
+
blockingChecks: [
|
|
134
|
+
failReviewCheck("deepbook_review_time_simulation_missing", "Review-time simulation", "Review-time simulation evidence is still required before any wallet handoff, signing, or execution.", "simulation")
|
|
135
|
+
]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function assertDeepbookHumanReviewSources(input) {
|
|
139
|
+
if (input.swapQuotePolicy.adapterId !== input.plan.adapterId ||
|
|
140
|
+
input.swapQuotePolicy.protocol !== input.plan.protocol ||
|
|
141
|
+
input.swapQuotePolicy.actionKind !== input.plan.actionKind) {
|
|
142
|
+
throw new Error("human-readable review quote policy identity must match the action plan");
|
|
143
|
+
}
|
|
144
|
+
if (input.swapQuotePolicy.quoteSource.poolKey !== input.poolResolution.poolKey) {
|
|
145
|
+
throw new Error("human-readable review pool target must match swap quote policy poolKey");
|
|
146
|
+
}
|
|
147
|
+
if (input.swapQuotePolicy.quoteSource.direction !== input.quotePolicy.direction) {
|
|
148
|
+
throw new Error("human-readable review target direction must match swap quote policy direction");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function classifyHumanReviewFailure(error) {
|
|
152
|
+
const message = error instanceof Error ? error.message : "";
|
|
153
|
+
if (/object ownership/i.test(message)) {
|
|
154
|
+
return "object_resolution_failed";
|
|
155
|
+
}
|
|
156
|
+
if (/asset|target|pool|direction|protocol|adapter/i.test(message)) {
|
|
157
|
+
return "asset_mismatch";
|
|
158
|
+
}
|
|
159
|
+
if (/amount|quote|slippage|min/i.test(message)) {
|
|
160
|
+
return "amount_mismatch";
|
|
161
|
+
}
|
|
162
|
+
return "unsupported_action";
|
|
163
|
+
}
|
|
164
|
+
function amountFromQuotePolicy(role, amount, display) {
|
|
165
|
+
return {
|
|
166
|
+
role,
|
|
167
|
+
symbol: amount.asset.symbol,
|
|
168
|
+
coinType: amount.asset.coinType,
|
|
169
|
+
decimals: amount.asset.decimals,
|
|
170
|
+
rawAmount: amount.raw,
|
|
171
|
+
rawAmountSource: "quote_policy_evidence",
|
|
172
|
+
...(display?.displayAmount ? { displayAmount: display.displayAmount } : {}),
|
|
173
|
+
...(display?.displayAmountSource ? { displayAmountSource: display.displayAmountSource } : {})
|
|
174
|
+
};
|
|
175
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { parseDeepbookRawU64 } from "../../core/read/deepbookReadHelpers.js";
|
|
2
|
+
export const DEEPBOOK_REVIEW_QUOTE_STALE_AFTER_MS = 30_000;
|
|
3
|
+
// Same-machine pipelines capture `now` before the network quote fetch, so the
|
|
4
|
+
// fetch timestamp can land a few hundred milliseconds "in the future". Treat
|
|
5
|
+
// skew within this tolerance as a fresh quote (age 0) and record the skew;
|
|
6
|
+
// anything beyond it is a real clock-integrity violation and refuses.
|
|
7
|
+
export const DEEPBOOK_QUOTE_FUTURE_SKEW_TOLERANCE_MS = 5_000;
|
|
8
|
+
export const DEEPBOOK_MAX_SLIPPAGE_BPS = 1000;
|
|
9
|
+
export const DEEPBOOK_MIN_SLIPPAGE_BPS = 1;
|
|
10
|
+
const BPS_DENOMINATOR = 10000n;
|
|
11
|
+
export function deriveDeepbookSwapQuotePolicy(input) {
|
|
12
|
+
assertSlippageBps(input.maxSlippageBps);
|
|
13
|
+
const staleAfterMs = input.staleAfterMs ?? DEEPBOOK_REVIEW_QUOTE_STALE_AFTER_MS;
|
|
14
|
+
if (!Number.isInteger(staleAfterMs) || staleAfterMs < 1) {
|
|
15
|
+
throw new Error("staleAfterMs must be a positive integer");
|
|
16
|
+
}
|
|
17
|
+
const fetchedAtMs = parseIsoUtcTimestampMs(input.fetchedAt, "fetchedAt");
|
|
18
|
+
const nowMs = parseValidDateMs(input.now, "now");
|
|
19
|
+
const rawQuoteAgeMs = nowMs - fetchedAtMs;
|
|
20
|
+
const direction = directionFromRawQuote(input.rawQuote);
|
|
21
|
+
if (rawQuoteAgeMs < -DEEPBOOK_QUOTE_FUTURE_SKEW_TOLERANCE_MS) {
|
|
22
|
+
return {
|
|
23
|
+
status: "refresh_required",
|
|
24
|
+
refreshReason: "quote_stale",
|
|
25
|
+
reason: "quote_timestamp_in_future",
|
|
26
|
+
direction,
|
|
27
|
+
fetchedAt: input.fetchedAt,
|
|
28
|
+
quoteAgeMs: 0,
|
|
29
|
+
staleAfterMs,
|
|
30
|
+
clockSkewMs: -rawQuoteAgeMs
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const clockSkewMs = rawQuoteAgeMs < 0 ? -rawQuoteAgeMs : undefined;
|
|
34
|
+
const quoteAgeMs = rawQuoteAgeMs < 0 ? 0 : rawQuoteAgeMs;
|
|
35
|
+
if (quoteAgeMs > staleAfterMs) {
|
|
36
|
+
return {
|
|
37
|
+
status: "refresh_required",
|
|
38
|
+
refreshReason: "quote_stale",
|
|
39
|
+
reason: "quote_stale",
|
|
40
|
+
direction,
|
|
41
|
+
fetchedAt: input.fetchedAt,
|
|
42
|
+
quoteAgeMs,
|
|
43
|
+
staleAfterMs
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const expectedOut = parseUnsignedRaw(input.rawQuote.directionalOutput.raw, "directionalOutput.raw");
|
|
47
|
+
if (expectedOut === 0n) {
|
|
48
|
+
return unavailableQuote(input, direction, quoteAgeMs, staleAfterMs, "zero_expected_output");
|
|
49
|
+
}
|
|
50
|
+
const minOut = (expectedOut * (BPS_DENOMINATOR - BigInt(input.maxSlippageBps))) / BPS_DENOMINATOR;
|
|
51
|
+
if (minOut === 0n) {
|
|
52
|
+
return unavailableQuote(input, direction, quoteAgeMs, staleAfterMs, "zero_min_out");
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
status: "ok",
|
|
56
|
+
direction,
|
|
57
|
+
quoteFresh: true,
|
|
58
|
+
fetchedAt: input.fetchedAt,
|
|
59
|
+
quoteAgeMs,
|
|
60
|
+
staleAfterMs,
|
|
61
|
+
...(clockSkewMs !== undefined ? { clockSkewMs } : {}),
|
|
62
|
+
feeMode: input.feeMode ?? "deep",
|
|
63
|
+
maxSlippageBps: input.maxSlippageBps,
|
|
64
|
+
sourceAmountRaw: parsePositiveRaw(input.rawQuote.inputAmount.raw, "inputAmount.raw").toString(),
|
|
65
|
+
expectedOutRaw: expectedOut.toString(),
|
|
66
|
+
minOutRaw: minOut.toString(),
|
|
67
|
+
deepAmountRaw: parseUnsignedRaw(input.rawQuote.deepRequired.raw, "deepRequired.raw").toString()
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function assertSlippageBps(value) {
|
|
71
|
+
if (!Number.isInteger(value) || value < DEEPBOOK_MIN_SLIPPAGE_BPS || value > DEEPBOOK_MAX_SLIPPAGE_BPS) {
|
|
72
|
+
throw new Error(`maxSlippageBps must be an integer from ${DEEPBOOK_MIN_SLIPPAGE_BPS} to ${DEEPBOOK_MAX_SLIPPAGE_BPS}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function parseIsoUtcTimestampMs(value, field) {
|
|
76
|
+
const parsed = new Date(value);
|
|
77
|
+
const timestampMs = parsed.getTime();
|
|
78
|
+
if (!Number.isFinite(timestampMs) || parsed.toISOString() !== value) {
|
|
79
|
+
throw new Error(`${field} must be an ISO 8601 UTC timestamp`);
|
|
80
|
+
}
|
|
81
|
+
return timestampMs;
|
|
82
|
+
}
|
|
83
|
+
function parseValidDateMs(value, field) {
|
|
84
|
+
if (!(value instanceof Date)) {
|
|
85
|
+
throw new Error(`${field} must be a valid Date`);
|
|
86
|
+
}
|
|
87
|
+
const timestampMs = value.getTime();
|
|
88
|
+
if (!Number.isFinite(timestampMs)) {
|
|
89
|
+
throw new Error(`${field} must be a valid Date`);
|
|
90
|
+
}
|
|
91
|
+
return timestampMs;
|
|
92
|
+
}
|
|
93
|
+
function directionFromRawQuote(rawQuote) {
|
|
94
|
+
return rawQuote.sourceMoveFunction.startsWith("pool::get_quote_quantity_out") ? "base_to_quote" : "quote_to_base";
|
|
95
|
+
}
|
|
96
|
+
function unavailableQuote(input, direction, quoteAgeMs, staleAfterMs, reason) {
|
|
97
|
+
return {
|
|
98
|
+
status: "refresh_required",
|
|
99
|
+
refreshReason: "quote_unavailable",
|
|
100
|
+
reason,
|
|
101
|
+
direction,
|
|
102
|
+
fetchedAt: input.fetchedAt,
|
|
103
|
+
quoteAgeMs,
|
|
104
|
+
staleAfterMs
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function parsePositiveRaw(value, field) {
|
|
108
|
+
return parseDeepbookRawU64(value, field, { positive: true });
|
|
109
|
+
}
|
|
110
|
+
function parseUnsignedRaw(value, field) {
|
|
111
|
+
return parseDeepbookRawU64(value, field);
|
|
112
|
+
}
|