@wowok/agent-mcp 2.3.18 → 2.4.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.
- package/dist/customer/industry-risks.js +31 -31
- package/dist/customer/order-monitor.js +57 -57
- package/dist/customer/order-strategy.js +89 -89
- package/dist/customer/post-purchase.js +97 -97
- package/dist/customer/reminder-system.js +26 -26
- package/dist/customer/risk-assessment.js +46 -46
- package/dist/customer/types.d.ts +4 -4
- package/dist/customer/types.js +4 -4
- package/dist/customer/user-preferences.js +50 -50
- package/dist/experience/intent-distill.js +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -1624
- package/dist/knowledge/acquisition-flywheel.js +64 -64
- package/dist/knowledge/arbitration-trust.js +10 -10
- package/dist/knowledge/demand-matching.js +8 -8
- package/dist/knowledge/dynamic-pricing.js +18 -18
- package/dist/knowledge/flywheel-loop.js +11 -11
- package/dist/knowledge/glossary.js +22 -22
- package/dist/knowledge/guard-ledger.d.ts +1 -1
- package/dist/knowledge/guard-ledger.js +145 -104
- package/dist/knowledge/guard-lint.d.ts +77 -0
- package/dist/knowledge/guard-lint.js +670 -0
- package/dist/knowledge/guard-migration.d.ts +48 -0
- package/dist/knowledge/guard-migration.js +228 -0
- package/dist/knowledge/guard-puzzle.d.ts +109 -14
- package/dist/knowledge/guard-puzzle.js +627 -101
- package/dist/knowledge/guard-risk.d.ts +10 -1
- package/dist/knowledge/guard-risk.js +1634 -292
- package/dist/knowledge/guard-templates.d.ts +38 -0
- package/dist/knowledge/guard-templates.js +605 -0
- package/dist/knowledge/guard-translation.d.ts +14 -2
- package/dist/knowledge/guard-translation.js +825 -194
- package/dist/knowledge/index.d.ts +8 -4
- package/dist/knowledge/index.js +9 -5
- package/dist/knowledge/industry-evolution.js +29 -29
- package/dist/knowledge/industry-generalizer.js +52 -52
- package/dist/knowledge/industry-registry.js +20 -33
- package/dist/knowledge/intent-metrics.js +67 -67
- package/dist/knowledge/process-model.js +80 -80
- package/dist/knowledge/reputation-rules.js +9 -9
- package/dist/knowledge/reward-templates.js +51 -51
- package/dist/knowledge/safety-rules.js +3 -3
- package/dist/knowledge/tool-constraints.js +20 -4
- package/dist/knowledge/trust-metrics.js +26 -26
- package/dist/project/graph.d.ts +1 -0
- package/dist/project/graph.js +27 -1
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.js +39 -2
- package/dist/project/namespace.d.ts +11 -1
- package/dist/project/namespace.js +27 -2
- package/dist/project/query.d.ts +2 -0
- package/dist/project/query.js +56 -15
- package/dist/rules.d.ts +12 -0
- package/dist/rules.js +9 -0
- package/dist/schema/call/allocation.d.ts +10 -10
- package/dist/schema/call/base.js +19 -19
- package/dist/schema/call/bridge.d.ts +32 -32
- package/dist/schema/call/demand.d.ts +84 -84
- package/dist/schema/call/guard.d.ts +153 -0
- package/dist/schema/call/guard.js +50 -0
- package/dist/schema/call/machine.d.ts +38 -38
- package/dist/schema/call/permission.d.ts +78 -78
- package/dist/schema/call/repository.d.ts +22 -22
- package/dist/schema/call/semantic.js +229 -25
- package/dist/schema/call/service.d.ts +7 -7
- package/dist/schema/local/wip.d.ts +39 -19
- package/dist/schema/local/wip.js +5 -5
- package/dist/schema/messenger/index.d.ts +26 -26
- package/dist/schema/messenger/index.js +2 -2
- package/dist/schema/operations.d.ts +270 -192
- package/dist/schema/query/index.d.ts +184 -184
- package/dist/schema/query/index.js +15 -9
- package/dist/schema/trust/index.d.ts +4 -4
- package/dist/schema/utils/guard-parser.js +4 -4
- package/dist/schema/utils/guard-query-utils.d.ts +7 -0
- package/dist/schema/utils/guard-query-utils.js +14 -1
- package/dist/schema/utils/node-parser.js +14 -14
- package/dist/schemas/bridge_operation.output.json +15 -15
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/messenger_operation.output.json +18 -16
- package/dist/schemas/onchain_events.output.json +15 -15
- package/dist/schemas/onchain_operations.output.json +16 -16
- package/dist/schemas/onchain_operations.schema.json +11 -20
- package/dist/schemas/onchain_operations_allocation.schema.json +7 -10
- package/dist/schemas/onchain_operations_machine.schema.json +2 -5
- package/dist/schemas/onchain_operations_service.schema.json +2 -5
- package/dist/schemas/onchain_table_data.output.json +20 -26
- package/dist/schemas/wip_file.output.json +24 -1
- package/dist/tools/handlers/bridge.d.ts +1 -0
- package/dist/tools/handlers/bridge.js +1 -0
- package/dist/tools/handlers/config.d.ts +2 -0
- package/dist/tools/handlers/config.js +71 -0
- package/dist/tools/handlers/file-export.d.ts +3 -0
- package/dist/tools/handlers/file-export.js +90 -0
- package/dist/tools/handlers/local.d.ts +30 -0
- package/dist/tools/handlers/local.js +27 -0
- package/dist/tools/handlers/messenger.d.ts +16 -0
- package/dist/tools/handlers/messenger.js +187 -0
- package/dist/tools/handlers/onchain.d.ts +2 -0
- package/dist/tools/handlers/onchain.js +246 -0
- package/dist/tools/handlers/project.d.ts +2 -0
- package/dist/tools/handlers/project.js +53 -0
- package/dist/tools/handlers/query.d.ts +5 -0
- package/dist/tools/handlers/query.js +256 -0
- package/dist/tools/handlers/schema-query.d.ts +2 -0
- package/dist/tools/handlers/schema-query.js +92 -0
- package/dist/tools/handlers/trust.d.ts +2 -0
- package/dist/tools/handlers/trust.js +194 -0
- package/dist/tools/handlers/wip.d.ts +2 -0
- package/dist/tools/handlers/wip.js +44 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.js +479 -0
- package/dist/tools/rules-hook.d.ts +2 -0
- package/dist/tools/rules-hook.js +22 -0
- package/dist/tools/shared.d.ts +29 -0
- package/dist/tools/shared.js +130 -0
- package/dist/tools/types.d.ts +35 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/wrap.d.ts +6 -0
- package/dist/tools/wrap.js +55 -0
- package/package.json +19 -5
package/dist/index.js
CHANGED
|
@@ -1,92 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { z } from "zod";
|
|
3
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
4
|
import { readFileSync } from "fs";
|
|
6
|
-
import { resolve } from "path";
|
|
7
5
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import { assembleInfoPuzzle, assessRisk, } from "./customer/index.js";
|
|
18
|
-
const HARNESS_ENABLED = () => isRuntimeEnabled("harness");
|
|
19
|
-
function withHarness(base, operation, intent) {
|
|
20
|
-
if (!HARNESS_ENABLED())
|
|
21
|
-
return base;
|
|
22
|
-
try {
|
|
23
|
-
const harness = getHarness();
|
|
24
|
-
const expected = harness.expect(operation, intent, base.operation_type, base.data);
|
|
25
|
-
return {
|
|
26
|
-
...base,
|
|
27
|
-
harness,
|
|
28
|
-
expected,
|
|
29
|
-
operation_id: `${base.operation_type}_${Date.now()}`,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return base;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function buildPendingConfirmation(operation_type, data, env) {
|
|
37
|
-
const gate = confirmGate(operation_type, data, env, env?.user_intent_phrases);
|
|
38
|
-
if (gate.pass)
|
|
39
|
-
return { content: [], structuredContent: null };
|
|
40
|
-
const preview = gate.preview;
|
|
41
|
-
const rendered = renderPreview(preview);
|
|
42
|
-
const output = {
|
|
43
|
-
message: rendered,
|
|
44
|
-
result: {
|
|
45
|
-
type: "pending_confirmation",
|
|
46
|
-
preview,
|
|
47
|
-
rule_id: gate.rule_id,
|
|
48
|
-
},
|
|
49
|
-
semantic: {
|
|
50
|
-
intent: `${operation_type}_awaiting_confirmation`,
|
|
51
|
-
status: "pending_input",
|
|
52
|
-
summary: `Operation blocked by ConfirmGate (${gate.level}). Review the preview and re-call with env.confirmed=true to proceed.`,
|
|
53
|
-
next_actions: [
|
|
54
|
-
{
|
|
55
|
-
action: "confirm: re-call the SAME operation with env.confirmed=true",
|
|
56
|
-
reason: `ConfirmGate rule '${gate.rule_id}' matched. The operation was NOT executed.`,
|
|
57
|
-
tool: "onchain_operations",
|
|
58
|
-
priority: "required",
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
warnings: preview.warnings ?? [],
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
return {
|
|
65
|
-
content: [{ type: "text", text: rendered }],
|
|
66
|
-
structuredContent: output,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
function buildConstraintError(operation_type, violations) {
|
|
70
|
-
const errors = violations.filter((v) => v.severity === "error");
|
|
71
|
-
const errorList = errors.map((v) => ` • [${v.field}] ${v.message}`).join("\n");
|
|
72
|
-
const message = `Pre-call constraint violations for '${operation_type}':\n${errorList}\n\nFix the listed field(s) and retry.`;
|
|
73
|
-
const output = {
|
|
74
|
-
message,
|
|
75
|
-
result: {
|
|
76
|
-
type: "error",
|
|
77
|
-
error: message,
|
|
78
|
-
error_code: "invalid_parameter",
|
|
79
|
-
retryable: false,
|
|
80
|
-
recovery_hint: "Review the constraint violations above and correct the corresponding fields.",
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
content: [{ type: "text", text: message }],
|
|
85
|
-
structuredContent: output,
|
|
86
|
-
};
|
|
6
|
+
import { OnchainOperationsSchema, WipOperationsSchema, WatchQueryOperationsSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, ProtocolInfoQuerySchema, CallOutputSchema, MessengerOperationInputSchema, MessengerOperationOutputSchema, createServerConfig, createCapabilitiesConfig, } from "./schema/index.js";
|
|
7
|
+
import { areSchemasAvailable, getSchemaIndex, } from "./schema-query/index.js";
|
|
8
|
+
import { isProjectServiceEnabled, observe as projectObserve, } from "./project/index.js";
|
|
9
|
+
import { registerSuccessHook } from "./schema/call/handler.js";
|
|
10
|
+
import { listServices } from "./config/index.js";
|
|
11
|
+
import { setTelemetryEnabled } from "./telemetry/index.js";
|
|
12
|
+
import { registerAllTools } from "./tools/index.js";
|
|
13
|
+
if (process.env.WOWOK_TELEMETRY === "false" || process.env.WOWOK_TELEMETRY === "0") {
|
|
14
|
+
setTelemetryEnabled(false);
|
|
87
15
|
}
|
|
88
|
-
import { CallService, CallMachine, CallProgress, CallPermission, CallGuard, CallArbitration, CallRepository, CallContact, CallTreasury, CallReward, CallAllocation, CallPersonal, CallPayment, CallDemand, CallOrder, gen_passport, CallProof, gen_proof, guard2file, parseGuardFile, formatGuardParseErrors, machineNode2file, generateNodeComments, generate_wip, verify_wip, sign_wip, wip2html, account_operation, local_mark_operation, local_info_operation, watch_conversations, send_message, send_file, watch_messages, extract_zip_messages, pull_messages, generate_wts, verify_wts, sign_wts, wts2html, proof_message, mark_messages_as_viewed, mark_conversation_as_viewed, query_local_mark_list, query_account_list, query_local_info_list, query_local_token_list, query_account, GetLocalNamesByAddresses, query_personal, query_objects, query_table, query_tableItem, queryProtocolInfo, query_received, queryTableItem_RepositoryData, queryTableItem_PermissionPerm, queryTableItem_RewardRecord, queryTableItem_DemandPresenter, queryTableItem_TreasuryHistory, queryTableItem_MachineNode, queryTableItem_ProgressHistory, queryTableItem_AddressMark, queryTableItem_EntityRegistrar, queryTableItem_EntityLinker, query_events, blacklist, friendslist, guardlist, settings, transformRewardInput, transformPersonalInput, } from "@wowok/wowok";
|
|
89
|
-
import { areSchemasAvailable, getSchemaIndex, processSchemaQuery, } from "./schema-query/index.js";
|
|
90
16
|
const SERVER_DESCRIPTION = `WoWok MCP Server - Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.
|
|
91
17
|
|
|
92
18
|
## CRITICAL: Schema Discovery Rule
|
|
@@ -195,1211 +121,7 @@ Token amounts are HIGHLY SENSITIVE. Always:
|
|
|
195
121
|
- machineNode2file
|
|
196
122
|
`;
|
|
197
123
|
const server = new McpServer(createServerConfig(packageJson, SERVER_DESCRIPTION), createCapabilitiesConfig());
|
|
198
|
-
|
|
199
|
-
if (process.env.WOWOK_TELEMETRY === "false" || process.env.WOWOK_TELEMETRY === "0") {
|
|
200
|
-
setTelemetryEnabled(false);
|
|
201
|
-
}
|
|
202
|
-
function buildClassifiedErrorResult(base, error, classified) {
|
|
203
|
-
const result = { ...base, error };
|
|
204
|
-
if (classified.error_code !== undefined)
|
|
205
|
-
result.error_code = classified.error_code;
|
|
206
|
-
if (classified.retryable !== undefined)
|
|
207
|
-
result.retryable = classified.retryable;
|
|
208
|
-
if (classified.recovery_hint !== undefined)
|
|
209
|
-
result.recovery_hint = classified.recovery_hint;
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
const statusErrorShape = (error, classified, ctx) => ({
|
|
213
|
-
result: buildClassifiedErrorResult({ status: "error" }, error, classified),
|
|
214
|
-
semantic: buildDataSemantic(undefined, ctx, true, error),
|
|
215
|
-
});
|
|
216
|
-
const operationErrorShape = (error, classified, ctx) => ({
|
|
217
|
-
result: buildClassifiedErrorResult({ operation: "error" }, error, classified),
|
|
218
|
-
semantic: buildDataSemantic(undefined, ctx, true, error),
|
|
219
|
-
});
|
|
220
|
-
const strictStatusErrorShape = (error, _classified, _ctx) => ({
|
|
221
|
-
result: { status: "error", error },
|
|
222
|
-
});
|
|
223
|
-
function reg(name, config, handler, errorShapeBuilder, customTimeoutMs) {
|
|
224
|
-
const timeoutMs = customTimeoutMs ?? 60000;
|
|
225
|
-
const wrappedHandler = wrapHandlerWithErrorShape(handler, timeoutMs, name, errorShapeBuilder);
|
|
226
|
-
server.registerTool(name, config, withTelemetry(name, wrappedHandler));
|
|
227
|
-
}
|
|
228
|
-
function withTimeout(promise, timeoutMs = 30000, operationName = "operation") {
|
|
229
|
-
let timer;
|
|
230
|
-
return Promise.race([
|
|
231
|
-
promise.finally(() => {
|
|
232
|
-
if (timer)
|
|
233
|
-
clearTimeout(timer);
|
|
234
|
-
}),
|
|
235
|
-
new Promise((_, reject) => {
|
|
236
|
-
timer = setTimeout(() => {
|
|
237
|
-
let hint = "";
|
|
238
|
-
if (operationName.includes("messenger")) {
|
|
239
|
-
hint = " This is a messenger network operation. Possible causes: " +
|
|
240
|
-
"(1) messenger server (https://messenger.wowok.net) unreachable, " +
|
|
241
|
-
"(2) no messenger-enabled account configured (use account_operation to set messenger name), " +
|
|
242
|
-
"(3) network connectivity issue. " +
|
|
243
|
-
"Ensure you have a messenger-enabled account and the server is reachable.";
|
|
244
|
-
}
|
|
245
|
-
reject(new Error(`Operation '${operationName}' timed out after ${timeoutMs}ms.${hint}`));
|
|
246
|
-
}, timeoutMs);
|
|
247
|
-
}),
|
|
248
|
-
]);
|
|
249
|
-
}
|
|
250
|
-
function wrapHandlerWithErrorShape(handler, timeoutMs, toolName, errorShapeBuilder) {
|
|
251
|
-
return async (args) => {
|
|
252
|
-
try {
|
|
253
|
-
return await withTimeout(handler(args), timeoutMs, toolName);
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
if (errorShapeBuilder) {
|
|
257
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
258
|
-
const classified = classifyError(errorMessage);
|
|
259
|
-
const ctx = { operation_type: toolName, data: args };
|
|
260
|
-
const structuredContent = errorShapeBuilder(errorMessage, classified, ctx);
|
|
261
|
-
return {
|
|
262
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
263
|
-
structuredContent,
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
throw error;
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
async function handleOnchainTableData(args) {
|
|
271
|
-
const validated = strictParse(OnchainTableDataSchema, args, "onchain_table_data input");
|
|
272
|
-
let result;
|
|
273
|
-
switch (validated.query_type) {
|
|
274
|
-
case "onchain_table": {
|
|
275
|
-
const queryResult = await query_table({ parent: validated.parent, cursor: validated.cursor, limit: validated.limit, no_cache: validated.no_cache, network: validated.network });
|
|
276
|
-
result = { query_type: "onchain_table", result: queryResult };
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
279
|
-
case "onchain_table_item_repository_data": {
|
|
280
|
-
const queryResult = await queryTableItem_RepositoryData({ parent: validated.parent, name: validated.name, entity: validated.entity, no_cache: validated.no_cache, network: validated.network });
|
|
281
|
-
result = { query_type: "onchain_table_item_repository_data", result: queryResult };
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
case "onchain_table_item_permission_perm": {
|
|
285
|
-
const queryResult = await queryTableItem_PermissionPerm({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
286
|
-
result = { query_type: "onchain_table_item_permission_perm", result: queryResult };
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
case "onchain_table_item_reward_record": {
|
|
290
|
-
const queryResult = await queryTableItem_RewardRecord({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
291
|
-
result = { query_type: "onchain_table_item_reward_record", result: queryResult };
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
case "onchain_table_item_demand_presenter": {
|
|
295
|
-
const queryResult = await queryTableItem_DemandPresenter({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
296
|
-
result = { query_type: "onchain_table_item_demand_presenter", result: queryResult };
|
|
297
|
-
break;
|
|
298
|
-
}
|
|
299
|
-
case "onchain_table_item_treasury_history": {
|
|
300
|
-
const queryResult = await queryTableItem_TreasuryHistory({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
301
|
-
result = { query_type: "onchain_table_item_treasury_history", result: queryResult };
|
|
302
|
-
break;
|
|
303
|
-
}
|
|
304
|
-
case "onchain_table_item_machine_node": {
|
|
305
|
-
const queryResult = await queryTableItem_MachineNode({ parent: validated.parent, key: validated.key, no_cache: validated.no_cache, network: validated.network });
|
|
306
|
-
result = { query_type: "onchain_table_item_machine_node", result: queryResult };
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
case "onchain_table_item_progress_history": {
|
|
310
|
-
const queryResult = await queryTableItem_ProgressHistory({ parent: validated.parent, u64: validated.u64, no_cache: validated.no_cache, network: validated.network });
|
|
311
|
-
result = { query_type: "onchain_table_item_progress_history", result: queryResult };
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
case "onchain_table_item_address_mark": {
|
|
315
|
-
const queryResult = await queryTableItem_AddressMark({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
316
|
-
result = { query_type: "onchain_table_item_address_mark", result: queryResult };
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
case "onchain_table_item_entity_registrar": {
|
|
320
|
-
const queryResult = await queryTableItem_EntityRegistrar({ address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
321
|
-
result = { query_type: "onchain_table_item_entity_registrar", result: queryResult };
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
case "onchain_table_item_entity_linker": {
|
|
325
|
-
const queryResult = await queryTableItem_EntityLinker({ address: validated.address, no_cache: validated.no_cache, network: validated.network });
|
|
326
|
-
result = { query_type: "onchain_table_item_entity_linker", result: queryResult };
|
|
327
|
-
break;
|
|
328
|
-
}
|
|
329
|
-
case "onchain_table_item_generic": {
|
|
330
|
-
const queryResult = await query_tableItem({
|
|
331
|
-
parent: validated.parent,
|
|
332
|
-
key: { type: validated.key_type, value: validated.key_value },
|
|
333
|
-
no_cache: validated.no_cache,
|
|
334
|
-
network: validated.network
|
|
335
|
-
});
|
|
336
|
-
result = { query_type: "onchain_table_item_generic", result: queryResult };
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
default:
|
|
340
|
-
throw new Error(`Unknown table query type. Valid query_types are: "onchain_table", "onchain_table_item_repository_data", "onchain_table_item_permission_perm", "onchain_table_item_reward_record", "onchain_table_item_demand_presenter", "onchain_table_item_treasury_history", "onchain_table_item_machine_node", "onchain_table_item_progress_history", "onchain_table_item_address_mark", "onchain_table_item_entity_registrar", "onchain_table_item_entity_linker", "onchain_table_item_generic"`);
|
|
341
|
-
}
|
|
342
|
-
return {
|
|
343
|
-
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
344
|
-
structuredContent: {
|
|
345
|
-
result,
|
|
346
|
-
semantic: buildDataSemantic(result, {
|
|
347
|
-
operation_type: "onchain_table_data",
|
|
348
|
-
data: validated,
|
|
349
|
-
}),
|
|
350
|
-
},
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
async function handleOnchainOperations(args) {
|
|
354
|
-
let validated;
|
|
355
|
-
let constraintWarnings = [];
|
|
356
|
-
try {
|
|
357
|
-
if (typeof args === 'object' && args !== null && args.description && !args.operation_type) {
|
|
358
|
-
const hasWrappedParams = typeof args.description === 'string' &&
|
|
359
|
-
(args.description.includes('operation_type') || args.description.includes('data'));
|
|
360
|
-
if (hasWrappedParams) {
|
|
361
|
-
throw new Error("Invalid parameter structure. Parameters should NOT be wrapped in 'description' field.\n" +
|
|
362
|
-
"Correct format: { operation_type: '...', data: {...} }\n" +
|
|
363
|
-
"Incorrect format: { description: '{ operation_type: ... }' }");
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
validated = strictParse(OnchainOperationsSchema, args, "onchain_operations input");
|
|
367
|
-
const env = getEnvConfig(validated.env);
|
|
368
|
-
const gateResult = buildPendingConfirmation(validated.operation_type, validated.data, env);
|
|
369
|
-
if (gateResult.structuredContent) {
|
|
370
|
-
return gateResult;
|
|
371
|
-
}
|
|
372
|
-
const constraintViolations = validateOperation(validated.operation_type, validated.data);
|
|
373
|
-
if (hasBlockingViolations(constraintViolations)) {
|
|
374
|
-
return buildConstraintError(validated.operation_type, constraintViolations);
|
|
375
|
-
}
|
|
376
|
-
constraintWarnings = getWarningViolations(constraintViolations).map((v) => `[PRE-CHECK] ${v.message}`);
|
|
377
|
-
const clientSchemaVersion = env?.client_schema_version;
|
|
378
|
-
const schemaStrictMode = env?.schema_strict_mode;
|
|
379
|
-
const schemaCheck = clientSchemaVersion
|
|
380
|
-
? checkClientSchemaCompatibility(clientSchemaVersion, { mode: schemaStrictMode ? "strict" : "warn" })
|
|
381
|
-
: undefined;
|
|
382
|
-
const buildCtx = (data) => ({
|
|
383
|
-
operation_type: validated.operation_type,
|
|
384
|
-
data,
|
|
385
|
-
pre_warnings: constraintWarnings.length ? constraintWarnings : undefined,
|
|
386
|
-
schema_check: schemaCheck,
|
|
387
|
-
});
|
|
388
|
-
const projectEnvPrefix = env?.project;
|
|
389
|
-
if (isProjectServiceEnabled()) {
|
|
390
|
-
const pn = projectNormalize({
|
|
391
|
-
operation_type: validated.operation_type,
|
|
392
|
-
data: validated.data,
|
|
393
|
-
projectPrefix: projectEnvPrefix,
|
|
394
|
-
});
|
|
395
|
-
validated.data = pn.data;
|
|
396
|
-
}
|
|
397
|
-
if (env && typeof env === "object") {
|
|
398
|
-
delete env.confirmed;
|
|
399
|
-
delete env.user_intent_phrases;
|
|
400
|
-
delete env.project;
|
|
401
|
-
delete env.client_schema_version;
|
|
402
|
-
delete env.schema_strict_mode;
|
|
403
|
-
}
|
|
404
|
-
switch (validated.operation_type) {
|
|
405
|
-
case "service": {
|
|
406
|
-
const callService = new CallService(validated.data);
|
|
407
|
-
const result = validated.submission
|
|
408
|
-
? await callService.call_with_submission(env, await transformSubmission(validated.submission))
|
|
409
|
-
: await callService.call(env);
|
|
410
|
-
const data = validated.data;
|
|
411
|
-
const intent = data?.publish ? "publish service" : data?.bPublished !== undefined ? "modify service" : "create service";
|
|
412
|
-
return handleCallResult(result, withHarness(buildCtx(data), "service", intent));
|
|
413
|
-
}
|
|
414
|
-
case "machine": {
|
|
415
|
-
if (validated.data.node && typeof validated.data.node === 'object' && 'json_or_markdown_file' in validated.data.node) {
|
|
416
|
-
const filePathStr = validated.data.node.json_or_markdown_file;
|
|
417
|
-
let fileContent;
|
|
418
|
-
try {
|
|
419
|
-
const filePath = resolve(filePathStr);
|
|
420
|
-
fileContent = readFileSync(filePath, 'utf-8');
|
|
421
|
-
}
|
|
422
|
-
catch (e) {
|
|
423
|
-
throw new Error(`Failed to read file '${filePathStr}': ${e.message}`);
|
|
424
|
-
}
|
|
425
|
-
const parseResult = parseMachineNodesFromText(fileContent);
|
|
426
|
-
if (!parseResult.success) {
|
|
427
|
-
const errorMessages = formatMachineNodeErrors(parseResult.errors);
|
|
428
|
-
throw new Error(`Machine node validation failed for file '${filePathStr}':\n\n${errorMessages}`);
|
|
429
|
-
}
|
|
430
|
-
if (!parseResult.data) {
|
|
431
|
-
throw new Error(`No nodes found in file '${filePathStr}'`);
|
|
432
|
-
}
|
|
433
|
-
validated.data.node = {
|
|
434
|
-
op: "set",
|
|
435
|
-
nodes: parseResult.data,
|
|
436
|
-
bReplace: true
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
const callMachine = new CallMachine(validated.data);
|
|
440
|
-
const result = validated.submission
|
|
441
|
-
? await callMachine.call_with_submission(env, await transformSubmission(validated.submission))
|
|
442
|
-
: await callMachine.call(env);
|
|
443
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
444
|
-
}
|
|
445
|
-
case "progress": {
|
|
446
|
-
const callProgress = new CallProgress(validated.data);
|
|
447
|
-
const result = validated.submission
|
|
448
|
-
? await callProgress.call_with_submission(env, await transformSubmission(validated.submission))
|
|
449
|
-
: await callProgress.call(env);
|
|
450
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
451
|
-
}
|
|
452
|
-
case "repository": {
|
|
453
|
-
const callRepository = new CallRepository(validated.data);
|
|
454
|
-
const result = validated.submission
|
|
455
|
-
? await callRepository.call_with_submission(env, await transformSubmission(validated.submission))
|
|
456
|
-
: await callRepository.call(env);
|
|
457
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
458
|
-
}
|
|
459
|
-
case "arbitration": {
|
|
460
|
-
const callArbitration = new CallArbitration(validated.data);
|
|
461
|
-
const result = validated.submission
|
|
462
|
-
? await callArbitration.call_with_submission(env, await transformSubmission(validated.submission))
|
|
463
|
-
: await callArbitration.call(env);
|
|
464
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
465
|
-
}
|
|
466
|
-
case "contact": {
|
|
467
|
-
const callContact = new CallContact(validated.data);
|
|
468
|
-
const result = validated.submission
|
|
469
|
-
? await callContact.call_with_submission(env, await transformSubmission(validated.submission))
|
|
470
|
-
: await callContact.call(env);
|
|
471
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
472
|
-
}
|
|
473
|
-
case "treasury": {
|
|
474
|
-
const callTreasury = new CallTreasury(validated.data);
|
|
475
|
-
const result = validated.submission
|
|
476
|
-
? await callTreasury.call_with_submission(env, await transformSubmission(validated.submission))
|
|
477
|
-
: await callTreasury.call(env);
|
|
478
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
479
|
-
}
|
|
480
|
-
case "reward": {
|
|
481
|
-
const transformedData = transformRewardInput(validated.data);
|
|
482
|
-
const callReward = new CallReward(transformedData);
|
|
483
|
-
const result = validated.submission
|
|
484
|
-
? await callReward.call_with_submission(env, await transformSubmission(validated.submission))
|
|
485
|
-
: await callReward.call(env);
|
|
486
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
487
|
-
}
|
|
488
|
-
case "allocation": {
|
|
489
|
-
const callAllocation = new CallAllocation(validated.data);
|
|
490
|
-
const result = validated.submission
|
|
491
|
-
? await callAllocation.call_with_submission(env, await transformSubmission(validated.submission))
|
|
492
|
-
: await callAllocation.call(env);
|
|
493
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
494
|
-
}
|
|
495
|
-
case "permission": {
|
|
496
|
-
const callPermission = new CallPermission(validated.data);
|
|
497
|
-
const result = await callPermission.call(env);
|
|
498
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
499
|
-
}
|
|
500
|
-
case "guard": {
|
|
501
|
-
const validatedData = validated.data;
|
|
502
|
-
if (validatedData.root?.type === "file") {
|
|
503
|
-
const filePath = resolve(validatedData.root.file_path);
|
|
504
|
-
let fileContent;
|
|
505
|
-
try {
|
|
506
|
-
fileContent = readFileSync(filePath, 'utf-8');
|
|
507
|
-
}
|
|
508
|
-
catch (e) {
|
|
509
|
-
throw new Error(`Failed to read Guard definition file '${validatedData.root.file_path}': ${e.message}`);
|
|
510
|
-
}
|
|
511
|
-
const parseResult = parseGuardFile(fileContent, validatedData.root.format);
|
|
512
|
-
if (!parseResult.success) {
|
|
513
|
-
const errorMessages = formatGuardParseErrors(parseResult.errors);
|
|
514
|
-
throw new Error(`Guard validation failed for file '${validatedData.root.file_path}':\n\n${errorMessages}`);
|
|
515
|
-
}
|
|
516
|
-
const fileData = parseResult.data;
|
|
517
|
-
validatedData.root = { type: "node", node: fileData.root };
|
|
518
|
-
if (fileData.table !== undefined && validatedData.table === undefined) {
|
|
519
|
-
validatedData.table = fileData.table;
|
|
520
|
-
}
|
|
521
|
-
if (fileData.description !== undefined && validatedData.description === undefined) {
|
|
522
|
-
validatedData.description = fileData.description;
|
|
523
|
-
}
|
|
524
|
-
if (fileData.rely !== undefined && validatedData.rely === undefined) {
|
|
525
|
-
validatedData.rely = fileData.rely;
|
|
526
|
-
}
|
|
527
|
-
if (fileData.namedNew !== undefined && validatedData.namedNew === undefined) {
|
|
528
|
-
validatedData.namedNew = fileData.namedNew;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
if (validatedData.root && typeof validatedData.root === 'object') {
|
|
532
|
-
const rootObj = validatedData.root;
|
|
533
|
-
if (rootObj.type === 'node' && rootObj.node) {
|
|
534
|
-
validatedData.root = rootObj.node;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
if (!validatedData.table || validatedData.table.length === 0) {
|
|
538
|
-
throw new Error("Guard 'table' field is required and cannot be empty");
|
|
539
|
-
}
|
|
540
|
-
if (!validatedData.root) {
|
|
541
|
-
throw new Error("Guard 'root' field is required");
|
|
542
|
-
}
|
|
543
|
-
const callGuard = new CallGuard(validatedData);
|
|
544
|
-
const result = await callGuard.call(env);
|
|
545
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
546
|
-
}
|
|
547
|
-
case "personal": {
|
|
548
|
-
const transformedData = transformPersonalInput(validated.data);
|
|
549
|
-
const callPersonal = new CallPersonal(transformedData);
|
|
550
|
-
const result = await callPersonal.call(env);
|
|
551
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
552
|
-
}
|
|
553
|
-
case "payment": {
|
|
554
|
-
const callPayment = new CallPayment(validated.data);
|
|
555
|
-
const result = await callPayment.call(env);
|
|
556
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
557
|
-
}
|
|
558
|
-
case "demand": {
|
|
559
|
-
const callDemand = new CallDemand(validated.data);
|
|
560
|
-
const result = validated.submission
|
|
561
|
-
? await callDemand.call_with_submission(env, await transformSubmission(validated.submission))
|
|
562
|
-
: await callDemand.call(env);
|
|
563
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
564
|
-
}
|
|
565
|
-
case "order": {
|
|
566
|
-
const callOrder = new CallOrder(validated.data);
|
|
567
|
-
const result = validated.submission
|
|
568
|
-
? await callOrder.call_with_submission(env, await transformSubmission(validated.submission))
|
|
569
|
-
: await callOrder.call(env);
|
|
570
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
571
|
-
}
|
|
572
|
-
case "gen_passport": {
|
|
573
|
-
const result = await gen_passport(env, validated.guard, validated.info);
|
|
574
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
575
|
-
}
|
|
576
|
-
case "proof": {
|
|
577
|
-
const callProof = new CallProof(validated.data);
|
|
578
|
-
const result = validated.submission
|
|
579
|
-
? await callProof.call_with_submission(env, await transformSubmission(validated.submission))
|
|
580
|
-
: await callProof.call(env);
|
|
581
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
582
|
-
}
|
|
583
|
-
case "gen_proof": {
|
|
584
|
-
const result = await gen_proof(env, validated.proof, validated.server_pubkey, validated.server_signature, validated.proof_type, validated.description, validated.item_count, validated.about_address);
|
|
585
|
-
return handleCallResult(result, buildCtx(validated.data));
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
throw new Error(`Unknown on-chain operation type: ${validated.operation_type}`);
|
|
589
|
-
}
|
|
590
|
-
catch (error) {
|
|
591
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
592
|
-
return handleCallResult({ error: errorMessage }, validated ? {
|
|
593
|
-
operation_type: validated.operation_type,
|
|
594
|
-
data: validated.data,
|
|
595
|
-
} : undefined);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
function wrapLocalHandler(config) {
|
|
599
|
-
const { schema, operationFn, parseLabel, buildContext } = config;
|
|
600
|
-
return async (args) => {
|
|
601
|
-
let validated;
|
|
602
|
-
try {
|
|
603
|
-
validated = strictParse(schema, args, parseLabel);
|
|
604
|
-
const result = await operationFn(validated);
|
|
605
|
-
const ctx = buildContext(validated);
|
|
606
|
-
return {
|
|
607
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
608
|
-
structuredContent: {
|
|
609
|
-
result: {
|
|
610
|
-
status: "success",
|
|
611
|
-
data: result,
|
|
612
|
-
},
|
|
613
|
-
semantic: buildDataSemantic(result, ctx),
|
|
614
|
-
},
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
catch (error) {
|
|
618
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
619
|
-
const ctx = validated ? buildContext(validated) : undefined;
|
|
620
|
-
const classified = classifyError(errorMessage);
|
|
621
|
-
const errorResult = {
|
|
622
|
-
status: "error",
|
|
623
|
-
error: errorMessage,
|
|
624
|
-
};
|
|
625
|
-
if (classified.error_code !== undefined)
|
|
626
|
-
errorResult.error_code = classified.error_code;
|
|
627
|
-
if (classified.retryable !== undefined)
|
|
628
|
-
errorResult.retryable = classified.retryable;
|
|
629
|
-
if (classified.recovery_hint !== undefined)
|
|
630
|
-
errorResult.recovery_hint = classified.recovery_hint;
|
|
631
|
-
return {
|
|
632
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
633
|
-
structuredContent: {
|
|
634
|
-
result: errorResult,
|
|
635
|
-
semantic: buildDataSemantic(undefined, ctx, true, errorMessage),
|
|
636
|
-
},
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
const handleAccountOperation = wrapLocalHandler({
|
|
642
|
-
schema: AccountOperationSchema,
|
|
643
|
-
operationFn: account_operation,
|
|
644
|
-
parseLabel: "account_operation input",
|
|
645
|
-
buildContext: (validated) => ({ operation_type: "account_" + validated.operation_type, data: validated }),
|
|
646
|
-
});
|
|
647
|
-
const handleMarkOperation = wrapLocalHandler({
|
|
648
|
-
schema: LocalMarkOperationSchema,
|
|
649
|
-
operationFn: local_mark_operation,
|
|
650
|
-
parseLabel: "local_mark_operation input",
|
|
651
|
-
buildContext: (validated) => ({ operation_type: "mark_" + validated.operation_type, data: validated }),
|
|
652
|
-
});
|
|
653
|
-
const handleInfoOperation = wrapLocalHandler({
|
|
654
|
-
schema: LocalInfoOperationSchema,
|
|
655
|
-
operationFn: local_info_operation,
|
|
656
|
-
parseLabel: "local_info_operation input",
|
|
657
|
-
buildContext: (validated) => ({ operation_type: "local_info", data: validated }),
|
|
658
|
-
});
|
|
659
|
-
async function handleWipOperations(args) {
|
|
660
|
-
const validated = strictParse(WipOperationsSchema, args, "wip_file input");
|
|
661
|
-
let structuredContent;
|
|
662
|
-
switch (validated.type) {
|
|
663
|
-
case "generate": {
|
|
664
|
-
const result = await generate_wip(validated.options, validated.outputPath);
|
|
665
|
-
structuredContent = { result: { type: "generate", filePath: result } };
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
case "verify": {
|
|
669
|
-
const result = await verify_wip(validated.wipFilePath, validated.hash_equal, validated.requireSignature);
|
|
670
|
-
structuredContent = { result: { type: "verify", ...result } };
|
|
671
|
-
break;
|
|
672
|
-
}
|
|
673
|
-
case "sign": {
|
|
674
|
-
const result = await sign_wip(validated.wipFilePath, validated.account, validated.outputPath);
|
|
675
|
-
structuredContent = { result: { type: "sign", filePath: result } };
|
|
676
|
-
break;
|
|
677
|
-
}
|
|
678
|
-
case "wip2html": {
|
|
679
|
-
const result = await wip2html(validated.wipPath, validated.options);
|
|
680
|
-
let output = { type: "wip2html" };
|
|
681
|
-
if (typeof result === "string") {
|
|
682
|
-
output.html = result;
|
|
683
|
-
}
|
|
684
|
-
else if (Array.isArray(result)) {
|
|
685
|
-
output.files = result;
|
|
686
|
-
}
|
|
687
|
-
else {
|
|
688
|
-
output.html = String(result);
|
|
689
|
-
}
|
|
690
|
-
structuredContent = { result: output };
|
|
691
|
-
break;
|
|
692
|
-
}
|
|
693
|
-
default:
|
|
694
|
-
throw new Error("Unknown WIP operation type");
|
|
695
|
-
}
|
|
696
|
-
return {
|
|
697
|
-
content: [{ type: "text", text: JSON.stringify(structuredContent) }],
|
|
698
|
-
structuredContent,
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
async function handleWatchQueryOperations(args) {
|
|
702
|
-
const validated = strictParse(WatchQueryOperationsSchema, args, "watch_and_query input");
|
|
703
|
-
let result;
|
|
704
|
-
switch (validated.query_type) {
|
|
705
|
-
case "local_mark_list": {
|
|
706
|
-
const queryResult = await query_local_mark_list(validated.filter || {});
|
|
707
|
-
result = { query_type: "local_mark_list", result: queryResult };
|
|
708
|
-
break;
|
|
709
|
-
}
|
|
710
|
-
case "account_list": {
|
|
711
|
-
const queryResult = await query_account_list(validated.filter);
|
|
712
|
-
result = { query_type: "account_list", result: queryResult };
|
|
713
|
-
break;
|
|
714
|
-
}
|
|
715
|
-
case "local_info_list": {
|
|
716
|
-
const queryResult = await query_local_info_list(validated.filter);
|
|
717
|
-
result = { query_type: "local_info_list", result: queryResult };
|
|
718
|
-
break;
|
|
719
|
-
}
|
|
720
|
-
case "token_list": {
|
|
721
|
-
const queryResult = await query_local_token_list(validated.filter || {});
|
|
722
|
-
result = { query_type: "token_list", result: queryResult };
|
|
723
|
-
break;
|
|
724
|
-
}
|
|
725
|
-
case "account_balance": {
|
|
726
|
-
const queryResult = await query_account({ name_or_address: validated.name_or_address, token_type: validated.token_type, balance: validated.balance, coin: validated.coin, network: validated.network });
|
|
727
|
-
result = { query_type: "account_balance", result: queryResult };
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
case "local_names": {
|
|
731
|
-
const queryResult = await GetLocalNamesByAddresses(validated.addresses);
|
|
732
|
-
result = { query_type: "local_names", result: queryResult };
|
|
733
|
-
break;
|
|
734
|
-
}
|
|
735
|
-
case "onchain_personal_profile": {
|
|
736
|
-
const queryResult = await query_personal({ account: validated.account, no_cache: validated.no_cache, network: validated.network });
|
|
737
|
-
result = { query_type: "onchain_personal_profile", result: queryResult };
|
|
738
|
-
break;
|
|
739
|
-
}
|
|
740
|
-
case "onchain_objects": {
|
|
741
|
-
const queryResult = await query_objects({ objects: validated.objects, no_cache: validated.no_cache, network: validated.network });
|
|
742
|
-
if (queryResult && queryResult.objects && Array.isArray(queryResult.objects)) {
|
|
743
|
-
queryResult.objects = queryResult.objects.map((obj) => {
|
|
744
|
-
if (obj && obj.data && obj.data.type === "Guard" && obj.data.root) {
|
|
745
|
-
try {
|
|
746
|
-
const nodeComments = generateNodeComments(obj.data.root);
|
|
747
|
-
return {
|
|
748
|
-
...obj,
|
|
749
|
-
_guard_node_comments: nodeComments
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
catch (e) {
|
|
753
|
-
return obj;
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
return obj;
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
result = { query_type: "onchain_objects", result: queryResult };
|
|
760
|
-
break;
|
|
761
|
-
}
|
|
762
|
-
case "onchain_received": {
|
|
763
|
-
const queryResult = await query_received({
|
|
764
|
-
name_or_address: normalizeAccountOrMark(validated.name_or_address),
|
|
765
|
-
type: validated.type,
|
|
766
|
-
cursor: validated.cursor,
|
|
767
|
-
limit: validated.limit,
|
|
768
|
-
no_cache: validated.no_cache,
|
|
769
|
-
network: validated.network
|
|
770
|
-
});
|
|
771
|
-
result = { query_type: "onchain_received", result: queryResult };
|
|
772
|
-
break;
|
|
773
|
-
}
|
|
774
|
-
default:
|
|
775
|
-
throw new Error(`Unknown query type. Valid query_types are: "local_mark_list", "account_list", "local_info_list", "token_list", "account_balance", "local_names", "onchain_personal_profile", "onchain_objects", "onchain_received". For table queries, use the "onchain_table_data" tool.`);
|
|
776
|
-
}
|
|
777
|
-
return {
|
|
778
|
-
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
779
|
-
structuredContent: {
|
|
780
|
-
result,
|
|
781
|
-
semantic: buildDataSemantic(result, {
|
|
782
|
-
operation_type: "query_toolkit",
|
|
783
|
-
data: validated,
|
|
784
|
-
}),
|
|
785
|
-
},
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
async function handleWowokInfo(args) {
|
|
789
|
-
const validated = strictParse(ProtocolInfoQuerySchema, args, "wowok_buildin_info input");
|
|
790
|
-
const queryResult = await queryProtocolInfo(validated);
|
|
791
|
-
return {
|
|
792
|
-
content: [{ type: "text", text: JSON.stringify({ result: queryResult }) }],
|
|
793
|
-
structuredContent: { result: queryResult },
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
async function handleOnchainEvents(args) {
|
|
797
|
-
const validated = strictParse(OnchainEventsInputSchema, args, "onchain_events input");
|
|
798
|
-
const queryResult = await query_events({
|
|
799
|
-
type: validated.type,
|
|
800
|
-
cursor: validated.cursor ? {
|
|
801
|
-
eventSeq: String(validated.cursor.eventSeq),
|
|
802
|
-
txDigest: validated.cursor.txDigest
|
|
803
|
-
} : null,
|
|
804
|
-
limit: validated.limit ?? null,
|
|
805
|
-
order: validated.order ?? null,
|
|
806
|
-
no_cache: validated.no_cache,
|
|
807
|
-
network: validated.network,
|
|
808
|
-
});
|
|
809
|
-
return {
|
|
810
|
-
content: [{ type: "text", text: JSON.stringify({ result: queryResult }) }],
|
|
811
|
-
structuredContent: {
|
|
812
|
-
result: queryResult,
|
|
813
|
-
semantic: buildDataSemantic(queryResult, {
|
|
814
|
-
operation_type: "onchain_events",
|
|
815
|
-
data: validated,
|
|
816
|
-
}),
|
|
817
|
-
},
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
async function handleProjectOperation(args) {
|
|
821
|
-
const action = args.action;
|
|
822
|
-
const project = args.project;
|
|
823
|
-
const object = args.object;
|
|
824
|
-
let result;
|
|
825
|
-
switch (action) {
|
|
826
|
-
case "list_projects":
|
|
827
|
-
result = await queryProjects();
|
|
828
|
-
break;
|
|
829
|
-
case "list_objects":
|
|
830
|
-
if (!project)
|
|
831
|
-
throw new Error("'project' param is required for list_objects");
|
|
832
|
-
result = await queryProjectObjects(project);
|
|
833
|
-
break;
|
|
834
|
-
case "shareable":
|
|
835
|
-
result = await queryShareableObjects();
|
|
836
|
-
break;
|
|
837
|
-
case "dependencies":
|
|
838
|
-
if (!object)
|
|
839
|
-
throw new Error("'object' param is required for dependencies");
|
|
840
|
-
result = queryDependencies(object);
|
|
841
|
-
break;
|
|
842
|
-
case "referenced_by":
|
|
843
|
-
if (!object)
|
|
844
|
-
throw new Error("'object' param is required for referenced_by");
|
|
845
|
-
result = queryReferencedBy(object);
|
|
846
|
-
break;
|
|
847
|
-
case "pre_publish_check":
|
|
848
|
-
if (!object)
|
|
849
|
-
throw new Error("'object' param is required for pre_publish_check");
|
|
850
|
-
result = { warnings: queryPrePublishCheck(object) };
|
|
851
|
-
break;
|
|
852
|
-
case "cross_project_refs":
|
|
853
|
-
result = queryCrossProjectReferences();
|
|
854
|
-
break;
|
|
855
|
-
case "graph_stats":
|
|
856
|
-
result = queryGraphStats();
|
|
857
|
-
break;
|
|
858
|
-
case "save_graph":
|
|
859
|
-
result = { saved: true, path: saveGraph() };
|
|
860
|
-
break;
|
|
861
|
-
case "load_graph":
|
|
862
|
-
result = { loaded: loadGraph() };
|
|
863
|
-
break;
|
|
864
|
-
default:
|
|
865
|
-
throw new Error(`Unknown project_operation action: ${action}`);
|
|
866
|
-
}
|
|
867
|
-
return {
|
|
868
|
-
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
869
|
-
structuredContent: { result },
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
async function handleConfigOperation(args) {
|
|
873
|
-
const action = args.action;
|
|
874
|
-
let result;
|
|
875
|
-
switch (action) {
|
|
876
|
-
case "list":
|
|
877
|
-
result = { services: listServices() };
|
|
878
|
-
break;
|
|
879
|
-
case "toggle": {
|
|
880
|
-
const service = args.service;
|
|
881
|
-
if (!service)
|
|
882
|
-
throw new Error("'service' param is required for toggle");
|
|
883
|
-
const existing = getServiceInfo(service);
|
|
884
|
-
if (!existing) {
|
|
885
|
-
throw new Error(`Unknown service: ${service}. Use action='list' to see all valid services.`);
|
|
886
|
-
}
|
|
887
|
-
const newState = toggleService(service);
|
|
888
|
-
result = { service, enabled: newState, reminder: existing.reminder };
|
|
889
|
-
break;
|
|
890
|
-
}
|
|
891
|
-
case "enable": {
|
|
892
|
-
const service = args.service;
|
|
893
|
-
if (!service)
|
|
894
|
-
throw new Error("'service' param is required for enable");
|
|
895
|
-
const existing = getServiceInfo(service);
|
|
896
|
-
if (!existing)
|
|
897
|
-
throw new Error(`Unknown service: ${service}. Use action='list' to see all valid services.`);
|
|
898
|
-
setServiceEnabled(service, true);
|
|
899
|
-
result = { service, enabled: true, reminder: existing.reminder };
|
|
900
|
-
break;
|
|
901
|
-
}
|
|
902
|
-
case "disable": {
|
|
903
|
-
const service = args.service;
|
|
904
|
-
if (!service)
|
|
905
|
-
throw new Error("'service' param is required for disable");
|
|
906
|
-
const existing = getServiceInfo(service);
|
|
907
|
-
if (!existing)
|
|
908
|
-
throw new Error(`Unknown service: ${service}. Use action='list' to see all valid services.`);
|
|
909
|
-
setServiceEnabled(service, false);
|
|
910
|
-
result = { service, enabled: false, reminder: existing.reminder };
|
|
911
|
-
break;
|
|
912
|
-
}
|
|
913
|
-
case "reset": {
|
|
914
|
-
const service = args.service;
|
|
915
|
-
if (!service)
|
|
916
|
-
throw new Error("'service' param is required for reset");
|
|
917
|
-
const existing = getServiceInfo(service);
|
|
918
|
-
if (!existing)
|
|
919
|
-
throw new Error(`Unknown service: ${service}. Use action='list' to see all valid services.`);
|
|
920
|
-
resetService(service);
|
|
921
|
-
result = { service, enabled: getServiceInfo(service)?.enabled, reminder: existing.reminder, reset: true };
|
|
922
|
-
break;
|
|
923
|
-
}
|
|
924
|
-
case "info": {
|
|
925
|
-
const service = args.service;
|
|
926
|
-
if (!service)
|
|
927
|
-
throw new Error("'service' param is required for info");
|
|
928
|
-
const info = getServiceInfo(service);
|
|
929
|
-
if (!info)
|
|
930
|
-
throw new Error(`Unknown service: ${service}. Use action='list' to see all valid services.`);
|
|
931
|
-
result = info;
|
|
932
|
-
break;
|
|
933
|
-
}
|
|
934
|
-
default:
|
|
935
|
-
throw new Error(`Unknown config_operation action: ${action}`);
|
|
936
|
-
}
|
|
937
|
-
return {
|
|
938
|
-
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
939
|
-
structuredContent: { result },
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
function extractTrustMetrics(serviceObj) {
|
|
943
|
-
const data = serviceObj?.data ?? serviceObj ?? {};
|
|
944
|
-
const sales = Array.isArray(data.sales) ? data.sales : [];
|
|
945
|
-
const activeSales = sales.filter((s) => s && !s.suspension);
|
|
946
|
-
const compensationFund = data.compensation_fund;
|
|
947
|
-
const compBalance = (() => {
|
|
948
|
-
if (compensationFund === null || compensationFund === undefined)
|
|
949
|
-
return undefined;
|
|
950
|
-
if (typeof compensationFund === "bigint")
|
|
951
|
-
return compensationFund;
|
|
952
|
-
if (typeof compensationFund === "number")
|
|
953
|
-
return BigInt(compensationFund);
|
|
954
|
-
if (typeof compensationFund === "string") {
|
|
955
|
-
try {
|
|
956
|
-
return BigInt(compensationFund);
|
|
957
|
-
}
|
|
958
|
-
catch {
|
|
959
|
-
return undefined;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
if (typeof compensationFund === "object") {
|
|
963
|
-
const bal = compensationFund.balance;
|
|
964
|
-
if (bal === null || bal === undefined)
|
|
965
|
-
return undefined;
|
|
966
|
-
try {
|
|
967
|
-
return BigInt(bal);
|
|
968
|
-
}
|
|
969
|
-
catch {
|
|
970
|
-
return undefined;
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
return undefined;
|
|
974
|
-
})();
|
|
975
|
-
return {
|
|
976
|
-
arbitrationCases: Array.isArray(data.arbitrations) ? data.arbitrations.length : undefined,
|
|
977
|
-
compensationFundBalance: compBalance,
|
|
978
|
-
hasMachineBound: typeof data.machine === "string" && data.machine.length > 0,
|
|
979
|
-
hasBuyGuard: typeof data.buy_guard === "string" && data.buy_guard.length > 0,
|
|
980
|
-
};
|
|
981
|
-
}
|
|
982
|
-
function buildPuzzleRawData(serviceObj, orderAmount, trustScore, serviceOwner) {
|
|
983
|
-
const data = serviceObj?.data ?? serviceObj ?? {};
|
|
984
|
-
const sales = Array.isArray(data.sales) ? data.sales : [];
|
|
985
|
-
const order_allocators = data.order_allocators
|
|
986
|
-
? Array.isArray(data.order_allocators.allocators)
|
|
987
|
-
? data.order_allocators
|
|
988
|
-
: { allocators: data.order_allocators }
|
|
989
|
-
: undefined;
|
|
990
|
-
const serviceRaw = {
|
|
991
|
-
name: data.name ?? serviceObj?.id,
|
|
992
|
-
bPublished: data.bPublished,
|
|
993
|
-
bPaused: data.bPaused,
|
|
994
|
-
price: sales[0]?.price != null ? String(sales[0].price) : "0",
|
|
995
|
-
priceRaw: sales[0]?.price != null ? BigInt(sales[0].price) : 0n,
|
|
996
|
-
token_type: sales[0]?.price_type ?? (compensation_fund_token(data) ?? "0x2::wow::WOW"),
|
|
997
|
-
sales,
|
|
998
|
-
machine: data.machine ?? undefined,
|
|
999
|
-
buy_guard: data.buy_guard ?? undefined,
|
|
1000
|
-
customer_required: data.customer_required,
|
|
1001
|
-
arbitrations: data.arbitrations,
|
|
1002
|
-
compensation_fund: data.compensation_fund
|
|
1003
|
-
? { balance: extractBalance(data.compensation_fund) }
|
|
1004
|
-
: undefined,
|
|
1005
|
-
compensation_lock_duration: typeof data.setting_lock_duration === "number"
|
|
1006
|
-
? data.setting_lock_duration
|
|
1007
|
-
: undefined,
|
|
1008
|
-
um: data.um ?? undefined,
|
|
1009
|
-
order_allocators: order_allocators ? [order_allocators] : undefined,
|
|
1010
|
-
};
|
|
1011
|
-
return {
|
|
1012
|
-
service: serviceRaw,
|
|
1013
|
-
order_amount: orderAmount,
|
|
1014
|
-
trust_score: trustScore,
|
|
1015
|
-
service_owner: serviceOwner,
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
function compensation_fund_token(data) {
|
|
1019
|
-
if (data?.compensation_fund && typeof data.compensation_fund === "object") {
|
|
1020
|
-
return data.compensation_fund.token_type;
|
|
1021
|
-
}
|
|
1022
|
-
return undefined;
|
|
1023
|
-
}
|
|
1024
|
-
function extractBalance(b) {
|
|
1025
|
-
if (b === null || b === undefined)
|
|
1026
|
-
return 0n;
|
|
1027
|
-
if (typeof b === "bigint")
|
|
1028
|
-
return b;
|
|
1029
|
-
if (typeof b === "number")
|
|
1030
|
-
return BigInt(b);
|
|
1031
|
-
if (typeof b === "string") {
|
|
1032
|
-
try {
|
|
1033
|
-
return BigInt(b);
|
|
1034
|
-
}
|
|
1035
|
-
catch {
|
|
1036
|
-
return 0n;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
if (typeof b === "object") {
|
|
1040
|
-
const bal = b.balance;
|
|
1041
|
-
if (bal === null || bal === undefined)
|
|
1042
|
-
return 0n;
|
|
1043
|
-
try {
|
|
1044
|
-
return BigInt(bal);
|
|
1045
|
-
}
|
|
1046
|
-
catch {
|
|
1047
|
-
return 0n;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
return 0n;
|
|
1051
|
-
}
|
|
1052
|
-
async function handleTrustScore(args) {
|
|
1053
|
-
const validated = strictParse(TrustScoreInputSchema, args, "trust_score input");
|
|
1054
|
-
const depth = (validated.depth ?? "evaluate");
|
|
1055
|
-
const queryResult = await query_objects({
|
|
1056
|
-
objects: [validated.service],
|
|
1057
|
-
no_cache: validated.no_cache,
|
|
1058
|
-
network: validated.network,
|
|
1059
|
-
});
|
|
1060
|
-
const objects = queryResult?.objects;
|
|
1061
|
-
if (!objects || !Array.isArray(objects) || objects.length === 0) {
|
|
1062
|
-
throw new Error(`Service object not found for '${validated.service}'. ` +
|
|
1063
|
-
`Verify the ID/name and network, or use query_toolkit with query_type='onchain_objects' to debug.`);
|
|
1064
|
-
}
|
|
1065
|
-
const serviceObj = objects[0];
|
|
1066
|
-
const objType = serviceObj?.data?.object_type ?? serviceObj?.object_type ?? serviceObj?.type;
|
|
1067
|
-
if (objType && typeof objType === "string" && !objType.includes("Service")) {
|
|
1068
|
-
throw new Error(`Object '${validated.service}' is not a Service (type: ${objType}). ` +
|
|
1069
|
-
`trust_score only evaluates Service objects.`);
|
|
1070
|
-
}
|
|
1071
|
-
const metrics = extractTrustMetrics(serviceObj);
|
|
1072
|
-
const trustScore = computeServiceTrustScore(metrics);
|
|
1073
|
-
const sales = Array.isArray(serviceObj?.data?.sales) ? serviceObj.data.sales : [];
|
|
1074
|
-
const activeSale = sales.find((s) => s && !s.suspension) ?? sales[0];
|
|
1075
|
-
const salePriceRaw = activeSale?.price != null ? BigInt(activeSale.price) : 0n;
|
|
1076
|
-
const orderAmount = validated.order_amount != null
|
|
1077
|
-
? BigInt(validated.order_amount)
|
|
1078
|
-
: salePriceRaw;
|
|
1079
|
-
let riskScore = undefined;
|
|
1080
|
-
let infoPuzzle = undefined;
|
|
1081
|
-
if (depth === "evaluate" || depth === "preorder") {
|
|
1082
|
-
const puzzleRaw = buildPuzzleRawData(serviceObj, orderAmount, { score: trustScore.score, level: trustScore.level }, undefined);
|
|
1083
|
-
infoPuzzle = assembleInfoPuzzle(validated.service, puzzleRaw, depth);
|
|
1084
|
-
riskScore = assessRisk(infoPuzzle);
|
|
1085
|
-
}
|
|
1086
|
-
const result = {
|
|
1087
|
-
service_id: validated.service,
|
|
1088
|
-
service_name: serviceObj?.data?.name ?? serviceObj?.name ?? validated.service,
|
|
1089
|
-
service_basics: {
|
|
1090
|
-
bPublished: serviceObj?.data?.bPublished ?? false,
|
|
1091
|
-
bPaused: serviceObj?.data?.bPaused ?? false,
|
|
1092
|
-
sales_count: sales.filter((s) => s && !s.suspension).length,
|
|
1093
|
-
has_machine: !!serviceObj?.data?.machine,
|
|
1094
|
-
has_buy_guard: !!serviceObj?.data?.buy_guard,
|
|
1095
|
-
has_um_contact: !!serviceObj?.data?.um,
|
|
1096
|
-
arbitrations_count: Array.isArray(serviceObj?.data?.arbitrations)
|
|
1097
|
-
? serviceObj.data.arbitrations.length
|
|
1098
|
-
: 0,
|
|
1099
|
-
},
|
|
1100
|
-
trust_score: {
|
|
1101
|
-
score: trustScore.score,
|
|
1102
|
-
level: trustScore.level,
|
|
1103
|
-
summary: trustScore.summary,
|
|
1104
|
-
warnings: trustScore.warnings,
|
|
1105
|
-
breakdown: trustScore.breakdown,
|
|
1106
|
-
},
|
|
1107
|
-
order_amount: orderAmount.toString(),
|
|
1108
|
-
depth,
|
|
1109
|
-
...(riskScore ? {
|
|
1110
|
-
risk_score: {
|
|
1111
|
-
total: riskScore.total,
|
|
1112
|
-
level: riskScore.level,
|
|
1113
|
-
red_flags: riskScore.red_flags,
|
|
1114
|
-
advice: riskScore.advice,
|
|
1115
|
-
dimensions: riskScore.dimensions,
|
|
1116
|
-
},
|
|
1117
|
-
} : {}),
|
|
1118
|
-
...(infoPuzzle ? {
|
|
1119
|
-
info_puzzle: {
|
|
1120
|
-
completeness: infoPuzzle.completeness,
|
|
1121
|
-
gaps: infoPuzzle.gaps,
|
|
1122
|
-
assembled_at: infoPuzzle.assembled_at,
|
|
1123
|
-
},
|
|
1124
|
-
} : {}),
|
|
1125
|
-
};
|
|
1126
|
-
return {
|
|
1127
|
-
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
1128
|
-
structuredContent: { result },
|
|
1129
|
-
};
|
|
1130
|
-
}
|
|
1131
|
-
function normalizeAccountOrMark(input) {
|
|
1132
|
-
if (typeof input === 'string') {
|
|
1133
|
-
return { name_or_address: input, local_mark_first: true };
|
|
1134
|
-
}
|
|
1135
|
-
return input;
|
|
1136
|
-
}
|
|
1137
|
-
function normalizeManyAccountOrMark(input) {
|
|
1138
|
-
if (Array.isArray(input)) {
|
|
1139
|
-
return {
|
|
1140
|
-
entities: input.map(item => typeof item === 'string' ? { name_or_address: item, local_mark_first: true } : item),
|
|
1141
|
-
check_all_founded: true
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
return input;
|
|
1145
|
-
}
|
|
1146
|
-
async function handleMessengerOperation(args) {
|
|
1147
|
-
let validated;
|
|
1148
|
-
try {
|
|
1149
|
-
validated = strictParse(MessengerOperationInputSchema, args, "messenger_operation input");
|
|
1150
|
-
let result;
|
|
1151
|
-
switch (validated.operation) {
|
|
1152
|
-
case "watch_conversations": {
|
|
1153
|
-
const conversations = await watch_conversations(validated.filter);
|
|
1154
|
-
result = { operation: "watch_conversations", result: conversations };
|
|
1155
|
-
break;
|
|
1156
|
-
}
|
|
1157
|
-
case "send_message": {
|
|
1158
|
-
const sendResult = await send_message(validated.from, normalizeAccountOrMark(validated.to), validated.content, validated.options);
|
|
1159
|
-
const filteredResult = {
|
|
1160
|
-
...sendResult,
|
|
1161
|
-
merkleData: sendResult.merkleData ? {
|
|
1162
|
-
leafIndex: sendResult.merkleData.leafIndex,
|
|
1163
|
-
prevRoot: sendResult.merkleData.prevRoot,
|
|
1164
|
-
newRoot: sendResult.merkleData.newRoot,
|
|
1165
|
-
serverSignature: sendResult.merkleData.serverSignature,
|
|
1166
|
-
serverTimestamp: sendResult.merkleData.serverTimestamp,
|
|
1167
|
-
serverPublicKey: sendResult.merkleData.serverPublicKey,
|
|
1168
|
-
} : undefined,
|
|
1169
|
-
};
|
|
1170
|
-
result = { operation: "send_message", result: filteredResult };
|
|
1171
|
-
break;
|
|
1172
|
-
}
|
|
1173
|
-
case "send_file": {
|
|
1174
|
-
const sendResult = await send_file(validated.from, normalizeAccountOrMark(validated.to), validated.filePath, validated.options);
|
|
1175
|
-
const filteredResult = {
|
|
1176
|
-
...sendResult,
|
|
1177
|
-
merkleData: sendResult.merkleData ? {
|
|
1178
|
-
leafIndex: sendResult.merkleData.leafIndex,
|
|
1179
|
-
prevRoot: sendResult.merkleData.prevRoot,
|
|
1180
|
-
newRoot: sendResult.merkleData.newRoot,
|
|
1181
|
-
serverSignature: sendResult.merkleData.serverSignature,
|
|
1182
|
-
serverTimestamp: sendResult.merkleData.serverTimestamp,
|
|
1183
|
-
serverPublicKey: sendResult.merkleData.serverPublicKey,
|
|
1184
|
-
} : undefined,
|
|
1185
|
-
};
|
|
1186
|
-
result = { operation: "send_file", result: filteredResult };
|
|
1187
|
-
break;
|
|
1188
|
-
}
|
|
1189
|
-
case "watch_messages": {
|
|
1190
|
-
const filter = validated.filter ? {
|
|
1191
|
-
...validated.filter,
|
|
1192
|
-
peerAddress: validated.filter.peerAddress ? normalizeAccountOrMark(validated.filter.peerAddress) : undefined
|
|
1193
|
-
} : undefined;
|
|
1194
|
-
const messages = await watch_messages(filter);
|
|
1195
|
-
result = { operation: "watch_messages", result: messages };
|
|
1196
|
-
break;
|
|
1197
|
-
}
|
|
1198
|
-
case "extract_zip_messages": {
|
|
1199
|
-
const extractedPaths = await extract_zip_messages(validated.account, validated.messages, validated.outputDir);
|
|
1200
|
-
result = { operation: "extract_zip_messages", result: extractedPaths };
|
|
1201
|
-
break;
|
|
1202
|
-
}
|
|
1203
|
-
case "generate_wts": {
|
|
1204
|
-
const params = validated.params ? {
|
|
1205
|
-
...validated.params,
|
|
1206
|
-
peerAccount: normalizeAccountOrMark(validated.params.peerAccount)
|
|
1207
|
-
} : undefined;
|
|
1208
|
-
const wtsResult = await generate_wts(params);
|
|
1209
|
-
result = { operation: "generate_wts", result: wtsResult };
|
|
1210
|
-
break;
|
|
1211
|
-
}
|
|
1212
|
-
case "verify_wts": {
|
|
1213
|
-
const verifyResult = await verify_wts(validated.wtsFilePath);
|
|
1214
|
-
result = { operation: "verify_wts", result: verifyResult };
|
|
1215
|
-
break;
|
|
1216
|
-
}
|
|
1217
|
-
case "sign_wts": {
|
|
1218
|
-
const signedPath = await sign_wts(validated.wtsFilePath, validated.account, validated.outputPath);
|
|
1219
|
-
result = { operation: "sign_wts", result: signedPath };
|
|
1220
|
-
break;
|
|
1221
|
-
}
|
|
1222
|
-
case "wts2html": {
|
|
1223
|
-
const htmlResult = await wts2html(validated.wtsPath, validated.options);
|
|
1224
|
-
result = { operation: "wts2html", result: htmlResult };
|
|
1225
|
-
break;
|
|
1226
|
-
}
|
|
1227
|
-
case "proof_message": {
|
|
1228
|
-
const proofResult = await proof_message(validated.account, validated.messageId, validated.network);
|
|
1229
|
-
result = { operation: "proof_message", result: proofResult };
|
|
1230
|
-
break;
|
|
1231
|
-
}
|
|
1232
|
-
case "blacklist": {
|
|
1233
|
-
const blacklistParams = {
|
|
1234
|
-
account: validated.account,
|
|
1235
|
-
op: validated.blacklist.op
|
|
1236
|
-
};
|
|
1237
|
-
if ('users' in validated.blacklist) {
|
|
1238
|
-
blacklistParams.users = normalizeManyAccountOrMark(validated.blacklist.users);
|
|
1239
|
-
}
|
|
1240
|
-
const blacklistResult = await blacklist(blacklistParams);
|
|
1241
|
-
result = { operation: "blacklist", op: validated.blacklist.op, result: blacklistResult.result };
|
|
1242
|
-
break;
|
|
1243
|
-
}
|
|
1244
|
-
case "friendslist": {
|
|
1245
|
-
const friendslistParams = {
|
|
1246
|
-
account: validated.account,
|
|
1247
|
-
op: validated.friendslist.op
|
|
1248
|
-
};
|
|
1249
|
-
if ('users' in validated.friendslist) {
|
|
1250
|
-
friendslistParams.users = normalizeManyAccountOrMark(validated.friendslist.users);
|
|
1251
|
-
}
|
|
1252
|
-
const friendslistResult = await friendslist(friendslistParams);
|
|
1253
|
-
result = { operation: "friendslist", op: validated.friendslist.op, result: friendslistResult.result };
|
|
1254
|
-
break;
|
|
1255
|
-
}
|
|
1256
|
-
case "guardlist": {
|
|
1257
|
-
const guardlistResult = await guardlist({
|
|
1258
|
-
account: validated.account,
|
|
1259
|
-
...validated.guardlist
|
|
1260
|
-
});
|
|
1261
|
-
result = { operation: "guardlist", op: validated.guardlist.op, result: guardlistResult.result };
|
|
1262
|
-
break;
|
|
1263
|
-
}
|
|
1264
|
-
case "settings": {
|
|
1265
|
-
const settingsResult = await settings({
|
|
1266
|
-
account: validated.account,
|
|
1267
|
-
...validated.settings
|
|
1268
|
-
});
|
|
1269
|
-
result = { operation: "settings", op: validated.settings.op, result: settingsResult.result };
|
|
1270
|
-
break;
|
|
1271
|
-
}
|
|
1272
|
-
case "mark_messages_as_viewed": {
|
|
1273
|
-
const markedCount = await mark_messages_as_viewed(validated.messageIds, validated.account);
|
|
1274
|
-
result = { operation: "mark_messages_as_viewed", result: markedCount };
|
|
1275
|
-
break;
|
|
1276
|
-
}
|
|
1277
|
-
case "mark_conversation_as_viewed": {
|
|
1278
|
-
const markedCount = await mark_conversation_as_viewed(normalizeAccountOrMark(validated.peerAddress), validated.account);
|
|
1279
|
-
result = { operation: "mark_conversation_as_viewed", result: markedCount };
|
|
1280
|
-
break;
|
|
1281
|
-
}
|
|
1282
|
-
case "pull_messages": {
|
|
1283
|
-
const messages = await pull_messages(validated.account, validated.limit);
|
|
1284
|
-
result = { operation: "pull_messages", result: messages };
|
|
1285
|
-
break;
|
|
1286
|
-
}
|
|
1287
|
-
default:
|
|
1288
|
-
throw new Error(`Unknown messenger operation: ${validated.operation}`);
|
|
1289
|
-
}
|
|
1290
|
-
return {
|
|
1291
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
1292
|
-
structuredContent: { result },
|
|
1293
|
-
};
|
|
1294
|
-
}
|
|
1295
|
-
catch (error) {
|
|
1296
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1297
|
-
const ctx = validated ? { operation_type: "messenger_" + validated.operation, data: validated } : undefined;
|
|
1298
|
-
const classified = classifyError(errorMessage);
|
|
1299
|
-
const errorResult = { operation: "error", error: errorMessage };
|
|
1300
|
-
if (classified.error_code !== undefined)
|
|
1301
|
-
errorResult.error_code = classified.error_code;
|
|
1302
|
-
if (classified.retryable !== undefined)
|
|
1303
|
-
errorResult.retryable = classified.retryable;
|
|
1304
|
-
if (classified.recovery_hint !== undefined)
|
|
1305
|
-
errorResult.recovery_hint = classified.recovery_hint;
|
|
1306
|
-
return {
|
|
1307
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
1308
|
-
structuredContent: {
|
|
1309
|
-
result: errorResult,
|
|
1310
|
-
semantic: buildDataSemantic(undefined, ctx, true, errorMessage),
|
|
1311
|
-
},
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
async function handleGuard2File(args) {
|
|
1316
|
-
const validated = strictParse(Guard2File_InputSchema, args, "guard2file input");
|
|
1317
|
-
const env = getEnvConfig(validated.env);
|
|
1318
|
-
try {
|
|
1319
|
-
await guard2file(validated.guard, validated.file_path, validated.format || "json", env.network);
|
|
1320
|
-
const result = {
|
|
1321
|
-
result: {
|
|
1322
|
-
status: "success",
|
|
1323
|
-
data: {
|
|
1324
|
-
file_path: resolve(validated.file_path),
|
|
1325
|
-
format: validated.format || "json",
|
|
1326
|
-
guard_object: validated.guard,
|
|
1327
|
-
},
|
|
1328
|
-
},
|
|
1329
|
-
};
|
|
1330
|
-
return {
|
|
1331
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
1332
|
-
structuredContent: result,
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
catch (error) {
|
|
1336
|
-
const result = {
|
|
1337
|
-
result: {
|
|
1338
|
-
status: "error",
|
|
1339
|
-
error: error.message,
|
|
1340
|
-
},
|
|
1341
|
-
};
|
|
1342
|
-
return {
|
|
1343
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
1344
|
-
structuredContent: result,
|
|
1345
|
-
};
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
async function handleMachineNode2File(args) {
|
|
1349
|
-
const validated = strictParse(MachineNode2File_InputSchema, args, "machineNode2file input");
|
|
1350
|
-
const env = getEnvConfig(validated.env);
|
|
1351
|
-
try {
|
|
1352
|
-
await machineNode2file(validated.machine, validated.file_path, validated.format || "json", env.network);
|
|
1353
|
-
let node_count = undefined;
|
|
1354
|
-
try {
|
|
1355
|
-
const filePath = resolve(validated.file_path);
|
|
1356
|
-
const fileContent = await import('fs/promises').then(fs => fs.readFile(filePath, 'utf-8'));
|
|
1357
|
-
if ((validated.format || "json") === "json") {
|
|
1358
|
-
const parsed = JSON.parse(fileContent);
|
|
1359
|
-
if (Array.isArray(parsed)) {
|
|
1360
|
-
node_count = parsed.length;
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
else {
|
|
1364
|
-
const nodeMatches = fileContent.match(/^##\s+Node:/gm);
|
|
1365
|
-
node_count = nodeMatches ? nodeMatches.length : 0;
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
catch {
|
|
1369
|
-
node_count = undefined;
|
|
1370
|
-
}
|
|
1371
|
-
const result = {
|
|
1372
|
-
result: {
|
|
1373
|
-
status: "success",
|
|
1374
|
-
data: {
|
|
1375
|
-
file_path: resolve(validated.file_path),
|
|
1376
|
-
format: validated.format || "json",
|
|
1377
|
-
machine_object: validated.machine,
|
|
1378
|
-
},
|
|
1379
|
-
},
|
|
1380
|
-
};
|
|
1381
|
-
if (node_count !== undefined) {
|
|
1382
|
-
result.result.data.node_count = node_count;
|
|
1383
|
-
}
|
|
1384
|
-
return {
|
|
1385
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
1386
|
-
structuredContent: result,
|
|
1387
|
-
};
|
|
1388
|
-
}
|
|
1389
|
-
catch (error) {
|
|
1390
|
-
const result = {
|
|
1391
|
-
result: {
|
|
1392
|
-
status: "error",
|
|
1393
|
-
error: error.message,
|
|
1394
|
-
},
|
|
1395
|
-
};
|
|
1396
|
-
return {
|
|
1397
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
1398
|
-
structuredContent: result,
|
|
1399
|
-
};
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
export { OnchainOperationsSchema, WipOperationsSchema, WatchQueryOperationsSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, ProtocolInfoQuerySchema, CallOutputSchema, MessengerOperationInputSchema, MessengerOperationOutputSchema };
|
|
124
|
+
export { OnchainOperationsSchema, WipOperationsSchema, WatchQueryOperationsSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, ProtocolInfoQuerySchema, CallOutputSchema, MessengerOperationInputSchema, MessengerOperationOutputSchema, };
|
|
1403
125
|
async function main() {
|
|
1404
126
|
if (areSchemasAvailable()) {
|
|
1405
127
|
const index = getSchemaIndex();
|
|
@@ -1420,342 +142,7 @@ async function main() {
|
|
|
1420
142
|
}
|
|
1421
143
|
const activeServices = listServices().filter((s) => s.enabled).map((s) => s.name);
|
|
1422
144
|
console.error(`Phase 2 active services: ${activeServices.join(", ") || "none"}`);
|
|
1423
|
-
|
|
1424
|
-
title: "⛓️ On-chain Operations",
|
|
1425
|
-
description: "On-chain operations for WoWok object: service (marketplace listings), machine (workflow templates), progress (order tracking), repository (on-chain database), arbitration (dispute resolution), contact (IM management), treasury (team funds), reward (incentive pools), allocation (auto-distribution), permission (access control), guard (programmable trust rules), personal (public profile), payment (direct coin transfers), demand (service requests), order (order management), gen_passport (verified credentials), proof (on-chain proof objects), gen_proof (generate proof shortcut).\n\n💡 Schema hint: Use schema_query with action='get' and name='onchain_operations' to retrieve the complete parameter schema. For individual operation schemas (e.g., 'onchain_operations_permission'), use schema_query with action='list_operations' to see all available operation schemas.",
|
|
1426
|
-
inputSchema: OnchainOperationsSchema,
|
|
1427
|
-
outputSchema: CallOutputSchema,
|
|
1428
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
1429
|
-
_meta: createToolMeta("operation", ["service", "machine", "progress", "repository", "arbitration", "contact", "treasury", "reward", "allocation", "permission", "guard", "personal", "payment", "demand", "order", "gen_passport", "proof", "gen_proof", "on-chain", "blockchain"]),
|
|
1430
|
-
}, handleOnchainOperations);
|
|
1431
|
-
reg("account_operation", {
|
|
1432
|
-
title: "🔒 LOCAL ONLY: Account - Wallet Management",
|
|
1433
|
-
description: "🔒 100% LOCAL, NEVER ON-CHAIN 🔒 Manage WoWok accounts locally on device: generate, suspend, resume, faucet-test, operate assets, sign data, etc.\n\n💡 Schema hint: Use schema_query with action='get' and name='account_operation' to retrieve the exact parameter schema before calling.",
|
|
1434
|
-
inputSchema: AccountOperationSchema,
|
|
1435
|
-
outputSchema: AccountOperationOutputWrappedSchema,
|
|
1436
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1437
|
-
_meta: createToolMeta("operation", ["account", "local", "private", "wallet", "off-chain"]),
|
|
1438
|
-
}, handleAccountOperation, statusErrorShape);
|
|
1439
|
-
reg("local_mark_operation", {
|
|
1440
|
-
title: "🔒 LOCAL ONLY: LocalMark - Address Book Management",
|
|
1441
|
-
description: "100% LOCAL, NEVER ON-CHAIN 🔒 Manage ID names and tags stored ONLY on your local device for easy identification of user address or object IDs by name.\n\n💡 Schema hint: Use schema_query with action='get' and name='local_mark_operation' to retrieve the exact parameter schema before calling.",
|
|
1442
|
-
inputSchema: LocalMarkOperationSchema,
|
|
1443
|
-
outputSchema: LocalMarkOperationOutputWrappedSchema,
|
|
1444
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1445
|
-
_meta: createToolMeta("operation", ["mark", "local", "private", "address-book", "off-chain"]),
|
|
1446
|
-
}, handleMarkOperation, statusErrorShape);
|
|
1447
|
-
reg("local_info_operation", {
|
|
1448
|
-
title: "🔒 LOCAL ONLY: LocalInfo - Private Data Management",
|
|
1449
|
-
description: "100% LOCAL, NEVER ON-CHAIN 🔒 Manage sensitive personal information stored ONLY on your device: delivery addresses, phone numbers, contacts.\n\n💡 Schema hint: Use schema_query with action='get' and name='local_info_operation' to retrieve the exact parameter schema before calling.",
|
|
1450
|
-
inputSchema: LocalInfoOperationSchema,
|
|
1451
|
-
outputSchema: LocalInfoOperationOutputWrappedSchema,
|
|
1452
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1453
|
-
_meta: createToolMeta("operation", ["info", "local", "private", "data-management", "off-chain"]),
|
|
1454
|
-
}, handleInfoOperation, statusErrorShape);
|
|
1455
|
-
reg("wip_file", {
|
|
1456
|
-
title: "🤝 Witness Immutable Promise File Operations",
|
|
1457
|
-
description: "generate (create WIP files from markdown and images), verify (integrity check), sign (add signatures), or wip2html (convert to HTML).\n\n💡 Schema hint: Use schema_query with action='get' and name='wip_file' to retrieve the exact parameter schema before calling.",
|
|
1458
|
-
inputSchema: WipOperationsSchema,
|
|
1459
|
-
outputSchema: z.object({
|
|
1460
|
-
result: WipOperationOutputSchema,
|
|
1461
|
-
}),
|
|
1462
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
1463
|
-
_meta: createToolMeta("operation", ["wip", "promise", "file-generation", "verification", "signature", "local"]),
|
|
1464
|
-
}, handleWipOperations);
|
|
1465
|
-
reg("messenger_operation", {
|
|
1466
|
-
title: "💬 Messenger Operations",
|
|
1467
|
-
description: "WoWok encrypted messenger operations: watch conversations (with unread filtering, preview messages), send message, send file, watch messages (with viewed status filtering), extract zip messages, generate WTS, verify WTS, sign WTS, WTS to HTML, proof message on-chain, manage blacklist, friendslist, guardlist, settings, mark messages as viewed, mark conversation as viewed, and pull messages from server.\n\n💡 Schema hint: Use schema_query with action='get' and name='messenger_operation' to retrieve the exact parameter schema before calling.",
|
|
1468
|
-
inputSchema: MessengerOperationInputSchema,
|
|
1469
|
-
outputSchema: MessengerOperationOutputSchema,
|
|
1470
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
1471
|
-
_meta: createToolMeta("operation", ["messenger", "message", "file", "wts", "blacklist", "friendslist", "guardlist", "settings", "proof", "communication"]),
|
|
1472
|
-
}, handleMessengerOperation, operationErrorShape, 30000);
|
|
1473
|
-
reg("guard2file", {
|
|
1474
|
-
title: "📄 Guard to File - Export Guard Definition",
|
|
1475
|
-
description: "Export a Guard object's definition from the blockchain to a local JSON or Markdown file for editing and creating new Guard objects. Note: To query on-chain object information, use the 'query_toolkit' tool instead.\n\n💡 Schema hint: Use schema_query with action='get' and name='guard2file' to retrieve the exact parameter schema before calling.",
|
|
1476
|
-
inputSchema: Guard2File_InputSchema,
|
|
1477
|
-
outputSchema: Guard2File_OutputWrappedSchema,
|
|
1478
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1479
|
-
_meta: createToolMeta("generate file", ["guard", "export", "file", "json", "markdown", "on-chain"]),
|
|
1480
|
-
}, handleGuard2File, strictStatusErrorShape);
|
|
1481
|
-
reg("machineNode2file", {
|
|
1482
|
-
title: "⚙️ Machine Node to File - Export Machine Node Definition",
|
|
1483
|
-
description: "Export a Machine object's node definition from the blockchain to a local JSON or Markdown file for editing and creating new Machine objects. Note: To query on-chain object information, use the 'query_toolkit' tool instead.\n\n💡 Schema hint: Use schema_query with action='get' and name='machineNode2file' to retrieve the exact parameter schema before calling.",
|
|
1484
|
-
inputSchema: MachineNode2File_InputSchema,
|
|
1485
|
-
outputSchema: MachineNode2File_OutputWrappedSchema,
|
|
1486
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1487
|
-
_meta: createToolMeta("generate file", ["machine", "export", "file", "json", "markdown", "on-chain", "workflow"]),
|
|
1488
|
-
}, handleMachineNode2File, strictStatusErrorShape);
|
|
1489
|
-
reg("query_toolkit", {
|
|
1490
|
-
title: "🔍 Data Query Toolkit",
|
|
1491
|
-
description: "WOWOK data query toolkit — 9 query types covering local device data and on-chain blockchain data:\n\n"
|
|
1492
|
-
+ "LOCAL (device-only, never on-chain):\n"
|
|
1493
|
-
+ "1. local_mark_list — Query your LOCAL address book: maps human-readable names to blockchain addresses with optional tags. Use to resolve names→addresses or find addresses by tag.\n"
|
|
1494
|
-
+ "2. account_list — Query your LOCAL accounts (addresses, messenger status, suspension state). Use filter.includePubkey=true to also include public keys. Use to discover available accounts before operations.\n"
|
|
1495
|
-
+ "3. local_info_list — Query your LOCAL private info: sensitive data like delivery addresses, phone numbers, contacts stored ONLY on this device.\n"
|
|
1496
|
-
+ "4. token_list — Query cached token metadata: symbol, decimals, icon URL, description for tokens previously fetched from chain. Use to look up token precision/decimals before performing token operations. Returns: TokenTypeInfo[] (type, alias, name, symbol, decimals, iconUrl).\n"
|
|
1497
|
-
+ "5. account_balance — Query an account's coin balance OR paginated coin objects. Use balance=true for total amount, or coin={cursor,limit} to list individual coin objects. Supports multi-token via token_type parameter.\n"
|
|
1498
|
-
+ "6. local_names — Query local names by a list of addresses. For each address, returns the resolved account name (if exists) and local mark name (if exists). Returns: { account?, local_mark?, address }[].\n\n"
|
|
1499
|
-
+ "ONCHAIN (blockchain):\n"
|
|
1500
|
-
+ "7. onchain_personal_profile — Query any user's PUBLIC on-chain profile: social links, reputation (likes/dislikes), personal info records, voting history, referrer.\n"
|
|
1501
|
-
+ "8. onchain_objects — Batch query on-chain WOWOK objects by ID or name: supports Service, Machine, Order, Treasury, Reward, Arb, Personal, Contact, and more.\n"
|
|
1502
|
-
+ "9. onchain_received — Query objects (Payments, Tokens, NFTs) received by a specific object. Supports pagination and type filter.\n\n"
|
|
1503
|
-
+ "For dynamic table data queries (pagination, table items), use the 'onchain_table_data' tool.\n\n"
|
|
1504
|
-
+ "💡 Schema hint: Use schema_query with action='get' and name='query_toolkit' to retrieve the exact parameter schema with all query types and field definitions.",
|
|
1505
|
-
inputSchema: WatchQueryOperationsSchema,
|
|
1506
|
-
outputSchema: z.object({
|
|
1507
|
-
result: z.unknown().describe("Query result — type depends on query_type. Local queries return arrays (MarkData[], AccountData[], InfoData[], TokenTypeInfo[]). account_balance returns { address, balance? | coin? }. Onchain queries return typed objects or undefined. onchain_received returns ReceivedBalance | ReceivedNormal[]."),
|
|
1508
|
-
semantic: z.unknown().optional().describe("Business semantic summary for the query operation"),
|
|
1509
|
-
}),
|
|
1510
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1511
|
-
_meta: createToolMeta("query", ["watch", "query", "on-chain", "local", "events", "objects", "tokens", "balance", "profile"]),
|
|
1512
|
-
}, handleWatchQueryOperations);
|
|
1513
|
-
reg("onchain_table_data", {
|
|
1514
|
-
title: "📊 Watch WoWok On-chain Table Data Query",
|
|
1515
|
-
description: "Query dynamic table data of on-chain objects — supports paginated table queries and specific table item lookups. Each table item belongs to a parent object type and has a specific meaning:\n\n"
|
|
1516
|
-
+ "1. onchain_table — Paginated query of ANY object's dynamic fields table (Parent: any object). Returns all entries with keys, types, and object IDs. Use to explore all sub-items of an object.\n"
|
|
1517
|
-
+ "2. onchain_table_item_repository_data — Query a record from a Repository's on-chain key-value database (Parent: Repository). Key: name + entity (address or number). Returns the stored data record with typed value.\n"
|
|
1518
|
-
+ "3. onchain_table_item_permission_perm — Query a permission entry from a Permission object's access control table (Parent: Permission). Key: user address or Guard ID. Returns the permission list (perm[]) granted to that user/guard.\n"
|
|
1519
|
-
+ "4. onchain_table_item_entity_registrar — Query an entity's registration record from the GLOBAL EntityRegistrar (Parent: system EntityRegistrar). Key: user address. Returns registration info: description, referrer, records, mark_object.\n"
|
|
1520
|
-
+ "5. onchain_table_item_entity_linker — Query community votes/endorsements for an entity from the GLOBAL EntityLinker (Parent: system EntityLinker). Key: entity address. Returns vote records (likes/dislikes) showing community trust.\n"
|
|
1521
|
-
+ "6. onchain_table_item_reward_record — Query a reward claim record from a Reward object's distribution table (Parent: Reward). Key: recipient address. Returns claim history: guard used, total claimed, per-claim details.\n"
|
|
1522
|
-
+ "7. onchain_table_item_demand_presenter — Query a demand submission from a Demand object's presenter table (Parent: Demand). Key: presenter address. Returns submission details: recommendation, service, feedback, acceptance score.\n"
|
|
1523
|
-
+ "8. onchain_table_item_treasury_history — Query a payment record from a Treasury's history table (Parent: Treasury). Key: payment ID (address). Returns payment details: operation type, signer, amount, external guard.\n"
|
|
1524
|
-
+ "9. onchain_table_item_machine_node — Query a workflow node definition from a Machine object's node table (Parent: Machine). Key: node name (string). Returns node configuration: pairs, forwards, guards, thresholds.\n"
|
|
1525
|
-
+ "10. onchain_table_item_progress_history — Query a progress step record from a Progress object's history table (Parent: Progress). Key: sequence number (u64). Returns step details: node, next_node, session state, time.\n"
|
|
1526
|
-
+ "11. onchain_table_item_address_mark — Query a PUBLIC on-chain name/tag mark from an AddressMark object's table (Parent: AddressMark). Key: address. Returns public labels: entity, name, tags[]. Unlike local marks, these are published on-chain.\n"
|
|
1527
|
-
+ "12. onchain_table_item_generic — Query a generic table item from ANY object's dynamic fields (Parent: any object). Supports arbitrary key types (address, u64, string, object ID, etc.). Use for custom objects and general-purpose table lookups. Returns: ObjectBase | undefined.\n\n"
|
|
1528
|
-
+ "💡 Schema hint: Use schema_query with action='get' and name='onchain_table_data' to retrieve the exact parameter schema with all table item types and field definitions.",
|
|
1529
|
-
inputSchema: OnchainTableDataSchema,
|
|
1530
|
-
outputSchema: OnchainTableDataResultSchema,
|
|
1531
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1532
|
-
_meta: createToolMeta("table query", ["on-chain", "table", "dynamic fields", "pagination", "repository", "permission", "reward", "demand", "treasury", "machine", "progress"]),
|
|
1533
|
-
}, handleOnchainTableData);
|
|
1534
|
-
reg("onchain_events", {
|
|
1535
|
-
title: "📅 Watch WoWok On-chain Events",
|
|
1536
|
-
description: "Watch on-chain WoWok events by type. Supports arbitration events, new order events, progress events, demand presentation events, demand feedback events, and new entity registration events. Use pagination cursor for fetching large result sets.\n\n💡 Schema hint: Use schema_query with action='get' and name='onchain_events' to retrieve the exact parameter schema with all event types and field definitions.",
|
|
1537
|
-
inputSchema: OnchainEventsInputSchema,
|
|
1538
|
-
outputSchema: OnchainEventsResultSchema,
|
|
1539
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1540
|
-
_meta: createToolMeta("watch wowook events", ["events", "on-chain", "arbitration", "order", "progress", "demand", "entity"]),
|
|
1541
|
-
}, handleOnchainEvents);
|
|
1542
|
-
reg("wowok_buildin_info", {
|
|
1543
|
-
title: "ℹ️ WoWok Build-in Information",
|
|
1544
|
-
description: "Query WoWok protocol information: 'constants', 'built-in permissions', 'guard instructions', 'current network', 'value types', or 'mainnet bridge tokens'. For 'mainnet bridge tokens': returns cross-chain bridge tokens (ETH, WETH, WBTC, USDC, USDT) with each token's symbol, WOW-side type tag (wowTypeTag), EVM address, decimals, and description. The wowTypeTag (format {address}::{module}::{struct}) can be used directly as the `type_parameter` of Service / Treasury / Reward / Allocation objects to set their payment token — e.g. use USDT's wowTypeTag to create a Service that accepts USDT payments.",
|
|
1545
|
-
inputSchema: ProtocolInfoQuerySchema,
|
|
1546
|
-
outputSchema: ProtocolInfoResultSchema,
|
|
1547
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1548
|
-
_meta: createToolMeta("WoWok info", ["build-in", "constants", "permissions", "guard", "network", "value-types", "bridge-tokens"]),
|
|
1549
|
-
}, handleWowokInfo);
|
|
1550
|
-
reg("schema_query", {
|
|
1551
|
-
title: "📋 Schema Query",
|
|
1552
|
-
description: "Look up JSON Schemas for WoWok MCP tools and on-chain operations. " +
|
|
1553
|
-
"This is the authoritative reference for exact parameter structures, types, and required fields. " +
|
|
1554
|
-
"Always check the schema before calling an unfamiliar tool.\n\n" +
|
|
1555
|
-
"Actions:\n" +
|
|
1556
|
-
" 'list' - Show all available schemas (tools + on-chain operations). Start here to discover what exists.\n" +
|
|
1557
|
-
" 'get' - Fetch the full input JSON Schema by name (e.g. 'onchain_operations'). Use with the 'name' param.\n" +
|
|
1558
|
-
" 'get_output' - Fetch the output JSON Schema of a tool by name (e.g. 'onchain_operations'). Use with the 'name' param. Use this to understand a tool's return value structure.\n" +
|
|
1559
|
-
" 'search' - Find schemas by keyword, matching name/title/description. Use with the 'query' param.\n" +
|
|
1560
|
-
" 'list_operations' - Show only on-chain operation schemas (prefixed 'onchain_operations_'). Narrower than 'list'.",
|
|
1561
|
-
inputSchema: SchemaQueryInputSchema,
|
|
1562
|
-
outputSchema: SchemaQueryOutputSchema,
|
|
1563
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1564
|
-
_meta: createToolMeta("schema", ["schema", "json-schema", "types", "structure", "validation", "reference"]),
|
|
1565
|
-
}, async (args) => {
|
|
1566
|
-
const request = {
|
|
1567
|
-
action: args.action,
|
|
1568
|
-
name: args.name,
|
|
1569
|
-
query: args.query,
|
|
1570
|
-
};
|
|
1571
|
-
const response = processSchemaQuery(request);
|
|
1572
|
-
let textContent = response.message;
|
|
1573
|
-
const data = response.data;
|
|
1574
|
-
if (response.success && data) {
|
|
1575
|
-
switch (args.action) {
|
|
1576
|
-
case "list":
|
|
1577
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
1578
|
-
textContent += "\n\nAll available schemas:\n";
|
|
1579
|
-
for (const item of data) {
|
|
1580
|
-
textContent += `\n • ${item.name}`;
|
|
1581
|
-
if (item.title) {
|
|
1582
|
-
textContent += ` - ${item.title}`;
|
|
1583
|
-
}
|
|
1584
|
-
if (item.description) {
|
|
1585
|
-
textContent += `\n ${item.description.slice(0, 100)}...`;
|
|
1586
|
-
}
|
|
1587
|
-
textContent += "\n";
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
break;
|
|
1591
|
-
case "list_operations":
|
|
1592
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
1593
|
-
textContent += "\n\nOn-chain operation schemas:\n";
|
|
1594
|
-
for (const item of data) {
|
|
1595
|
-
textContent += `\n • ${item.name}`;
|
|
1596
|
-
if (item.title) {
|
|
1597
|
-
textContent += ` - ${item.title}`;
|
|
1598
|
-
}
|
|
1599
|
-
if (item.description) {
|
|
1600
|
-
textContent += `\n ${item.description.slice(0, 100)}...`;
|
|
1601
|
-
}
|
|
1602
|
-
textContent += "\n";
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
break;
|
|
1606
|
-
case "get":
|
|
1607
|
-
if (data) {
|
|
1608
|
-
textContent += "\n\n## JSON Schema\n\n";
|
|
1609
|
-
textContent += "```json\n";
|
|
1610
|
-
textContent += JSON.stringify(data, null, 2);
|
|
1611
|
-
textContent += "\n```\n";
|
|
1612
|
-
}
|
|
1613
|
-
break;
|
|
1614
|
-
case "get_output":
|
|
1615
|
-
if (data) {
|
|
1616
|
-
textContent += "\n\n## Output JSON Schema\n\n";
|
|
1617
|
-
textContent += "```json\n";
|
|
1618
|
-
textContent += JSON.stringify(data, null, 2);
|
|
1619
|
-
textContent += "\n```\n";
|
|
1620
|
-
}
|
|
1621
|
-
break;
|
|
1622
|
-
case "search":
|
|
1623
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
1624
|
-
textContent += `\n\nFound ${data.length} schemas matching '${args.query}':\n`;
|
|
1625
|
-
for (const item of data) {
|
|
1626
|
-
textContent += `\n • ${item.name}`;
|
|
1627
|
-
if (item.title) {
|
|
1628
|
-
textContent += ` - ${item.title}`;
|
|
1629
|
-
}
|
|
1630
|
-
if (item.description) {
|
|
1631
|
-
textContent += `\n ${item.description.slice(0, 100)}...`;
|
|
1632
|
-
}
|
|
1633
|
-
textContent += "\n";
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
else {
|
|
1637
|
-
textContent += "\n\nNo schemas found. Try 'list' to browse all available schemas, or use a broader search term.";
|
|
1638
|
-
}
|
|
1639
|
-
break;
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
if (response.suggestions && response.suggestions.length > 0) {
|
|
1643
|
-
textContent += "\n\n💡 Suggestions:\n";
|
|
1644
|
-
for (const suggestion of response.suggestions) {
|
|
1645
|
-
textContent += ` • ${suggestion}\n`;
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
return {
|
|
1649
|
-
content: [{
|
|
1650
|
-
type: "text",
|
|
1651
|
-
text: textContent,
|
|
1652
|
-
}],
|
|
1653
|
-
structuredContent: response,
|
|
1654
|
-
};
|
|
1655
|
-
});
|
|
1656
|
-
reg("bridge_operation", {
|
|
1657
|
-
title: "🌉 Bridge - Cross-Chain Operations",
|
|
1658
|
-
description: "🌉 Simplified cross-chain bridge between WOW and EVM (Ethereum mainnet). Only WOW mainnet provides cross-chain functionality.\n\n" +
|
|
1659
|
-
"Key concepts (transparent to user):\n" +
|
|
1660
|
-
" • Global single activeEvmAccount - auto-generated on first use, holds cross-chain assets.\n" +
|
|
1661
|
-
" • WOW→EVM: assets auto-claim to activeEvmAccount; optional withdrawTo transfers to a final EVM address.\n" +
|
|
1662
|
-
" • EVM→WOW: deposit from activeEvmAccount (balance checked first), assets arrive at the WOW account.\n\n" +
|
|
1663
|
-
"Operations (operation_type):\n" +
|
|
1664
|
-
" • cross_chain_wow_to_evm - WOW→EVM cross-chain (asset to activeEvmAccount or withdrawTo). [Requires WOW mainnet env]\n" +
|
|
1665
|
-
" • cross_chain_evm_to_wow - EVM→WOW cross-chain (from activeEvmAccount to WOW account). [Requires WOW mainnet env]\n" +
|
|
1666
|
-
" • withdraw - Withdraw from activeEvmAccount to another EVM address (non-cross-chain). [No env needed]\n" +
|
|
1667
|
-
" • query_active_evm_account - Query activeEvmAccount address + balances (per chain or all). [No env needed]\n" +
|
|
1668
|
-
" • query_supported_evm_chains - List supported EVM chains (enum/description/chainId/RPC health). [No env needed]\n" +
|
|
1669
|
-
" • query_supported_tokens - List supported Bridge tokens per chain (WOW/EVM contract addresses, decimals, description). [No env needed]\n" +
|
|
1670
|
-
" • query_transfer_list - Query transfer history list with optional filters (status/direction/token/limit). [No env needed]\n" +
|
|
1671
|
-
" • query_transfer_status - Query single transfer detail by transferId. [No env needed]\n" +
|
|
1672
|
-
" • manage_evm_rpc - Manage EVM RPC endpoints (list/add/remove/set/ping) to handle 429 rate limits. [No env needed]\n\n" +
|
|
1673
|
-
"Token support follows SDK config (ETH/WETH/WBTC/USDC/USDT). WOW account names are supported (resolved via LocalMark).\n" +
|
|
1674
|
-
"NOTE: Use schema_query (name='bridge_operation') to retrieve the exact JSON Schema with all field definitions before calling.",
|
|
1675
|
-
inputSchema: BridgeOperationsSchema,
|
|
1676
|
-
outputSchema: BridgeCallOutputSchema,
|
|
1677
|
-
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
1678
|
-
_meta: createToolMeta("operation", ["bridge", "cross-chain", "evm", "ethereum", "wow", "transfer", "rpc"]),
|
|
1679
|
-
}, handleBridgeOperations);
|
|
1680
|
-
reg("project_operation", {
|
|
1681
|
-
title: "🗂️ Project - Namespace & Object Graph",
|
|
1682
|
-
description: "Phase 2 project namespace service — manage and query the local object dependency graph (DAG) " +
|
|
1683
|
-
"built on top of local_mark tags. No on-chain writes; all data comes from local marks tagged " +
|
|
1684
|
-
"`project:<prefix>` (auto-injected by the ProjectService when enabled, default ON).\n\n" +
|
|
1685
|
-
"Actions:\n" +
|
|
1686
|
-
" • list_projects — List all discovered projects (grouped by `project:<prefix>` tag) with object counts.\n" +
|
|
1687
|
-
" • list_objects — List objects in a project (requires `project` param).\n" +
|
|
1688
|
-
" • shareable — List objects tagged `shareable:true` (cross-project reusable: common Permission, 3rd-party Arb).\n" +
|
|
1689
|
-
" • dependencies — Trace forward dependencies of an object (BFS transitive closure + dangling refs).\n" +
|
|
1690
|
-
" • referenced_by — Reverse query: who references this object?\n" +
|
|
1691
|
-
" • pre_publish_check — Pre-publish sanity check for a service (dangling deps + cycles).\n" +
|
|
1692
|
-
" • cross_project_refs — Find edges that cross project boundaries.\n" +
|
|
1693
|
-
" • graph_stats — Graph statistics (node/edge counts, cycles, dangling deps).\n" +
|
|
1694
|
-
" • save_graph — Save the in-memory graph to ~/.wowok/project-graph.json (persist across sessions).\n" +
|
|
1695
|
-
" • load_graph — Load the graph from file (restore after restart).\n\n" +
|
|
1696
|
-
"NOTE: The graph is in-memory by default. Use save_graph/load_graph for cross-session persistence " +
|
|
1697
|
-
"(or toggle graph_persist via config_operation for auto-save). " +
|
|
1698
|
-
"list_projects/shareable always query local_mark (persistent).\n\n" +
|
|
1699
|
-
"💡 Schema hint: Use schema_query with action='get' and name='project_operation' to retrieve the exact parameter schema with all actions and field definitions.",
|
|
1700
|
-
inputSchema: ProjectOperationInputSchema,
|
|
1701
|
-
outputSchema: ProjectOperationOutputSchema,
|
|
1702
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1703
|
-
_meta: createToolMeta("project", ["project", "namespace", "graph", "dag", "dependency", "reference", "organization"]),
|
|
1704
|
-
}, handleProjectOperation);
|
|
1705
|
-
reg("config_operation", {
|
|
1706
|
-
title: "⚙️ Config - Runtime Service Toggles",
|
|
1707
|
-
description: "Phase 2 runtime configuration — toggle Phase 2 services on/off at runtime WITHOUT restarting the MCP server. " +
|
|
1708
|
-
"This is the session-level switch mechanism: AI can toggle based on user conversation context, or users can " +
|
|
1709
|
-
"directly control which Phase 2 features are active.\n\n" +
|
|
1710
|
-
"Actions:\n" +
|
|
1711
|
-
" • list — List all services with current state + reminders.\n" +
|
|
1712
|
-
" • toggle — Toggle a service on/off (requires `service` param). Returns reminder text.\n" +
|
|
1713
|
-
" • enable — Enable a service (requires `service` param).\n" +
|
|
1714
|
-
" • disable — Disable a service (requires `service` param).\n" +
|
|
1715
|
-
" • reset — Reset a service to its default (requires `service` param).\n" +
|
|
1716
|
-
" • info — Get detailed info about a service (requires `service` param).\n\n" +
|
|
1717
|
-
"Services:\n" +
|
|
1718
|
-
" • confirm_gate — Safety Confirmation Gate (default ON)\n" +
|
|
1719
|
-
" • project_service — Project Namespace + Dependency Graph (default ON)\n" +
|
|
1720
|
-
" • harness — L4 Verify/Recover Loop (default OFF)\n" +
|
|
1721
|
-
" • graph_persist — Graph Persistence to File (default OFF)\n" +
|
|
1722
|
-
" • semantic_rich — Semantic Layer Enrichment Reminder (default ON)\n" +
|
|
1723
|
-
" • experience_layer — Real-time Experience Layer (Phase 2 Topic 2, default ON)\n" +
|
|
1724
|
-
" • customer_intelligence — Buyer Intelligence / Risk & Preference Alerts (Phase 3 C-3, default ON)\n" +
|
|
1725
|
-
" • order_monitor — In-progress Order Monitoring (Phase 3 C-3.2, default OFF)\n" +
|
|
1726
|
-
" • industry_evolution — Industry Specialization Evolution Flywheel (Phase 4, default ON)\n\n" +
|
|
1727
|
-
"NOTE: Toggles persist for the MCP process lifetime. Set WOWOK_RUNTIME_CONFIG_PERSIST=1 " +
|
|
1728
|
-
"to persist across sessions to ~/.wowok/runtime-config.json.\n\n" +
|
|
1729
|
-
"💡 Schema hint: Use schema_query with action='get' and name='config_operation' to retrieve the exact parameter schema with all actions and field definitions.",
|
|
1730
|
-
inputSchema: ConfigOperationInputSchema,
|
|
1731
|
-
outputSchema: ConfigOperationOutputSchema,
|
|
1732
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1733
|
-
_meta: createToolMeta("config", ["config", "toggle", "service", "runtime", "switch", "enable", "disable"]),
|
|
1734
|
-
}, handleConfigOperation);
|
|
1735
|
-
reg("trust_score", {
|
|
1736
|
-
title: "🛡️ Trust Score - Service Risk & Trust Assessment",
|
|
1737
|
-
description: "Proactively query the trust score and risk assessment of a Service object. " +
|
|
1738
|
-
"This is the standalone query form of the trust_score field that is otherwise only " +
|
|
1739
|
-
"passively injected into onchain_operations semantic output.\n\n" +
|
|
1740
|
-
"Returns:\n" +
|
|
1741
|
-
" • trust_score (0-100, 5 dimensions: arbitration/reviews/fulfillment/fund_safety/transparency)\n" +
|
|
1742
|
-
" • risk_score (4 dimensions: workflow/fund/trust/behavior, 100-point) when depth >= 'evaluate'\n" +
|
|
1743
|
-
" • info_puzzle completeness + gaps summary\n" +
|
|
1744
|
-
" • service_basics snapshot (published/paused/sales/guards/arbitrations)\n\n" +
|
|
1745
|
-
"Use this tool when the user asks 'is this service trustworthy?', 'should I buy from this merchant?', " +
|
|
1746
|
-
"'what's the risk of ordering this service?', or any explicit trust/risk inquiry about a Service.\n\n" +
|
|
1747
|
-
"Parameters:\n" +
|
|
1748
|
-
" • service (required) — Service object ID or local_mark name.\n" +
|
|
1749
|
-
" • order_amount (optional) — Order amount in smallest token unit (e.g. 2000000000 for 2 WOW). " +
|
|
1750
|
-
"Defaults to the service's first active sale price.\n" +
|
|
1751
|
-
" • depth (optional, default 'evaluate') — 'browse' (trust score only), 'evaluate' (+ risk assessment), " +
|
|
1752
|
-
"'preorder' (most thorough, includes market context dimension).\n\n" +
|
|
1753
|
-
"💡 Schema hint: Use schema_query with action='get' and name='trust_score' to retrieve the exact parameter schema.",
|
|
1754
|
-
inputSchema: TrustScoreInputSchema,
|
|
1755
|
-
outputSchema: TrustScoreOutputSchema,
|
|
1756
|
-
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1757
|
-
_meta: createToolMeta("trust", ["trust", "score", "risk", "service", "merchant", "reputation", "safety", "evaluate"]),
|
|
1758
|
-
}, handleTrustScore);
|
|
145
|
+
registerAllTools(server);
|
|
1759
146
|
const transport = new StdioServerTransport();
|
|
1760
147
|
await server.connect(transport);
|
|
1761
148
|
process.on("SIGINT", async () => {
|