@wowok/agent-mcp 2.6.0 → 2.6.3

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 (186) hide show
  1. package/README.md +5 -3
  2. package/dist/customer/info-puzzle.d.ts +1 -1
  3. package/dist/customer/info-puzzle.js +4 -2
  4. package/dist/customer/risk-assessment.js +26 -4
  5. package/dist/customer/types.d.ts +2 -0
  6. package/dist/examples/guard-template-balance-check.json +38 -0
  7. package/dist/examples/guard-template-time-lock.json +39 -0
  8. package/dist/examples/machine-template-7node-rental.json +114 -0
  9. package/dist/examples/rental-ziroom-machine-create.json +137 -0
  10. package/dist/examples/rental-ziroom-permission-create.json +35 -0
  11. package/dist/examples/rental-ziroom-service-create.json +80 -0
  12. package/dist/examples/retail-myshop-service-create.json +88 -0
  13. package/dist/extensions/capability-manifest.d.ts +125 -0
  14. package/dist/extensions/capability-manifest.js +594 -0
  15. package/dist/extensions/constraint-registry.d.ts +24 -0
  16. package/dist/extensions/constraint-registry.js +196 -0
  17. package/dist/extensions/index.d.ts +12 -0
  18. package/dist/extensions/index.js +6 -0
  19. package/dist/extensions/metric-registry.d.ts +26 -0
  20. package/dist/extensions/metric-registry.js +257 -0
  21. package/dist/extensions/mode-evaluator.d.ts +15 -0
  22. package/dist/extensions/mode-evaluator.js +170 -0
  23. package/dist/extensions/modes.d.ts +2 -0
  24. package/dist/extensions/modes.js +493 -0
  25. package/dist/extensions/registry.d.ts +50 -0
  26. package/dist/extensions/registry.js +662 -0
  27. package/dist/extensions/types.d.ts +219 -0
  28. package/dist/extensions/types.js +1 -0
  29. package/dist/index.js +50 -0
  30. package/dist/knowledge/deployment-scanner.d.ts +3 -0
  31. package/dist/knowledge/deployment-scanner.js +64 -3
  32. package/dist/knowledge/fund-layer.d.ts +72 -0
  33. package/dist/knowledge/fund-layer.js +420 -0
  34. package/dist/knowledge/guard-render.d.ts +57 -0
  35. package/dist/knowledge/guard-render.js +700 -0
  36. package/dist/knowledge/guard-risk.d.ts +13 -0
  37. package/dist/knowledge/guard-risk.js +57 -0
  38. package/dist/knowledge/guard-submission-prompt.d.ts +31 -0
  39. package/dist/knowledge/guard-submission-prompt.js +171 -0
  40. package/dist/knowledge/guard-templates.js +278 -0
  41. package/dist/knowledge/machine-ledger.js +1 -1
  42. package/dist/knowledge/machine-render.d.ts +41 -0
  43. package/dist/knowledge/machine-render.js +565 -0
  44. package/dist/knowledge/machine-templates.js +24 -5
  45. package/dist/knowledge/reward-confirm.js +2 -2
  46. package/dist/knowledge/reward-puzzle.js +1 -1
  47. package/dist/knowledge/reward-risk.js +9 -9
  48. package/dist/knowledge/reward-templates.js +2 -2
  49. package/dist/knowledge/service-confirm.d.ts +15 -6
  50. package/dist/knowledge/service-confirm.js +119 -11
  51. package/dist/knowledge/service-context.js +1 -1
  52. package/dist/knowledge/service-ledger.js +1 -1
  53. package/dist/knowledge/service-risk.d.ts +1 -1
  54. package/dist/knowledge/service-risk.js +3 -3
  55. package/dist/knowledge/service-templates.js +2 -2
  56. package/dist/knowledge/service-translation.d.ts +1 -1
  57. package/dist/knowledge/service-translation.js +7 -7
  58. package/dist/knowledge/tool-constraints.js +6 -2
  59. package/dist/project/deployment-bridge.d.ts +1 -1
  60. package/dist/project/deployment-bridge.js +31 -7
  61. package/dist/project/deployment-doc.d.ts +3 -0
  62. package/dist/project/deployment-doc.js +76 -14
  63. package/dist/project/edit-planner.d.ts +123 -0
  64. package/dist/project/edit-planner.js +1371 -0
  65. package/dist/project/evaluation.d.ts +2 -0
  66. package/dist/project/evaluation.js +873 -88
  67. package/dist/project/graph-builder.d.ts +4 -1
  68. package/dist/project/graph-builder.js +132 -62
  69. package/dist/project/graph.d.ts +1 -0
  70. package/dist/project/handlers.d.ts +317 -6
  71. package/dist/project/handlers.js +1171 -19
  72. package/dist/project/stage-gate.d.ts +4 -0
  73. package/dist/project/stage-gate.js +64 -5
  74. package/dist/project/task-tracker.d.ts +26 -0
  75. package/dist/project/task-tracker.js +78 -0
  76. package/dist/safety/preview.js +16 -0
  77. package/dist/schema/call/allocation.d.ts +16 -16
  78. package/dist/schema/call/allocation.js +2 -2
  79. package/dist/schema/call/arbitration.js +19 -6
  80. package/dist/schema/call/base.d.ts +21 -13
  81. package/dist/schema/call/base.js +27 -6
  82. package/dist/schema/call/bridge.d.ts +5 -5
  83. package/dist/schema/call/bridge.js +3 -1
  84. package/dist/schema/call/contact.js +2 -2
  85. package/dist/schema/call/demand.d.ts +23 -31
  86. package/dist/schema/call/demand.js +2 -2
  87. package/dist/schema/call/guard.js +2 -2
  88. package/dist/schema/call/machine.d.ts +1976 -752
  89. package/dist/schema/call/machine.js +50 -4
  90. package/dist/schema/call/order.d.ts +149 -228
  91. package/dist/schema/call/order.js +4 -3
  92. package/dist/schema/call/payment.d.ts +183 -3
  93. package/dist/schema/call/payment.js +21 -3
  94. package/dist/schema/call/permission.js +2 -2
  95. package/dist/schema/call/personal.d.ts +241 -52
  96. package/dist/schema/call/progress.d.ts +53 -61
  97. package/dist/schema/call/progress.js +18 -4
  98. package/dist/schema/call/repository.d.ts +23 -31
  99. package/dist/schema/call/repository.js +2 -2
  100. package/dist/schema/call/reward.js +3 -3
  101. package/dist/schema/call/semantic.d.ts +1 -1
  102. package/dist/schema/call/semantic.js +37 -2
  103. package/dist/schema/call/service.d.ts +275 -127
  104. package/dist/schema/call/service.js +89 -13
  105. package/dist/schema/call/treasury.js +3 -3
  106. package/dist/schema/common/index.d.ts +13 -2
  107. package/dist/schema/common/index.js +80 -15
  108. package/dist/schema/local/index.d.ts +32 -35
  109. package/dist/schema/local/index.js +28 -6
  110. package/dist/schema/messenger/index.d.ts +274 -46
  111. package/dist/schema/operations.d.ts +1264 -544
  112. package/dist/schema/operations.js +65 -7
  113. package/dist/schema/project/index.d.ts +2846 -167
  114. package/dist/schema/project/index.js +570 -16
  115. package/dist/schema/query/index.d.ts +922 -349
  116. package/dist/schema/query/index.js +205 -42
  117. package/dist/schema/schema-query/index.d.ts +65 -3
  118. package/dist/schema/schema-query/index.js +38 -5
  119. package/dist/schema/utils/node-parser.js +20 -4
  120. package/dist/schema/utils/object-type-utils.d.ts +12 -0
  121. package/dist/schema/utils/object-type-utils.js +35 -0
  122. package/dist/schema/utils/permission-machine-check.d.ts +49 -0
  123. package/dist/schema/utils/permission-machine-check.js +121 -0
  124. package/dist/schema/utils/skills-recommendation.d.ts +2 -0
  125. package/dist/schema/utils/skills-recommendation.js +76 -0
  126. package/dist/schema-query/index.d.ts +20 -1
  127. package/dist/schema-query/index.js +306 -4
  128. package/dist/schemas/account_operation.output.json +7 -1
  129. package/dist/schemas/account_operation.schema.json +3 -3
  130. package/dist/schemas/bridge_operation.output.json +6 -0
  131. package/dist/schemas/bridge_operation.schema.json +1 -1
  132. package/dist/schemas/guard-templates.json +379 -0
  133. package/dist/schemas/guard2file.schema.json +1 -1
  134. package/dist/schemas/index.json +1 -1
  135. package/dist/schemas/local_info_operation.output.json +6 -0
  136. package/dist/schemas/local_mark_operation.output.json +7 -1
  137. package/dist/schemas/local_mark_operation.schema.json +1 -1
  138. package/dist/schemas/machineNode2file.schema.json +1 -1
  139. package/dist/schemas/messenger_operation.schema.json +4 -4
  140. package/dist/schemas/onchain_events.output.json +1 -1
  141. package/dist/schemas/onchain_operations.output.json +2820 -0
  142. package/dist/schemas/onchain_operations.schema.json +444 -330
  143. package/dist/schemas/onchain_operations_allocation.schema.json +37 -28
  144. package/dist/schemas/onchain_operations_arbitration.schema.json +16 -14
  145. package/dist/schemas/onchain_operations_contact.schema.json +10 -10
  146. package/dist/schemas/onchain_operations_demand.schema.json +10 -10
  147. package/dist/schemas/onchain_operations_gen_passport.schema.json +16 -16
  148. package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
  149. package/dist/schemas/onchain_operations_guard.schema.json +2 -2
  150. package/dist/schemas/onchain_operations_machine.schema.json +43 -35
  151. package/dist/schemas/onchain_operations_order.schema.json +72 -78
  152. package/dist/schemas/onchain_operations_payment.schema.json +141 -111
  153. package/dist/schemas/onchain_operations_permission.schema.json +3 -3
  154. package/dist/schemas/onchain_operations_personal.schema.json +7 -7
  155. package/dist/schemas/onchain_operations_progress.schema.json +9 -9
  156. package/dist/schemas/onchain_operations_proof.schema.json +8 -8
  157. package/dist/schemas/onchain_operations_repository.schema.json +10 -10
  158. package/dist/schemas/onchain_operations_reward.schema.json +14 -14
  159. package/dist/schemas/onchain_operations_service.schema.json +119 -48
  160. package/dist/schemas/onchain_operations_treasury.schema.json +11 -11
  161. package/dist/schemas/onchain_table_data.output.json +33 -25
  162. package/dist/schemas/onchain_table_data.schema.json +22 -21
  163. package/dist/schemas/project_operation.output.json +2194 -23
  164. package/dist/schemas/project_operation.schema.json +84 -6
  165. package/dist/schemas/query_toolkit.output.json +108 -80
  166. package/dist/schemas/query_toolkit.schema.json +12 -12
  167. package/dist/schemas/schema_query.output.json +70 -3
  168. package/dist/schemas/schema_query.schema.json +18 -3
  169. package/dist/schemas/wowok_buildin_info.output.json +81 -8
  170. package/dist/schemas/wowok_buildin_info.schema.json +46 -2
  171. package/dist/tools/handlers/local.js +20 -5
  172. package/dist/tools/handlers/onchain.js +594 -6
  173. package/dist/tools/handlers/project.js +76 -4
  174. package/dist/tools/handlers/query.js +27 -0
  175. package/dist/tools/handlers/schema-query.js +43 -1
  176. package/dist/tools/handlers/task-status.d.ts +170 -0
  177. package/dist/tools/handlers/task-status.js +55 -0
  178. package/dist/tools/handlers/wip.js +47 -1
  179. package/dist/tools/index.d.ts +8 -0
  180. package/dist/tools/index.js +387 -12
  181. package/dist/tools/retry.d.ts +8 -0
  182. package/dist/tools/retry.js +85 -0
  183. package/dist/tools/wip-deploy-assist.d.ts +28 -0
  184. package/dist/tools/wip-deploy-assist.js +278 -0
  185. package/package.json +2 -2
  186. package/dist/schemas/guard-node-examples.md +0 -199
