@zktx.io/sui-mcp 0.6.2 → 0.8.0
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 +94 -52
- package/dist/adapters/adapterPromptSurfaces.js +1 -1
- package/dist/core/activity/localDataService.js +8 -21
- package/dist/core/activity/localDataValidation.js +22 -46
- package/dist/core/activity/sqliteAccountStore.js +46 -0
- package/dist/core/activity/sqliteActivityStore.js +65 -147
- package/dist/core/activity/sqliteActivityStoreSchema.js +42 -26
- package/dist/core/activity/transactionActivityService.js +2 -2
- package/dist/core/preferences/preferencesStore.js +2 -2
- package/dist/core/preferences/sqlitePreferencesRepository.js +10 -0
- package/dist/core/read/deepbookReadHelpers.js +1 -1
- package/dist/core/read/readResponseGuidance.js +6 -6
- package/dist/core/session/cardResult.js +41 -0
- package/dist/core/session/cardSession.js +1 -1
- package/dist/core/session/cardSessionStore.js +51 -19
- package/dist/core/session/chainAccounts.js +120 -0
- package/dist/core/session/sessionStore.js +4 -8
- package/dist/core/session/settingsFileProtocol.js +1 -1
- package/dist/core/session/settingsFileStore.js +3 -30
- package/dist/core/session/settingsOperation.js +27 -19
- package/dist/core/session/settingsWorkflow.js +161 -87
- package/dist/core/session/sqliteCardStore.js +34 -14
- package/dist/core/session/sqliteSessionStore.js +5 -5
- package/dist/core/session/sqliteSettingsWorkflowStore.js +135 -41
- package/dist/core/session/sqliteTransactionRequest.js +18 -0
- package/dist/core/session/sqliteWalletConnectionOperation.js +13 -0
- package/dist/core/session/sqliteWalletWorkflowStore.js +569 -333
- package/dist/core/session/status.js +2 -2
- package/dist/core/session/wait.js +6 -11
- package/dist/core/session/walletConnection.js +71 -46
- package/dist/core/session/walletConnectionOperations.js +24 -0
- package/dist/core/session/walletRuntime.js +7 -13
- package/dist/core/session/walletWorkflow.js +248 -99
- package/dist/core/session/workflowState.js +104 -38
- package/dist/core/session/workflowView.js +92 -101
- package/dist/mcp/activeAccountResponse.js +3 -0
- package/dist/mcp/prompts.js +10 -4
- package/dist/mcp/resources.js +1 -1
- package/dist/mcp/responseGuidance.js +7 -9
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/serverInfo.js +21 -19
- package/dist/mcp/toolErrors.js +5 -3
- package/dist/mcp/toolNames.js +47 -46
- package/dist/mcp/tools/action/prepareSuiActionReview.js +13 -20
- package/dist/mcp/tools/read/deepbookReadTools.js +1 -1
- package/dist/mcp/tools/read/index.js +2 -2
- package/dist/mcp/tools/read/readToolHelpers.js +9 -7
- package/dist/mcp/tools/read/serverStatusTools.js +4 -5
- package/dist/mcp/tools/read/transactionActivityTools.js +3 -3
- package/dist/mcp/tools/session/executionResultTools.js +2 -2
- package/dist/mcp/tools/session/shared.js +2 -2
- package/dist/mcp/tools/session/statusTools.js +12 -10
- package/dist/mcp/tools/session/walletConnectionTools.js +29 -17
- package/dist/mcp/tools/settings/index.js +7 -4
- package/dist/mcp-app/account.html +7 -7
- package/dist/mcp-app/chart.html +3 -3
- package/dist/mcp-app/connect.html +13 -13
- package/dist/mcp-app/disconnect.html +3637 -0
- package/dist/mcp-app/disconnect.notices.txt +1480 -0
- package/dist/mcp-app/receipt.html +393 -393
- package/dist/mcp-app/review.html +459 -459
- package/dist/mcp-app/settings.html +7 -7
- package/dist/mcp-ui/contracts.js +3 -1
- package/dist/mcp-ui/tools.js +4 -4
- package/dist/runtime/application.js +3 -3
- package/dist/runtime/config.js +3 -6
- package/dist/runtime/localSettingsService.js +11 -8
- package/dist/runtime/shared/control.js +2 -2
- package/dist/runtime/smokeMainnetRead.js +23 -22
- package/dist/runtime/smokeReview.js +7 -7
- package/dist/runtime/start.js +1 -1
- package/dist/runtime/walletConnectTransport.js +16 -16
- package/dist/runtime/walletSdkChildRuntime.js +29 -12
- package/dist/runtime/walletSdkIpc.js +5 -4
- package/dist/runtime/walletSdkProcess.js +24 -8
- package/docs/AGENT_BEHAVIOR.md +149 -120
- package/docs/LOCAL_DB_ARCHITECTURE.md +103 -75
- package/docs/MCP_SETUP.md +365 -382
- package/docs/MCP_TOOLS.md +387 -271
- package/docs/SDK_API.md +23 -11
- package/docs/SIGNABLE_ADAPTER_CONTRACT.md +6 -6
- package/docs/TRANSACTION_ACTIVITY_LOG.md +11 -7
- package/docs/UTILITY_INDEX.md +66 -64
- package/docs/WALLET_CONNECTION.md +162 -166
- package/package.json +1 -1
- package/protocols/deepbook-margin.md +1 -1
- package/protocols/deepbook-v3.md +2 -2
|
@@ -1,80 +1,146 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CONNECTION_RECONCILIATION_MESSAGE, walletConnectionEligibility, usableWalletConnection, connectionHasSuiSigningScope, projectWalletConnection } from "./walletConnection.js";
|
|
2
2
|
import { isInitialChainObservation } from "./transactionRequest.js";
|
|
3
|
-
|
|
3
|
+
import { SUI_MAINNET_WALLET_CHAIN } from "./chainAccounts.js";
|
|
4
|
+
import { parseSuiAddress } from "../suiAddress.js";
|
|
5
|
+
export const workflowActions = ["connect", "disconnect", "stop_connection", "prepare_review",
|
|
4
6
|
"request_signature", "cancel", "stop_waiting", "read_result"];
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
export const workflowNextSteps = ["none", "wait", "check_status", "open_settings", "request_disconnect", "request_review"];
|
|
8
|
+
function walletServiceNextStep(status) {
|
|
9
|
+
if (status === "available")
|
|
10
|
+
return undefined;
|
|
11
|
+
return { kind: status === "unavailable" ? "open_settings" : "wait", reason: "wallet_unavailable",
|
|
12
|
+
message: status === "unavailable" ? "Open Settings, then Troubleshooting, to restart the connection service. No wallet request was sent."
|
|
13
|
+
: "Wait for the connection service to finish starting, then check status." };
|
|
14
|
+
}
|
|
15
|
+
export function walletActionDecision(facts, action, targetId) {
|
|
16
|
+
const deny = (kind, reason, message) => ({ allowed: false, nextStep: { kind, reason, message } });
|
|
17
|
+
const service = walletServiceNextStep(facts.walletAvailability.status);
|
|
18
|
+
if (service)
|
|
19
|
+
return { allowed: false, nextStep: service };
|
|
20
|
+
if (facts.pendingOperation)
|
|
21
|
+
return deny("check_status", "operation_busy", "Wait for the current wallet operation and its cleanup to finish, then check this request's status.");
|
|
22
|
+
const selection = walletConnectionEligibility(facts.connection, Date.parse(facts.evaluatedAt), facts.connectionPresence, facts.activeAccount, facts.readAddressCleared);
|
|
23
|
+
if (!facts.connectionPresence.confirmed || !facts.connectionPresence.managed || selection.connectionReconciliationRequired)
|
|
24
|
+
return deny("check_status", "connection_state_unconfirmed", selection.connectionReconciliationRequired ? CONNECTION_RECONCILIATION_MESSAGE : "The wallet session has not been confirmed. Check its status before continuing.");
|
|
25
|
+
if (action === "connect") {
|
|
26
|
+
if (!facts.requestedChains.length)
|
|
27
|
+
return deny("open_settings", "wallet_networks_required", "Choose networks in Settings before requesting a wallet connection.");
|
|
28
|
+
return selection.pairingAllowed ? { allowed: true, nextStep: { kind: "none" } }
|
|
29
|
+
: deny("request_disconnect", "connection_present", "Ask in chat for a Disconnect card before requesting a new wallet connection.");
|
|
30
|
+
}
|
|
31
|
+
if (targetId && facts.connection?.connectionId !== targetId)
|
|
32
|
+
return deny("check_status", "connection_target_changed", "The wallet session for this card is no longer current. Ask in chat for current connection status.");
|
|
33
|
+
return selection.manageable ? { allowed: true, nextStep: { kind: "none" } }
|
|
34
|
+
: deny("none", "no_session_to_disconnect", "There is no current wallet session to disconnect. No request was sent.");
|
|
35
|
+
}
|
|
36
|
+
export function fixedReviewTarget(session, input) {
|
|
37
|
+
const hasInputTarget = input?.connectionId !== undefined || input?.account !== undefined;
|
|
38
|
+
const inputId = typeof input?.connectionId === "string" && input.connectionId.length ? input.connectionId : undefined;
|
|
39
|
+
const inputAccount = typeof input?.account === "string" ? parseSuiAddress(input.account) : undefined;
|
|
40
|
+
if (hasInputTarget && (!inputId || !inputAccount))
|
|
41
|
+
return undefined;
|
|
42
|
+
if (inputId && session.walletConnectionId && inputId !== session.walletConnectionId ||
|
|
43
|
+
inputAccount && session.account && inputAccount !== session.account)
|
|
44
|
+
return undefined;
|
|
45
|
+
const connectionId = inputId ?? session.walletConnectionId, account = inputAccount ?? session.account;
|
|
46
|
+
return connectionId && account ? { connectionId, account } : undefined;
|
|
15
47
|
}
|
|
16
48
|
export function workflowConnectionEligibility(facts) {
|
|
17
|
-
const selection =
|
|
49
|
+
const selection = walletConnectionEligibility(facts.connection, Date.parse(facts.evaluatedAt), facts.connectionPresence, facts.activeAccount, facts.readAddressCleared);
|
|
18
50
|
const available = facts.walletAvailability.status === "available", dependent = facts.walletDependent !== false;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
:
|
|
22
|
-
|
|
23
|
-
|
|
51
|
+
return { selection, usableConnectionId: available && dependent ? selection.connection?.connectionId : undefined,
|
|
52
|
+
assetReadAccount: !dependent ? undefined : available ? selection.assetReadAccount : { status: "address_required" },
|
|
53
|
+
connection: projectWalletConnection(facts.connection, Date.parse(facts.evaluatedAt), facts.connectionPresence, available),
|
|
54
|
+
pendingOperation: facts.pendingOperation,
|
|
55
|
+
canDisconnect: available && selection.manageable,
|
|
24
56
|
connectionReconciliationRequired: available && dependent ? selection.connectionReconciliationRequired : undefined };
|
|
25
57
|
}
|
|
26
58
|
export function workflowEligibility(facts) {
|
|
27
59
|
const { record, session, request, authority, walletAvailability } = facts;
|
|
28
60
|
const at = Date.parse(facts.evaluatedAt);
|
|
29
|
-
const cardRemaining = record?.ownerId === facts.ownerId
|
|
61
|
+
const cardRemaining = record?.ownerId === facts.ownerId && record.state.reason !== "cancelled"
|
|
62
|
+
? Math.max(0, Date.parse(record.state.expiresAt) - at) : 0;
|
|
30
63
|
const remaining = record?.scope === "review" && session && !request
|
|
31
64
|
? Math.min(cardRemaining, Math.max(0, Date.parse(session.expiresAt) - at)) : cardRemaining;
|
|
32
65
|
const inputAvailable = remaining > 0 && record?.state.state === "ready" && record.acceptedInput === undefined;
|
|
33
66
|
const allowedActions = [];
|
|
34
67
|
const { selection, ...connectionEligibility } = workflowConnectionEligibility(facts);
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
const reviewTarget = session && !session.plans[0]?.reviewModel ? fixedReviewTarget(session, record?.state.input) : undefined;
|
|
69
|
+
const targetId = reviewTarget?.connectionId, targetAccount = reviewTarget?.account;
|
|
70
|
+
const reviewConnection = walletAvailability.status === "available" && !facts.connectionPresence.unrecorded && facts.walletDependent !== false && targetId && targetAccount
|
|
71
|
+
? usableWalletConnection(facts.connection, at, facts.connectionPresence, targetId, SUI_MAINNET_WALLET_CHAIN, targetAccount) : undefined;
|
|
72
|
+
const preparationIssue = session && record?.scope === "review" && !session.plans[0]?.reviewModel && !reviewTarget
|
|
73
|
+
? "This review has no matching fixed wallet target. Start a new review." : undefined;
|
|
74
|
+
const scopedDisconnect = record?.scope === "disconnect";
|
|
75
|
+
const walletDecision = walletActionDecision(facts, scopedDisconnect ? "disconnect" : "connect", scopedDisconnect ? String(record?.state.input.connectionId) : undefined);
|
|
76
|
+
let nextStep = facts.operation?.status === "running" && facts.operation.cardId === record?.state.cardId
|
|
77
|
+
? { kind: "wait" } : walletDecision.nextStep;
|
|
78
|
+
const disconnectTargetMatches = !scopedDisconnect || record.state.input.connectionId === facts.connection?.connectionId;
|
|
79
|
+
if (record?.scope === "connect" || scopedDisconnect) {
|
|
38
80
|
if (inputAvailable) {
|
|
39
81
|
allowedActions.push("cancel");
|
|
40
82
|
if (walletAvailability.status === "available") {
|
|
41
|
-
if (
|
|
83
|
+
if (record.scope === "connect" && walletDecision.allowed)
|
|
42
84
|
allowedActions.push("connect");
|
|
43
|
-
if (
|
|
85
|
+
if (scopedDisconnect && walletDecision.allowed)
|
|
44
86
|
allowedActions.push("disconnect");
|
|
45
|
-
if (selection.connection)
|
|
46
|
-
allowedActions.push("use_account");
|
|
47
87
|
}
|
|
48
88
|
}
|
|
49
|
-
if (remaining > 0 && facts.
|
|
89
|
+
if (record.state.state !== "closed" && remaining > 0 && facts.operation?.action === "connect" && facts.operation.status === "running")
|
|
50
90
|
allowedActions.push("stop_connection");
|
|
51
91
|
}
|
|
52
92
|
if (session && inputAvailable && record?.scope === "review" && session.status !== "expired" && Date.parse(session.expiresAt) > at && !session.preparationId) {
|
|
53
93
|
allowedActions.push("cancel");
|
|
54
|
-
if (walletAvailability.status === "available" &&
|
|
55
|
-
|
|
56
|
-
if (!account.allowed)
|
|
57
|
-
preparationIssue = account.message;
|
|
58
|
-
else if (!facts.busyForAccount)
|
|
94
|
+
if (walletAvailability.status === "available" && reviewConnection && !session.plans[0]?.reviewModel) {
|
|
95
|
+
if (!facts.busyForAccount)
|
|
59
96
|
allowedActions.push("prepare_review");
|
|
60
|
-
if (!facts.busyForAccount && session.status === "ready_for_wallet_review" && session.reviewState?.transactionReviewData &&
|
|
97
|
+
if (!facts.busyForAccount && connectionHasSuiSigningScope(reviewConnection, targetAccount) && session.status === "ready_for_wallet_review" && session.reviewState?.transactionReviewData &&
|
|
61
98
|
(!request || request.reviewRevision !== session.reviewRevision))
|
|
62
99
|
allowedActions.push("request_signature");
|
|
63
100
|
}
|
|
64
101
|
}
|
|
65
|
-
if (record && session && remaining > 0 && request && request.reviewSessionId === session.id &&
|
|
102
|
+
if (record && record.state.state !== "closed" && session && remaining > 0 && request && request.reviewSessionId === session.id &&
|
|
66
103
|
authority?.owner_id === facts.ownerId &&
|
|
67
104
|
(record.operationId === request.attemptId || record.scope === "review_manage" && record.state.input.attemptId === request.attemptId)) {
|
|
68
|
-
if (
|
|
105
|
+
if (request.requestStatus === "awaiting_signature" || !authority.observation_stopped && isInitialChainObservation(request.requestStatus))
|
|
69
106
|
allowedActions.push("stop_waiting");
|
|
70
|
-
if (isInitialChainObservation(request.requestStatus) || request.requestStatus === "outcome_unknown")
|
|
107
|
+
if (record.scope === "review_manage" && record.state.state === "ready" && record.acceptedInput === undefined && (isInitialChainObservation(request.requestStatus) || request.requestStatus === "outcome_unknown"))
|
|
71
108
|
allowedActions.push("read_result");
|
|
72
109
|
}
|
|
73
110
|
const expiry = session && inputAvailable && record?.scope === "review" && !session.preparationId &&
|
|
74
111
|
session.status === "ready_for_wallet_review" && (!request || request.reviewRevision !== session.reviewRevision)
|
|
75
112
|
? session.reviewState?.humanReadableReview?.freshness.expiresAt : undefined;
|
|
76
|
-
const
|
|
77
|
-
|
|
113
|
+
const reviewRead = expiry && session ? Math.min(remaining, Date.parse(session.expiresAt) - at, Date.parse(expiry) - at) : undefined;
|
|
114
|
+
const connectionDeadlines = inputAvailable && facts.walletDependent !== false && facts.connection?.status === "connected" &&
|
|
115
|
+
(["connect", "disconnect"].includes(record?.scope ?? "") || facts.connection.connectionId === reviewTarget?.connectionId)
|
|
116
|
+
? [Date.parse(facts.connection.expiresAt) - at].filter((delay) => delay > 0) : [];
|
|
117
|
+
const readDelays = [reviewRead, ...connectionDeadlines].filter((delay) => delay !== undefined && delay > 0);
|
|
118
|
+
const nextRead = readDelays.length ? Math.min(...readDelays) : undefined;
|
|
119
|
+
if (session) {
|
|
120
|
+
nextStep = { kind: "none" };
|
|
121
|
+
if (!session.plans[0]?.reviewModel && !request) {
|
|
122
|
+
const service = walletServiceNextStep(walletAvailability.status);
|
|
123
|
+
if (service)
|
|
124
|
+
nextStep = service;
|
|
125
|
+
else if (facts.connectionPresence.unrecorded)
|
|
126
|
+
nextStep = { kind: "check_status", reason: "connection_state_unconfirmed", message: CONNECTION_RECONCILIATION_MESSAGE };
|
|
127
|
+
else if (facts.pendingOperation)
|
|
128
|
+
nextStep = { kind: "check_status", reason: "operation_busy", message: "Wait for the current wallet operation and its cleanup to finish, then check this review's status." };
|
|
129
|
+
else if (reviewTarget && connectionEligibility.connection?.connectionId === targetId && connectionEligibility.connection?.sessionPresence === "absent")
|
|
130
|
+
nextStep = { kind: "request_review", message: "The original wallet session is no longer present. Reconnect a wallet and ask in chat for a new transaction review." };
|
|
131
|
+
else if (reviewTarget && facts.connection && facts.connection.connectionId !== targetId)
|
|
132
|
+
nextStep = { kind: "request_review", message: "This review belongs to the earlier wallet connection. Ask in chat for a new transaction review." };
|
|
133
|
+
else if (!reviewConnection && connectionEligibility.canDisconnect && facts.connection?.connectionId === targetId)
|
|
134
|
+
nextStep = { kind: "request_disconnect", message: "The original wallet connection is unavailable. Ask in chat for a Disconnect card, then start a new review after reconnecting." };
|
|
135
|
+
else if (!reviewConnection)
|
|
136
|
+
nextStep = { kind: "check_status", message: "This review keeps its original account and connection. Ask in chat to check that wallet connection's status before continuing." };
|
|
137
|
+
else if (facts.busyForAccount)
|
|
138
|
+
nextStep = { kind: "wait", message: "A previous transaction request for this Sui account is still pending. Wait for it to finish, then check this review's status." };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { allowedActions, preparationIssue, nextStep, ...connectionEligibility, reviewTarget,
|
|
142
|
+
canDisconnect: connectionEligibility.canDisconnect && disconnectTargetMatches,
|
|
143
|
+
...(session ? { usableConnectionId: reviewConnection?.connectionId } : {}),
|
|
78
144
|
actionRemainingMs: remaining, inputRemainingMs: inputAvailable ? remaining : 0,
|
|
79
145
|
...(nextRead !== undefined && nextRead > 0 ? { nextStateReadAfterMs: nextRead } : {}) };
|
|
80
146
|
}
|
|
@@ -1,84 +1,86 @@
|
|
|
1
|
-
import { workflowActions } from "./workflowState.js";
|
|
1
|
+
import { workflowActions, workflowNextSteps } from "./workflowState.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { suiAddressStringSchema
|
|
3
|
+
import { suiAddressStringSchema } from "../suiAddress.js";
|
|
4
4
|
import { actionPlanSchema, internalSessionStatusSchema, reviewStateOutputSchema } from "../action/schemas.js";
|
|
5
|
-
import { walletConnectionSchema, walletAvailabilitySchema, workflowProgressSchema, WALLET_CONNECTION_POLL_SECONDS,
|
|
5
|
+
import { walletConnectionSchema, walletAvailabilitySchema, workflowProgressSchema, WALLET_CONNECTION_POLL_SECONDS, connectionChainStateSchema } from "./walletConnection.js";
|
|
6
6
|
import { transactionRequestSchema } from "./transactionRequest.js";
|
|
7
7
|
import { workflowProgress } from "./walletConnection.js";
|
|
8
8
|
import { reviewProgress, EXECUTION_POLLING_INTERVAL_SECONDS } from "./status.js";
|
|
9
|
-
import { walletRunIdSchema,
|
|
9
|
+
import { walletRunIdSchema, walletObservationSchema } from "./walletRuntime.js";
|
|
10
|
+
import { walletConnectionActionSchema, walletConnectionOperationSchema } from "./walletConnectionOperations.js";
|
|
11
|
+
import { walletChainSchema, walletChainsSchema, SUI_MAINNET_WALLET_CHAIN, normalizeChainAddress } from "./chainAccounts.js";
|
|
10
12
|
export const CONNECT_BOUNDARY = "A wallet connection provides account context; it is not a transaction approval or proof of address ownership.";
|
|
11
13
|
export const REVIEW_BOUNDARY = "Review evidence is not a safety guarantee. Only an explicit card action and wallet approval may authorize this exact transaction.";
|
|
12
|
-
export const connectionViewSchema = walletConnectionSchema.extend({
|
|
14
|
+
export const connectionViewSchema = walletConnectionSchema.extend({
|
|
15
|
+
sessionPresence: z.enum(["present", "absent", "unusable", "unconfirmed"]),
|
|
16
|
+
chainStates: z.array(connectionChainStateSchema).optional(),
|
|
17
|
+
disconnectImpact: z.object({ impactId: z.string(), requestCount: z.number().int().nonnegative(), chains: walletChainsSchema }).strict().optional()
|
|
18
|
+
});
|
|
13
19
|
export { assetReadAccountSchema } from "./walletConnection.js";
|
|
14
|
-
export const pendingConnectionStatusSchema = z.enum(["
|
|
15
|
-
const connectAction = z.object({ action: z.literal("connect"), walletRunId: walletRunIdSchema }).strict();
|
|
16
|
-
const disconnectAction = z.object({ action: z.literal("disconnect"), walletRunId: walletRunIdSchema, connectionId: z.string().min(1) }).strict();
|
|
17
|
-
const accountAction = z.object({ action: z.literal("use_account"), walletRunId: walletRunIdSchema, connectionId: z.string().min(1), account: suiAddressStringSchema }).strict();
|
|
20
|
+
export const pendingConnectionStatusSchema = z.enum(["awaiting_approval", "disconnect_pending", "cleanup_pending"]);
|
|
18
21
|
const reviewAction = z.object({ action: z.enum(["prepare_review", "request_signature"]), connectionId: z.string().min(1),
|
|
19
22
|
walletRunId: walletRunIdSchema, account: suiAddressStringSchema, reviewRevision: z.number().int().nonnegative() }).strict();
|
|
20
|
-
const simpleAction = z.object({ action: z.enum(["cancel", "
|
|
21
|
-
|
|
22
|
-
export const
|
|
23
|
+
const simpleAction = z.object({ action: z.enum(["cancel", "stop_waiting", "read_result"]) }).strict();
|
|
24
|
+
const stopConnectionAction = z.object({ action: z.literal("stop_connection"), operationId: z.string().uuid() }).strict();
|
|
25
|
+
export const workflowActionSchema = z.union([walletConnectionActionSchema, stopConnectionAction, reviewAction, simpleAction]);
|
|
26
|
+
export const automaticWorkflowActionSchema = z.union([walletConnectionActionSchema.options[0], reviewAction.extend({ action: z.literal("prepare_review") })]);
|
|
23
27
|
export function parseWorkflowAction(input) {
|
|
24
28
|
const action = workflowActionSchema.parse(input);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
allowedActions: z.array(z.enum(workflowActions)),
|
|
31
|
-
actionRemainingMs: z.number().int().nonnegative(),
|
|
32
|
-
nextStateReadAfterMs: z.number().int().nonnegative().optional(),
|
|
33
|
-
automaticAction: automaticWorkflowActionSchema.optional(),
|
|
34
|
-
observe: z.boolean(),
|
|
35
|
-
walletAvailability: walletAvailabilitySchema,
|
|
36
|
-
walletObservation: walletObservationSchema.optional(),
|
|
37
|
-
runtimeRecovery: walletRecoverySchema.optional(),
|
|
38
|
-
connectionConflict: connectionConflictSchema.optional(),
|
|
39
|
-
manageableConnectionIds: z.array(z.string().min(1)),
|
|
40
|
-
connectionReconciliationRequired: z.literal(true).optional(),
|
|
41
|
-
usableConnectionId: z.string().min(1).optional(),
|
|
42
|
-
assetReadAccount: assetReadAccountSchema.optional(),
|
|
43
|
-
acceptedWalletRunId: walletRunIdSchema.optional(),
|
|
44
|
-
progress: workflowProgressSchema,
|
|
45
|
-
boundary: z.enum([CONNECT_BOUNDARY, REVIEW_BOUNDARY]),
|
|
46
|
-
connections: z.array(connectionViewSchema),
|
|
47
|
-
activeAccount: z.string().optional(),
|
|
48
|
-
connection: connectionViewSchema.optional(),
|
|
49
|
-
connectionAction: z.enum(["connect", "disconnect"]).optional(),
|
|
50
|
-
review: z.object({
|
|
51
|
-
reviewSessionId: z.string(), plan: actionPlanSchema, reviewRevision: z.number().int().nonnegative(),
|
|
52
|
-
status: internalSessionStatusSchema, account: z.string().optional(), preparing: z.boolean(),
|
|
53
|
-
accountRequestPending: z.literal(true).optional(),
|
|
54
|
-
error: z.string().optional(),
|
|
55
|
-
state: reviewStateOutputSchema.optional()
|
|
56
|
-
}).strict().optional(),
|
|
57
|
-
request: transactionRequestSchema.optional(),
|
|
58
|
-
receipt: z.unknown().optional(),
|
|
59
|
-
netGasMist: z.string().regex(/^-?[0-9]+$/).optional(),
|
|
60
|
-
observationStopped: z.boolean().optional()
|
|
61
|
-
}).strict().superRefine((view, context) => {
|
|
62
|
-
const connection = view.connections.find((item) => item.connectionId === view.usableConnectionId);
|
|
63
|
-
if (view.usableConnectionId && (!connection || connection.status !== "connected" ||
|
|
64
|
-
view.walletAvailability.status !== "available" || view.connectionConflict || view.connectionReconciliationRequired ||
|
|
65
|
-
view.connections.some((item) => item.pendingAction || item.status === "awaiting_approval"))) {
|
|
66
|
-
context.addIssue({ code: "custom", path: ["usableConnectionId"], message: "The usable connection must match current connection facts." });
|
|
67
|
-
}
|
|
68
|
-
if (new Set(view.manageableConnectionIds).size !== view.manageableConnectionIds.length ||
|
|
69
|
-
view.manageableConnectionIds.some((id) => !view.connections.some((item) => item.connectionId === id &&
|
|
70
|
-
!item.pendingAction && item.status !== "awaiting_approval"))) {
|
|
71
|
-
context.addIssue({ code: "custom", path: ["manageableConnectionIds"], message: "Management must name distinct recorded targets without pending operations." });
|
|
29
|
+
if ("account" in action) {
|
|
30
|
+
const account = normalizeChainAddress(SUI_MAINNET_WALLET_CHAIN, action.account);
|
|
31
|
+
if (!account)
|
|
32
|
+
throw new Error("A valid chain account is required.");
|
|
33
|
+
return { ...action, account };
|
|
72
34
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
context.addIssue({ code: "custom", path: ["assetReadAccount"], message: "The default address must belong to the usable connection and stored selection." });
|
|
35
|
+
return action;
|
|
36
|
+
}
|
|
37
|
+
function checkReviewAccount(view, context) {
|
|
38
|
+
if (view.reviewTarget && (view.review?.account && view.review.account !== view.reviewTarget.account ||
|
|
39
|
+
view.request && view.request.account !== view.reviewTarget.account)) {
|
|
40
|
+
context.addIssue({ code: "custom", path: ["reviewTarget"], message: "The fixed review target must match its recorded account and request." });
|
|
80
41
|
}
|
|
81
|
-
}
|
|
42
|
+
}
|
|
43
|
+
const nextStepSchema = z.object({ kind: z.enum(workflowNextSteps), message: z.string().optional(), reason: z.string().optional() }).strict();
|
|
44
|
+
const liveFields = {
|
|
45
|
+
allowedActions: z.array(z.enum(workflowActions)), actionRemainingMs: z.number().int().nonnegative(),
|
|
46
|
+
nextStateReadAfterMs: z.number().int().nonnegative().optional(), observe: z.boolean(),
|
|
47
|
+
walletAvailability: walletAvailabilitySchema, walletObservation: walletObservationSchema.optional(),
|
|
48
|
+
progress: workflowProgressSchema, nextStep: nextStepSchema
|
|
49
|
+
};
|
|
50
|
+
export const connectViewSchema = z.object({ ...liveFields, kind: z.literal("connect"), mode: z.literal("connect"),
|
|
51
|
+
allowedActions: z.array(z.enum(["connect", "cancel", "stop_connection"])),
|
|
52
|
+
boundary: z.literal(CONNECT_BOUNDARY), requestedChains: walletChainsSchema,
|
|
53
|
+
operation: walletConnectionOperationSchema.optional(), automaticAction: walletConnectionActionSchema.options[0].optional() }).strict();
|
|
54
|
+
export const disconnectViewSchema = z.object({ ...liveFields, kind: z.literal("disconnect"), mode: z.literal("disconnect"),
|
|
55
|
+
allowedActions: z.array(z.enum(["disconnect", "cancel"])),
|
|
56
|
+
boundary: z.literal(CONNECT_BOUNDARY), connection: connectionViewSchema.optional(),
|
|
57
|
+
operation: walletConnectionOperationSchema.optional() }).strict();
|
|
58
|
+
const reviewPayloadSchema = z.object({
|
|
59
|
+
reviewSessionId: z.string(), plan: actionPlanSchema, reviewRevision: z.number().int().nonnegative(),
|
|
60
|
+
status: internalSessionStatusSchema, account: z.string().optional(), preparing: z.boolean(),
|
|
61
|
+
accountRequestPending: z.literal(true).optional(), error: z.string().optional(), state: reviewStateOutputSchema.optional()
|
|
62
|
+
}).strict();
|
|
63
|
+
const reviewTargetSchema = z.object({ connectionId: z.string(), account: suiAddressStringSchema }).strict();
|
|
64
|
+
const netGasSchema = z.string().regex(/^-?[0-9]+$/).optional();
|
|
65
|
+
export const reviewViewSchema = z.object({ ...liveFields, kind: z.literal("review"), mode: z.enum(["review", "review_manage"]),
|
|
66
|
+
allowedActions: z.array(z.enum(["prepare_review", "request_signature", "read_result", "stop_waiting", "cancel"])),
|
|
67
|
+
boundary: z.literal(REVIEW_BOUNDARY), reviewTarget: reviewTargetSchema.optional(), review: reviewPayloadSchema,
|
|
68
|
+
walletName: z.string().optional(), acceptedWalletRunId: walletRunIdSchema.optional(),
|
|
69
|
+
automaticAction: reviewAction.extend({ action: z.literal("prepare_review") }).optional(),
|
|
70
|
+
request: transactionRequestSchema.optional(), receipt: z.unknown().optional(), netGasMist: netGasSchema,
|
|
71
|
+
observationStopped: z.boolean().optional()
|
|
72
|
+
}).strict().superRefine(checkReviewAccount);
|
|
73
|
+
export const workflowViewSchema = z.discriminatedUnion("kind", [connectViewSchema, disconnectViewSchema, reviewViewSchema]);
|
|
74
|
+
const closedResult = z.object({ message: z.string(), recordedAt: z.string().datetime() }).strict();
|
|
75
|
+
const closedFields = { allowedActions: z.array(z.never()), observe: z.literal(false), actionRemainingMs: z.literal(0), result: closedResult };
|
|
76
|
+
export const closedWalletCardSchema = z.object({ ...closedFields, kind: z.enum(["connect", "disconnect"]),
|
|
77
|
+
result: closedResult.extend({ pendingWork: z.enum(["approval_response", "session_removal", "session_status"]).optional() }), walletName: z.string().optional(),
|
|
78
|
+
networks: z.array(z.object({ chainId: walletChainSchema, status: z.enum(["bound", "not_approved", "multiple_accounts", "invalid_response"]) }).strict()) }).strict();
|
|
79
|
+
export const closedReviewCardSchema = z.object({ ...closedFields, kind: z.literal("review"),
|
|
80
|
+
mode: z.enum(["review", "review_manage"]), review: reviewPayloadSchema.optional(),
|
|
81
|
+
reviewTarget: reviewTargetSchema.optional(), request: transactionRequestSchema.optional(),
|
|
82
|
+
receipt: z.unknown().optional(), netGasMist: netGasSchema,
|
|
83
|
+
observationStopped: z.boolean().optional(), boundary: z.literal(REVIEW_BOUNDARY) }).strict().superRefine(checkReviewAccount);
|
|
82
84
|
function automaticReviewAction(input) {
|
|
83
85
|
const { record, session, request } = input;
|
|
84
86
|
if (!session || record?.scope !== "review" || request || session.preparationError ||
|
|
@@ -86,18 +88,11 @@ function automaticReviewAction(input) {
|
|
|
86
88
|
return undefined;
|
|
87
89
|
const needsPreparation = !session.reviewState && session.reviewRevision === 0 ||
|
|
88
90
|
session.reviewState?.status === "refresh_required" && session.reviewState.refreshReason === "review_evidence_stale";
|
|
89
|
-
if (!needsPreparation || input.
|
|
90
|
-
return undefined;
|
|
91
|
-
const account = input.assetReadAccount.account;
|
|
92
|
-
const candidates = reviewWalletChoices(input, account);
|
|
93
|
-
if (candidates.length !== 1)
|
|
91
|
+
if (!needsPreparation || !input.reviewTarget)
|
|
94
92
|
return undefined;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
export function reviewWalletChoices(selection, account, requireSigningMethod = false) {
|
|
99
|
-
return selection.connections.filter((item) => item.connectionId === selection.usableConnectionId && item.accounts.includes(account) &&
|
|
100
|
-
(!requireSigningMethod || item.methods.includes("sui_signTransaction")));
|
|
93
|
+
const account = input.reviewTarget.account;
|
|
94
|
+
return { action: "prepare_review", walletRunId: input.walletAvailability.walletRunId,
|
|
95
|
+
connectionId: input.reviewTarget.connectionId, account, reviewRevision: session.reviewRevision };
|
|
101
96
|
}
|
|
102
97
|
function nextStateRead(input) {
|
|
103
98
|
const walletInput = input.record?.state.state === "ready" && input.record.scope !== "review_manage" && !input.request &&
|
|
@@ -109,24 +104,20 @@ function nextStateRead(input) {
|
|
|
109
104
|
return delays.length ? Math.min(...delays) : undefined;
|
|
110
105
|
}
|
|
111
106
|
export function projectConnectionView(input) {
|
|
112
|
-
const { walletAvailability } = input;
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
connectionAction: ["connect", "disconnect"].includes(String(input.record?.acceptedInput?.action)) ? input.record?.acceptedInput?.action : undefined,
|
|
127
|
-
acceptedWalletRunId: input.record?.acceptedInput?.walletRunId,
|
|
128
|
-
...(readAfter === undefined ? {} : { nextStateReadAfterMs: readAfter }),
|
|
129
|
-
connections: input.connections, activeAccount: input.activeAccount, connection, boundary: CONNECT_BOUNDARY });
|
|
107
|
+
const { walletAvailability, operation } = input, readAfter = nextStateRead(input);
|
|
108
|
+
const progress = workflowProgress(!!operation && operation.status === "running", true, walletAvailability);
|
|
109
|
+
const common = { allowedActions: input.allowedActions, actionRemainingMs: input.actionRemainingMs,
|
|
110
|
+
observe: progress.status === "waiting", progress, walletAvailability, walletObservation: input.walletObservation,
|
|
111
|
+
operation, nextStep: input.nextStep, boundary: CONNECT_BOUNDARY,
|
|
112
|
+
...(readAfter === undefined ? {} : { nextStateReadAfterMs: readAfter }) };
|
|
113
|
+
if (input.record?.scope === "disconnect")
|
|
114
|
+
return disconnectViewSchema.parse({ ...common, kind: "disconnect", mode: "disconnect",
|
|
115
|
+
connection: input.connection?.connectionId === input.record.state.input.connectionId ? input.connection : undefined });
|
|
116
|
+
return connectViewSchema.parse({ ...common, kind: "connect", mode: "connect",
|
|
117
|
+
requestedChains: walletChainsSchema.parse(input.record?.state.input.requestedChains ?? input.requestedChains),
|
|
118
|
+
...(!operation && input.record?.operationId && input.allowedActions.includes("connect")
|
|
119
|
+
? { automaticAction: { action: "connect", operationId: input.record.operationId, walletRunId: walletAvailability.walletRunId,
|
|
120
|
+
chains: input.record.state.input.requestedChains } } : {}) });
|
|
130
121
|
}
|
|
131
122
|
export function projectReviewView(input) {
|
|
132
123
|
const { record, session, request, authority, walletAvailability, boundReview } = input;
|
|
@@ -139,11 +130,11 @@ export function projectReviewView(input) {
|
|
|
139
130
|
const gas = displayedReview?.simulation?.gasCostSummary;
|
|
140
131
|
const automaticAction = automaticReviewAction(input);
|
|
141
132
|
const readAfter = nextStateRead(input);
|
|
142
|
-
return
|
|
133
|
+
return reviewViewSchema.parse({ kind: "review", mode: record.scope === "review_manage" ? "review_manage" : "review",
|
|
143
134
|
allowedActions: input.allowedActions, actionRemainingMs: input.actionRemainingMs, observe: progress.status === "waiting", progress, walletAvailability,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
135
|
+
reviewTarget: input.reviewTarget, nextStep: input.nextStep,
|
|
136
|
+
walletName: input.connection?.connectionId === input.reviewTarget?.connectionId ? input.connection?.walletName : undefined,
|
|
137
|
+
boundary: REVIEW_BOUNDARY, receipt: input.receipt,
|
|
147
138
|
walletObservation: input.walletObservation,
|
|
148
139
|
acceptedWalletRunId: record.acceptedInput?.walletRunId,
|
|
149
140
|
...(readAfter === undefined ? {} : { nextStateReadAfterMs: readAfter }),
|
|
@@ -153,7 +144,7 @@ export function projectReviewView(input) {
|
|
|
153
144
|
status: boundReview?.status ?? session.status, account: boundReview?.account ?? session.account,
|
|
154
145
|
...(!request && !session.plans[0]?.reviewModel && input.busyForAccount ? { accountRequestPending: true } : {}),
|
|
155
146
|
preparing: !boundReview && !!session.preparationId,
|
|
156
|
-
error: !boundReview ? [input.preparationIssue && `
|
|
147
|
+
error: !boundReview ? [input.preparationIssue && `Review target: ${input.preparationIssue}`,
|
|
157
148
|
session.preparationError && `Earlier review message: “${session.preparationError}”`].filter(Boolean).join("\n\n") || undefined : undefined,
|
|
158
149
|
state: displayedReview },
|
|
159
150
|
request, observationStopped: authority ? authority.observation_stopped === 1 : undefined });
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { walletChainSchema } from "../core/session/chainAccounts.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
export const activeAccountResponseSchema = z.discriminatedUnion("status", [
|
|
3
4
|
z.object({
|
|
4
5
|
status: z.literal("set"),
|
|
5
6
|
account: z.string(),
|
|
7
|
+
chainId: walletChainSchema,
|
|
6
8
|
source: z.literal("wallet_connection"),
|
|
7
9
|
setAt: z.string(),
|
|
8
10
|
boundary: z.literal("read_context_only_not_signing_authorization")
|
|
@@ -16,6 +18,7 @@ export function activeAccountResponse(active) {
|
|
|
16
18
|
? {
|
|
17
19
|
status: "set",
|
|
18
20
|
account: active.address,
|
|
21
|
+
chainId: active.chainId,
|
|
19
22
|
source: active.source,
|
|
20
23
|
setAt: active.setAt,
|
|
21
24
|
boundary: "read_context_only_not_signing_authorization"
|
package/dist/mcp/prompts.js
CHANGED
|
@@ -8,7 +8,7 @@ export const MCP_PROMPTS = [
|
|
|
8
8
|
description: "Review current supported mainnet surfaces and tool status.",
|
|
9
9
|
text: [
|
|
10
10
|
"Inspect the Sui MCP server status and supported mainnet Sui protocol surfaces.",
|
|
11
|
-
"Use
|
|
11
|
+
"Use read_get_server_status first, then read_list_supported_protocols.",
|
|
12
12
|
"Report implemented tools separately from unavailable or blocked surfaces."
|
|
13
13
|
].join("\n")
|
|
14
14
|
},
|
|
@@ -18,8 +18,8 @@ export const MCP_PROMPTS = [
|
|
|
18
18
|
description: "Prepare a local review session for a supported action proposal.",
|
|
19
19
|
text: [
|
|
20
20
|
"Prepare a reviewable Sui action only through Sui MCP's review-session flow.",
|
|
21
|
-
"Use
|
|
22
|
-
"External proposals get read-only local review and never become signing material. Use
|
|
21
|
+
"Use action_create_proposal_review when the input is a structured external payment or Sui action proposal.",
|
|
22
|
+
"External proposals get read-only local review and never become signing material. Use action_start_review for a natural-language swap intent; after a wallet account is connected, account-bound review can reach ready_for_wallet_review, where an explicit Review card action can request approval in the user’s wallet through the backend.",
|
|
23
23
|
"Present the internal Review card and summarize the returned review checks. This MCP response never contains signing data, transaction bytes, or signing readiness; only an explicit UI action and wallet approval authorize the backend request; request status is separate from server-verified chain execution facts."
|
|
24
24
|
].join("\n")
|
|
25
25
|
}
|
|
@@ -56,6 +56,7 @@ function registerSurfacePrompt(server, name, surface, description) {
|
|
|
56
56
|
}));
|
|
57
57
|
}
|
|
58
58
|
export function registerMcpPrompts(server, surfaces = []) {
|
|
59
|
+
const registeredNames = [];
|
|
59
60
|
for (const prompt of MCP_PROMPTS) {
|
|
60
61
|
server.registerPrompt(prompt.name, {
|
|
61
62
|
title: prompt.title,
|
|
@@ -72,13 +73,18 @@ export function registerMcpPrompts(server, surfaces = []) {
|
|
|
72
73
|
}
|
|
73
74
|
]
|
|
74
75
|
}));
|
|
76
|
+
registeredNames.push(prompt.name);
|
|
75
77
|
}
|
|
76
78
|
for (const surface of surfaces) {
|
|
77
|
-
|
|
79
|
+
const name = promptNameFor(surface);
|
|
80
|
+
registerSurfacePrompt(server, name, surface, surface.description);
|
|
81
|
+
registeredNames.push(name);
|
|
78
82
|
}
|
|
79
83
|
for (const [action, group] of actionGroups(surfaces)) {
|
|
80
84
|
registerBareActionPrompt(server, action, group);
|
|
85
|
+
registeredNames.push(action);
|
|
81
86
|
}
|
|
87
|
+
return registeredNames;
|
|
82
88
|
}
|
|
83
89
|
export function bareActionPromptText(action, group, intent, protocol) {
|
|
84
90
|
const chosen = group.length === 1 ? group[0] : group.find((surface) => surface.protocolSlug === (protocol ?? "").trim());
|
package/dist/mcp/resources.js
CHANGED
|
@@ -42,7 +42,7 @@ export const MCP_RESOURCES = [
|
|
|
42
42
|
name: "deepbook-v3",
|
|
43
43
|
uri: "suimcp://protocols/deepbook-v3",
|
|
44
44
|
title: "DeepBookV3",
|
|
45
|
-
description: "Protocol reference only; use MCP tool responses and
|
|
45
|
+
description: "Protocol reference only; use MCP tool responses and read_list_supported_protocols for current support.",
|
|
46
46
|
path: "protocols/deepbook-v3.md"
|
|
47
47
|
},
|
|
48
48
|
{
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { EXTERNAL_PROPOSAL_SETTLEMENT_TOKEN_SELECTION_UNSUPPORTED_CLAIM_ID } from "../core/proposal/types.js";
|
|
2
2
|
import { TOOL_NAMES } from "./toolNames.js";
|
|
3
|
-
export function interactionStatusUserAnswerUse(hasWalletObservation = false,
|
|
3
|
+
export function interactionStatusUserAnswerUse(hasWalletObservation = false, reconciliationRequired = false) {
|
|
4
4
|
return {
|
|
5
5
|
canAnswer: [
|
|
6
6
|
"stored_active_account_read_context",
|
|
7
7
|
"wallet_connections_when_wallet_availability_is_available",
|
|
8
8
|
"connection_qualified_default_asset_account",
|
|
9
9
|
"pending_local_wallet_connection_interactions",
|
|
10
|
-
...(hasConnectionConflict ? ["multiple_saved_connections_require_user_targeted_disconnection"] : []),
|
|
11
10
|
...(reconciliationRequired ? ["unrecorded_service_connection_requires_wallet_removal_and_confirmed_absence"] : []),
|
|
12
11
|
"pending_local_review_interactions",
|
|
13
12
|
"wallet_operation_availability_separate_from_stored_transaction_facts"
|
|
@@ -25,11 +24,10 @@ export function interactionStatusUserAnswerUse(hasWalletObservation = false, has
|
|
|
25
24
|
"complete_wallet_history",
|
|
26
25
|
"profit_or_pnl"
|
|
27
26
|
],
|
|
28
|
-
preconditionFields: ["walletAvailability", "assetReadAccount",
|
|
27
|
+
preconditionFields: ["walletAvailability", "assetReadAccount",
|
|
29
28
|
...(reconciliationRequired ? ["connectionReconciliationRequired"] : [])],
|
|
30
|
-
answerFields: ["activeAccount", "
|
|
31
|
-
...(
|
|
32
|
-
"manageableConnectionIds", ...(reconciliationRequired ? ["connectionReconciliationRequired"] : []),
|
|
29
|
+
answerFields: ["activeAccount", "requestedChains", "connection", "assetReadAccount", "pendingWalletConnections", "pendingReviewSessions", "walletAvailability",
|
|
30
|
+
"canDisconnect", ...(reconciliationRequired ? ["connectionReconciliationRequired"] : []),
|
|
33
31
|
...(hasWalletObservation ? ["walletObservation"] : [])],
|
|
34
32
|
diagnosticOnlyFields: [
|
|
35
33
|
"pendingWalletConnections.truncated",
|
|
@@ -69,7 +67,7 @@ export function executionResultUserAnswerUse(fields = {}) {
|
|
|
69
67
|
"profit_or_pnl"
|
|
70
68
|
],
|
|
71
69
|
answerFields: [
|
|
72
|
-
"walletAvailability", "progress",
|
|
70
|
+
"walletAvailability", "progress",
|
|
73
71
|
...(fields.reconciliationRequired ? ["connectionReconciliationRequired"] : []), ...(hasWaitOutcome ? ["waitOutcome"] : []),
|
|
74
72
|
"reviewSessionId",
|
|
75
73
|
"status",
|
|
@@ -95,7 +93,7 @@ export function executionResultUserAnswerUse(fields = {}) {
|
|
|
95
93
|
}
|
|
96
94
|
};
|
|
97
95
|
}
|
|
98
|
-
export function reviewStatusUserAnswerUse(hasReviewState, hasAdapterLifecycle = false, hasHumanReadableReview = false, hasSimulation = false,
|
|
96
|
+
export function reviewStatusUserAnswerUse(hasReviewState, hasAdapterLifecycle = false, hasHumanReadableReview = false, hasSimulation = false, reconciliationRequired = false) {
|
|
99
97
|
return {
|
|
100
98
|
canAnswer: [
|
|
101
99
|
"current_local_review_session_status",
|
|
@@ -119,7 +117,7 @@ export function reviewStatusUserAnswerUse(hasReviewState, hasAdapterLifecycle =
|
|
|
119
117
|
"profit_or_pnl"
|
|
120
118
|
],
|
|
121
119
|
answerFields: [
|
|
122
|
-
"walletAvailability", "progress",
|
|
120
|
+
"walletAvailability", "progress",
|
|
123
121
|
...(reconciliationRequired ? ["connectionReconciliationRequired"] : []), "reviewSessionId",
|
|
124
122
|
"status",
|
|
125
123
|
"pollingStatus",
|
package/dist/mcp/server.js
CHANGED
|
@@ -19,9 +19,9 @@ export function createMcpServer(deps) {
|
|
|
19
19
|
});
|
|
20
20
|
registerMcpResources(server);
|
|
21
21
|
registerReadCards(server, deps);
|
|
22
|
-
registerMcpPrompts(server, deps.promptSurfaces ?? []);
|
|
22
|
+
const registeredPromptNames = registerMcpPrompts(server, deps.promptSurfaces ?? []);
|
|
23
23
|
registerAccountTools(server, deps);
|
|
24
|
-
registerReadTools(server, deps);
|
|
24
|
+
registerReadTools(server, deps, registeredPromptNames);
|
|
25
25
|
registerSettingsTools(server, deps);
|
|
26
26
|
registerActionTools(server, deps);
|
|
27
27
|
registerSessionTools(server, deps);
|