@@ -0,0 +1,420 @@
1
+ import { GasTokenType } from "@wowok/wowok";
2
+ const GAS_TOKENS = [
3
+ {
4
+ type: "0x2::wow::WOW",
5
+ symbol: "WOW",
6
+ decimals: 9,
7
+ name: "Wowok Token",
8
+ description: "Default platform gas token for all WoWok operations. 1 WOW = 10^9 MIST. Available on testnet and mainnet.",
9
+ },
10
+ ];
11
+ const TESTNET_TOKENS = [];
12
+ function buildMainnetTokensFromSDK() {
13
+ try {
14
+ const { MAINNET_BRIDGE_CONFIG } = require("@wowok/wowok");
15
+ if (!MAINNET_BRIDGE_CONFIG?.tokens)
16
+ return [];
17
+ const seen = new Set();
18
+ return MAINNET_BRIDGE_CONFIG.tokens
19
+ .filter((t) => {
20
+ if (seen.has(t.wowTypeTag))
21
+ return false;
22
+ seen.add(t.wowTypeTag);
23
+ return true;
24
+ })
25
+ .map((t) => ({
26
+ type: t.wowTypeTag,
27
+ symbol: t.symbol,
28
+ decimals: t.wowDecimals,
29
+ name: `${t.symbol} (Bridge)`,
30
+ description: t.description ?? `Bridge token on WOW mainnet. ${t.wowDecimals} decimals.`,
31
+ }));
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+ export const OFFICIAL_TOKEN_REGISTRY = {
38
+ gas: GAS_TOKENS,
39
+ testnet: TESTNET_TOKENS,
40
+ mainnet: buildMainnetTokensFromSDK(),
41
+ };
42
+ export function getRegistryForNetwork(network) {
43
+ return [
44
+ ...OFFICIAL_TOKEN_REGISTRY.gas,
45
+ ...(network === "testnet" ? OFFICIAL_TOKEN_REGISTRY.testnet : []),
46
+ ...(network === "mainnet" ? OFFICIAL_TOKEN_REGISTRY.mainnet : []),
47
+ ];
48
+ }
49
+ export function findInRegistryByType(tokenType, network) {
50
+ const gasMatch = OFFICIAL_TOKEN_REGISTRY.gas.find((t) => t.type === tokenType);
51
+ if (gasMatch)
52
+ return gasMatch;
53
+ const netTokens = getRegistryForNetwork(network);
54
+ return netTokens.find((t) => t.type === tokenType);
55
+ }
56
+ export function findInRegistryBySymbol(symbol, network) {
57
+ const lower = symbol.toLowerCase();
58
+ const gasMatches = OFFICIAL_TOKEN_REGISTRY.gas.filter((t) => t.symbol.toLowerCase() === lower);
59
+ const netTokens = getRegistryForNetwork(network);
60
+ const netMatches = netTokens.filter((t) => t.symbol.toLowerCase() === lower && !gasMatches.some((g) => g.type === t.type));
61
+ return [...gasMatches, ...netMatches];
62
+ }
63
+ export async function resolveTokenByType(tokenType, network) {
64
+ const registryEntry = findInRegistryByType(tokenType, network);
65
+ if (registryEntry) {
66
+ return {
67
+ type: registryEntry.type,
68
+ symbol: registryEntry.symbol,
69
+ decimals: registryEntry.decimals,
70
+ name: registryEntry.name,
71
+ source: "registry",
72
+ verified: true,
73
+ };
74
+ }
75
+ try {
76
+ const { TokenInfo } = await import("@wowok/wowok");
77
+ const tokenInfo = TokenInfo.Instance();
78
+ const fetched = await tokenInfo.fetch(tokenType, undefined, network);
79
+ if (fetched) {
80
+ return {
81
+ type: fetched.type,
82
+ symbol: fetched.symbol ?? "",
83
+ decimals: fetched.decimals ?? 0,
84
+ name: fetched.name ?? "",
85
+ source: "cache",
86
+ verified: false,
87
+ };
88
+ }
89
+ }
90
+ catch {
91
+ }
92
+ return undefined;
93
+ }
94
+ export async function resolveTokensBySymbol(symbol, network, preferredType) {
95
+ const results = [];
96
+ const registryMatches = findInRegistryBySymbol(symbol, network);
97
+ for (const entry of registryMatches) {
98
+ results.push({
99
+ type: entry.type,
100
+ symbol: entry.symbol,
101
+ decimals: entry.decimals,
102
+ name: entry.name,
103
+ source: "registry",
104
+ verified: true,
105
+ });
106
+ }
107
+ try {
108
+ const { query_local_token_list } = await import("@wowok/wowok");
109
+ const cached = await query_local_token_list({ symbol });
110
+ for (const token of cached) {
111
+ if (results.some((r) => r.type === token.type))
112
+ continue;
113
+ results.push({
114
+ type: token.type,
115
+ symbol: token.symbol ?? "",
116
+ decimals: token.decimals ?? 0,
117
+ name: token.name ?? "",
118
+ source: "cache",
119
+ verified: false,
120
+ });
121
+ }
122
+ }
123
+ catch {
124
+ }
125
+ if (preferredType) {
126
+ results.sort((a, b) => {
127
+ if (a.type === preferredType)
128
+ return -1;
129
+ if (b.type === preferredType)
130
+ return 1;
131
+ if (a.verified && !b.verified)
132
+ return -1;
133
+ if (!a.verified && b.verified)
134
+ return 1;
135
+ return 0;
136
+ });
137
+ }
138
+ return results;
139
+ }
140
+ const AMOUNT_WITH_SYMBOL = /^(\d+(?:\.\d+)?)\s*([A-Za-z][A-Za-z0-9]*)$/;
141
+ export function isAmountWithSymbol(value) {
142
+ if (typeof value !== "string")
143
+ return false;
144
+ const match = value.match(AMOUNT_WITH_SYMBOL);
145
+ if (!match)
146
+ return false;
147
+ const symbol = match[2];
148
+ return symbol.length >= 2 && symbol.length <= 10;
149
+ }
150
+ export async function parseAmount(amount, tokenType, network) {
151
+ const originalInput = amount;
152
+ const resolution = await resolveTokenByType(tokenType, network);
153
+ const decimals = resolution?.decimals ?? 9;
154
+ const symbol = resolution?.symbol ?? "";
155
+ const source = resolution?.source ?? "registry";
156
+ const verified = resolution?.verified ?? false;
157
+ if (typeof amount === "string") {
158
+ const match = amount.match(AMOUNT_WITH_SYMBOL);
159
+ if (match) {
160
+ const numericPart = parseFloat(match[1]);
161
+ const symbolPart = match[2];
162
+ if (symbol && symbolPart.toLowerCase() !== symbol.toLowerCase()) {
163
+ throw new Error(`Amount symbol "${symbolPart}" does not match the expected token symbol "${symbol}" ` +
164
+ `(type: ${tokenType}). Either use the correct symbol or pass a pure numeric value ` +
165
+ `in smallest units (e.g., ${(numericPart * Math.pow(10, decimals)).toFixed(0)}).`);
166
+ }
167
+ const smallestUnit = displayToSmallestUnit(numericPart, decimals);
168
+ return {
169
+ smallestUnit,
170
+ displayAmount: `${numericPart} ${symbolPart}`,
171
+ originalInput,
172
+ tokenType,
173
+ tokenSymbol: symbol || symbolPart,
174
+ decimals,
175
+ converted: true,
176
+ source,
177
+ verified,
178
+ };
179
+ }
180
+ }
181
+ let smallestUnit;
182
+ try {
183
+ smallestUnit = BigInt(amount);
184
+ }
185
+ catch {
186
+ throw new Error(`Invalid amount: "${amount}". Expected a number, a numeric string (smallest unit), ` +
187
+ `or a display-format string like "2.5WOW" (matching the token's symbol).`);
188
+ }
189
+ const displayValue = smallestToDisplay(smallestUnit, decimals);
190
+ return {
191
+ smallestUnit,
192
+ displayAmount: symbol ? `${displayValue} ${symbol}` : displayValue,
193
+ originalInput,
194
+ tokenType,
195
+ tokenSymbol: symbol,
196
+ decimals,
197
+ converted: false,
198
+ source,
199
+ verified,
200
+ };
201
+ }
202
+ function displayToSmallestUnit(display, decimals) {
203
+ const str = display.toString();
204
+ const [wholePart, fracPart = ""] = str.split(".");
205
+ const paddedFrac = fracPart.padEnd(decimals, "0").slice(0, decimals);
206
+ const combined = wholePart + paddedFrac;
207
+ return BigInt(combined || "0");
208
+ }
209
+ export function smallestToDisplay(value, decimals) {
210
+ const divisor = BigInt(10) ** BigInt(decimals);
211
+ const whole = value / divisor;
212
+ const frac = value % divisor;
213
+ if (frac === 0n)
214
+ return whole.toString();
215
+ const fracStr = frac.toString().padStart(decimals, "0").replace(/0+$/, "");
216
+ return `${whole.toString()}.${fracStr}`;
217
+ }
218
+ export function generateFundConfirmation(fields, ambiguities = []) {
219
+ const hasAmbiguity = ambiguities.length > 0;
220
+ const parts = [
221
+ "MONEY TRANSACTION CONFIRMATION REQUIRED",
222
+ "",
223
+ ];
224
+ for (const field of fields) {
225
+ const verifiedTag = field.verified ? " [VERIFIED]" : " [UNVERIFIED]";
226
+ const sourceTag = ` (source: ${field.source})`;
227
+ parts.push(` • ${field.context}: ${field.displayAmount}${verifiedTag}${sourceTag}`);
228
+ if (field.converted) {
229
+ parts.push(` (converted from display format to smallest unit)`);
230
+ }
231
+ }
232
+ if (hasAmbiguity) {
233
+ parts.push("", "AMBIGUITY WARNING — multiple tokens share the same symbol:");
234
+ for (const amb of ambiguities) {
235
+ parts.push(` Symbol "${amb.symbol}" matches:`);
236
+ for (const c of amb.candidates) {
237
+ const vTag = c.verified ? " [VERIFIED]" : " [UNVERIFIED]";
238
+ parts.push(` - type: ${c.type}, decimals: ${c.decimals}${vTag} (source: ${c.source})`);
239
+ }
240
+ parts.push(` → Specify the full type string in type_parameter to disambiguate.`);
241
+ }
242
+ }
243
+ parts.push("", "This operation involves money. Please confirm before proceeding.");
244
+ return {
245
+ requiresConfirmation: true,
246
+ reason: hasAmbiguity
247
+ ? "Money transaction with ambiguous token symbol — user must specify full type"
248
+ : "Money transaction requires user confirmation",
249
+ fields,
250
+ ambiguities,
251
+ message: parts.join("\n"),
252
+ };
253
+ }
254
+ function extractTokenType(data, operationType) {
255
+ if (data?.object && typeof data.object === "object" && data.object.type_parameter) {
256
+ return data.object.type_parameter;
257
+ }
258
+ if (operationType === "payment" && data?.type_parameter) {
259
+ return data.type_parameter;
260
+ }
261
+ return GasTokenType;
262
+ }
263
+ const MONETARY_FIELDS = {
264
+ service: [
265
+ { path: "sales.sales", context: "Service sale price", isArray: true, amountField: "price" },
266
+ { path: "compensation_fund_add.balance", context: "Service compensation fund deposit" },
267
+ { path: "order_new.buy.total_pay.balance", context: "Order payment amount" },
268
+ { path: "discount.discount_value", context: "Discount value" },
269
+ ],
270
+ arbitration: [
271
+ { path: "dispute.fee.balance", context: "Arbitration dispute fee" },
272
+ { path: "fee", context: "Arbitration fee" },
273
+ ],
274
+ reward: [
275
+ { path: "coin_add.balance", context: "Reward coin add" },
276
+ ],
277
+ treasury: [
278
+ { path: "deposit.coin.balance", context: "Treasury deposit amount" },
279
+ { path: "withdraw.amount.fixed", context: "Treasury withdrawal amount" },
280
+ ],
281
+ payment: [
282
+ { path: "revenue", context: "Payment amount", isArray: true, amountField: "amount.balance" },
283
+ ],
284
+ };
285
+ function getNestedValue(obj, path) {
286
+ const parts = path.split(".");
287
+ let current = obj;
288
+ for (const part of parts) {
289
+ if (current == null)
290
+ return undefined;
291
+ current = current[part];
292
+ }
293
+ return current;
294
+ }
295
+ export async function processFundOperation(data, operationType, network) {
296
+ const result = {
297
+ convertedData: data,
298
+ warnings: [],
299
+ confirmation: null,
300
+ };
301
+ const fields = MONETARY_FIELDS[operationType];
302
+ if (!fields) {
303
+ return result;
304
+ }
305
+ const tokenType = extractTokenType(data, operationType);
306
+ const confirmationFields = [];
307
+ const ambiguities = [];
308
+ const seenSymbols = new Map();
309
+ for (const fieldDesc of fields) {
310
+ const isArr = fieldDesc.isArray === true;
311
+ const amountField = fieldDesc.amountField;
312
+ if (isArr && amountField) {
313
+ const arr = getNestedValue(data, fieldDesc.path);
314
+ if (Array.isArray(arr)) {
315
+ for (let i = 0; i < arr.length; i++) {
316
+ const item = arr[i];
317
+ const parts = amountField.split(".");
318
+ let parentObj = item;
319
+ for (let j = 0; j < parts.length - 1; j++) {
320
+ parentObj = parentObj?.[parts[j]];
321
+ if (parentObj == null)
322
+ break;
323
+ }
324
+ const finalKey = parts[parts.length - 1];
325
+ if (parentObj && parentObj[finalKey] != null) {
326
+ const path = `${fieldDesc.path}[${i}].${amountField}`;
327
+ await processSingleField(parentObj, finalKey, path, fieldDesc.context, tokenType, network, result, confirmationFields, ambiguities, seenSymbols);
328
+ }
329
+ }
330
+ }
331
+ }
332
+ else {
333
+ const lastDot = fieldDesc.path.lastIndexOf(".");
334
+ const parentPath = lastDot >= 0 ? fieldDesc.path.slice(0, lastDot) : "";
335
+ const finalKey = lastDot >= 0 ? fieldDesc.path.slice(lastDot + 1) : fieldDesc.path;
336
+ const parentObj = parentPath ? getNestedValue(data, parentPath) : data;
337
+ if (parentObj && parentObj[finalKey] != null) {
338
+ await processSingleField(parentObj, finalKey, fieldDesc.path, fieldDesc.context, tokenType, network, result, confirmationFields, ambiguities, seenSymbols);
339
+ }
340
+ }
341
+ }
342
+ if (confirmationFields.length > 0) {
343
+ result.confirmation = generateFundConfirmation(confirmationFields, ambiguities);
344
+ const totalAmounts = confirmationFields.length;
345
+ const hasUnverified = confirmationFields.some((f) => !f.verified);
346
+ const hasAmbiguity = ambiguities.length > 0;
347
+ if (hasAmbiguity) {
348
+ result.warnings.push(`AMBIGUOUS TOKEN: ${ambiguities.length} token symbol(s) have multiple candidates. ` +
349
+ `User must specify full type string in type_parameter to disambiguate. ` +
350
+ `See confirmation message for details.`);
351
+ }
352
+ if (hasUnverified) {
353
+ result.warnings.push(`UNVERIFIED TOKEN: some monetary fields use tokens not in the official registry. ` +
354
+ `Precision was resolved from cache/on-chain. Verify the token type before proceeding.`);
355
+ }
356
+ result.warnings.push(`MONEY CONFIRMATION: ${totalAmounts} monetary field(s) require user confirmation. ` +
357
+ `Token type: ${tokenType}. Use env.confirmed=true after user consent.`);
358
+ }
359
+ return result;
360
+ }
361
+ async function processSingleField(parentObj, fieldKey, fieldPath, context, tokenType, network, result, confirmationFields, ambiguities, seenSymbols) {
362
+ const value = parentObj[fieldKey];
363
+ if (value == null)
364
+ return;
365
+ try {
366
+ const parsed = await parseAmount(value, tokenType, network);
367
+ if (parsed.converted) {
368
+ parentObj[fieldKey] = parsed.smallestUnit.toString();
369
+ }
370
+ confirmationFields.push({
371
+ path: fieldPath,
372
+ displayAmount: parsed.displayAmount,
373
+ tokenType: parsed.tokenType,
374
+ tokenSymbol: parsed.tokenSymbol,
375
+ verified: parsed.verified,
376
+ source: parsed.source,
377
+ converted: parsed.converted,
378
+ context,
379
+ });
380
+ if (parsed.tokenSymbol && parsed.source !== "registry") {
381
+ const symbolKey = parsed.tokenSymbol.toLowerCase();
382
+ let candidates = seenSymbols.get(symbolKey);
383
+ if (!candidates) {
384
+ const allMatches = await resolveTokensBySymbol(parsed.tokenSymbol, network, tokenType);
385
+ if (allMatches.length > 1) {
386
+ candidates = allMatches;
387
+ seenSymbols.set(symbolKey, candidates);
388
+ ambiguities.push({
389
+ symbol: parsed.tokenSymbol,
390
+ candidates: candidates.map((c) => ({
391
+ type: c.type,
392
+ decimals: c.decimals,
393
+ source: c.source,
394
+ verified: c.verified,
395
+ })),
396
+ });
397
+ }
398
+ }
399
+ }
400
+ }
401
+ catch (err) {
402
+ result.warnings.push(`FUND LAYER ERROR at ${fieldPath}: ${err.message}`);
403
+ }
404
+ }
405
+ export function generateSkillsHint(confirmation) {
406
+ if (!confirmation || !confirmation.requiresConfirmation)
407
+ return null;
408
+ const hasAmbiguity = confirmation.ambiguities.length > 0;
409
+ if (hasAmbiguity) {
410
+ return ("SKILLS HINT: This money transaction has ambiguous token symbols. " +
411
+ "If the wowok-safety skill is installed, it can guide the user through " +
412
+ "interactive disambiguation. Otherwise, the MCP fund layer has already " +
413
+ "listed all candidates in the confirmation message — ask the user to " +
414
+ "specify the full token type string in type_parameter.");
415
+ }
416
+ return ("SKILLS HINT: This money transaction requires user confirmation. " +
417
+ "If the wowok-safety skill is installed, it provides R1-R10 confirmation " +
418
+ "dialogue scripts. Otherwise, present the confirmation message to the user " +
419
+ "and proceed only after explicit consent (env.confirmed=true).");
420
+ }
@@ -0,0 +1,57 @@
1
+ export interface GuardNodeForRender {
2
+ type: string;
3
+ nodes?: GuardNodeForRender[];
4
+ node?: GuardNodeForRender;
5
+ nodeLeft?: GuardNodeForRender;
6
+ nodeRight?: GuardNodeForRender;
7
+ query?: number | string;
8
+ object?: {
9
+ identifier?: number;
10
+ convert_witness?: number;
11
+ };
12
+ parameters?: GuardNodeForRender[];
13
+ identifier?: number;
14
+ context?: string;
15
+ historyIdx?: GuardNodeForRender;
16
+ sessionIdx?: GuardNodeForRender;
17
+ forwardIdx?: GuardNodeForRender;
18
+ where?: GuardNodeForRender;
19
+ find?: GuardNodeForRender;
20
+ objectLeft?: GuardNodeForRender;
21
+ objectRight?: GuardNodeForRender;
22
+ recipient?: GuardNodeForRender;
23
+ }
24
+ export interface GuardRenderInput {
25
+ root: GuardNodeForRender;
26
+ table?: Array<{
27
+ identifier: number;
28
+ name?: string;
29
+ value_type: string | number;
30
+ b_submission: boolean;
31
+ value?: unknown;
32
+ }>;
33
+ guardName?: string | null;
34
+ guardAddress?: string | null;
35
+ rely?: {
36
+ guards: string[];
37
+ logic_or?: boolean;
38
+ } | null;
39
+ }
40
+ export declare function renderGuardMermaid(root: GuardNodeForRender, options?: {
41
+ colored?: boolean;
42
+ }): string;
43
+ export declare function renderGuardTreeIndented(input: GuardRenderInput): string;
44
+ export declare function parseGuardTreeIndented(text: string): {
45
+ success: boolean;
46
+ data?: GuardNodeForRender;
47
+ errors: string[];
48
+ };
49
+ export declare function renderGuardAscii(input: GuardRenderInput): string;
50
+ export declare function renderGuardMarkmap(input: GuardRenderInput): string;
51
+ export declare function parseGuardTableJSON(text: string): Array<{
52
+ identifier: number;
53
+ name?: string;
54
+ value_type: string | number;
55
+ b_submission: boolean;
56
+ value?: unknown;
57
+ }> | null;