@wowok/agent-mcp 2.3.14 → 2.3.18
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/config/index.d.ts +1 -0
- package/dist/config/index.js +1 -0
- package/dist/config/runtime.d.ts +26 -0
- package/dist/config/runtime.js +217 -0
- package/dist/customer/index.d.ts +9 -0
- package/dist/customer/index.js +9 -0
- package/dist/customer/industry-risks.d.ts +40 -0
- package/dist/customer/industry-risks.js +438 -0
- package/dist/customer/info-puzzle.d.ts +102 -0
- package/dist/customer/info-puzzle.js +312 -0
- package/dist/customer/order-monitor.d.ts +75 -0
- package/dist/customer/order-monitor.js +327 -0
- package/dist/customer/order-strategy.d.ts +36 -0
- package/dist/customer/order-strategy.js +373 -0
- package/dist/customer/post-purchase.d.ts +42 -0
- package/dist/customer/post-purchase.js +350 -0
- package/dist/customer/reminder-system.d.ts +42 -0
- package/dist/customer/reminder-system.js +295 -0
- package/dist/customer/risk-assessment.d.ts +8 -0
- package/dist/customer/risk-assessment.js +337 -0
- package/dist/customer/types.d.ts +193 -0
- package/dist/customer/types.js +13 -0
- package/dist/customer/user-preferences.d.ts +70 -0
- package/dist/customer/user-preferences.js +460 -0
- package/dist/experience/experience-reuse.d.ts +10 -0
- package/dist/experience/experience-reuse.js +103 -0
- package/dist/experience/index.d.ts +6 -0
- package/dist/experience/index.js +5 -0
- package/dist/experience/intent-distill.d.ts +3 -0
- package/dist/experience/intent-distill.js +83 -0
- package/dist/experience/realtime-feedback.d.ts +5 -0
- package/dist/experience/realtime-feedback.js +94 -0
- package/dist/experience/types.d.ts +50 -0
- package/dist/experience/types.js +1 -0
- package/dist/experience/user-profile.d.ts +25 -0
- package/dist/experience/user-profile.js +171 -0
- package/dist/index.js +842 -371
- package/dist/knowledge/acquisition-flywheel.d.ts +53 -0
- package/dist/knowledge/acquisition-flywheel.js +192 -0
- package/dist/knowledge/arbitration-trust.d.ts +24 -0
- package/dist/knowledge/arbitration-trust.js +117 -0
- package/dist/knowledge/audit-rules.d.ts +28 -0
- package/dist/knowledge/audit-rules.js +141 -0
- package/dist/knowledge/demand-matching.d.ts +29 -0
- package/dist/knowledge/demand-matching.js +132 -0
- package/dist/knowledge/dynamic-pricing.d.ts +31 -0
- package/dist/knowledge/dynamic-pricing.js +87 -0
- package/dist/knowledge/flywheel-loop.d.ts +87 -0
- package/dist/knowledge/flywheel-loop.js +378 -0
- package/dist/knowledge/glossary.d.ts +18 -0
- package/dist/knowledge/glossary.js +209 -0
- package/dist/knowledge/guard-ledger.d.ts +19 -0
- package/dist/knowledge/guard-ledger.js +219 -0
- package/dist/knowledge/guard-puzzle.d.ts +93 -0
- package/dist/knowledge/guard-puzzle.js +278 -0
- package/dist/knowledge/guard-risk.d.ts +60 -0
- package/dist/knowledge/guard-risk.js +474 -0
- package/dist/knowledge/guard-translation.d.ts +46 -0
- package/dist/knowledge/guard-translation.js +487 -0
- package/dist/knowledge/index.d.ts +77 -0
- package/dist/knowledge/index.js +79 -0
- package/dist/knowledge/industry-evolution.d.ts +82 -0
- package/dist/knowledge/industry-evolution.js +323 -0
- package/dist/knowledge/industry-generalizer.d.ts +17 -0
- package/dist/knowledge/industry-generalizer.js +381 -0
- package/dist/knowledge/industry-registry.d.ts +48 -0
- package/dist/knowledge/industry-registry.js +187 -0
- package/dist/knowledge/intent-metrics.d.ts +42 -0
- package/dist/knowledge/intent-metrics.js +566 -0
- package/dist/knowledge/process-model.d.ts +24 -0
- package/dist/knowledge/process-model.js +160 -0
- package/dist/knowledge/reputation-rules.d.ts +42 -0
- package/dist/knowledge/reputation-rules.js +99 -0
- package/dist/knowledge/reward-templates.d.ts +25 -0
- package/dist/knowledge/reward-templates.js +125 -0
- package/dist/knowledge/safety-rules.d.ts +36 -0
- package/dist/knowledge/safety-rules.js +232 -0
- package/dist/knowledge/tool-constraints.d.ts +30 -0
- package/dist/knowledge/tool-constraints.js +175 -0
- package/dist/knowledge/trust-metrics.d.ts +37 -0
- package/dist/knowledge/trust-metrics.js +138 -0
- package/dist/loop-engineering/diagnose.d.ts +3 -2
- package/dist/loop-engineering/diagnose.js +94 -0
- package/dist/loop-engineering/improve.d.ts +1 -1
- package/dist/loop-engineering/improve.js +52 -1
- package/dist/project/graph.d.ts +71 -0
- package/dist/project/graph.js +314 -0
- package/dist/project/index.d.ts +62 -0
- package/dist/project/index.js +167 -0
- package/dist/project/namespace.d.ts +62 -0
- package/dist/project/namespace.js +181 -0
- package/dist/project/query.d.ts +40 -0
- package/dist/project/query.js +110 -0
- package/dist/safety/confirm-gate.d.ts +17 -0
- package/dist/safety/confirm-gate.js +88 -0
- package/dist/safety/index.d.ts +3 -0
- package/dist/safety/index.js +3 -0
- package/dist/safety/preview.d.ts +2 -0
- package/dist/safety/preview.js +36 -0
- package/dist/schema/call/allocation.d.ts +39 -14
- package/dist/schema/call/arbitration.d.ts +187 -162
- package/dist/schema/call/base.d.ts +1971 -87
- package/dist/schema/call/base.js +135 -3
- package/dist/schema/call/bridge-handler.js +15 -2
- package/dist/schema/call/bridge.d.ts +1478 -53
- package/dist/schema/call/bridge.js +50 -2
- package/dist/schema/call/contact.d.ts +25 -0
- package/dist/schema/call/demand.d.ts +79 -54
- package/dist/schema/call/guard.d.ts +125 -50
- package/dist/schema/call/handler.d.ts +3 -0
- package/dist/schema/call/handler.js +60 -14
- package/dist/schema/call/machine.d.ts +988 -938
- package/dist/schema/call/order.d.ts +25 -0
- package/dist/schema/call/payment.d.ts +25 -0
- package/dist/schema/call/permission.d.ts +244 -219
- package/dist/schema/call/personal.d.ts +25 -0
- package/dist/schema/call/progress.d.ts +25 -0
- package/dist/schema/call/proof.d.ts +62 -12
- package/dist/schema/call/proof.js +3 -3
- package/dist/schema/call/repository.d.ts +101 -76
- package/dist/schema/call/reward.d.ts +55 -30
- package/dist/schema/call/semantic.d.ts +10 -2
- package/dist/schema/call/semantic.js +616 -11
- package/dist/schema/call/service.d.ts +442 -417
- package/dist/schema/call/treasury.d.ts +25 -0
- package/dist/schema/common/index.js +3 -3
- package/dist/schema/config/index.d.ts +18 -0
- package/dist/schema/config/index.js +17 -0
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/local/index.d.ts +237 -81
- package/dist/schema/local/index.js +42 -6
- package/dist/schema/messenger/index.d.ts +1018 -79
- package/dist/schema/messenger/index.js +26 -17
- package/dist/schema/operations.d.ts +3192 -1746
- package/dist/schema/operations.js +93 -98
- package/dist/schema/project/index.d.ts +21 -0
- package/dist/schema/project/index.js +32 -0
- package/dist/schema/query/index.d.ts +2762 -1856
- package/dist/schema/query/index.js +38 -35
- package/dist/schema/schema-query/index.d.ts +33 -0
- package/dist/schema/schema-query/index.js +36 -0
- package/dist/schema/schema-version.d.ts +25 -0
- package/dist/schema/schema-version.js +76 -0
- package/dist/schema/trust/index.d.ts +407 -0
- package/dist/schema/trust/index.js +113 -0
- package/dist/schemas/account_operation.output.json +25 -16
- package/dist/schemas/account_operation.schema.json +1 -1
- package/dist/schemas/bridge_operation.output.json +744 -0
- package/dist/schemas/bridge_operation.schema.json +82 -8
- package/dist/schemas/config_operation.output.json +18 -0
- package/dist/schemas/config_operation.schema.json +34 -0
- package/dist/schemas/guard-node-schema.json +82 -0
- package/dist/schemas/guard2file.schema.json +23 -0
- package/dist/schemas/index.json +19 -1
- package/dist/schemas/local_info_operation.output.json +23 -0
- package/dist/schemas/local_info_operation.schema.json +1 -1
- package/dist/schemas/local_mark_operation.output.json +24 -1
- package/dist/schemas/local_mark_operation.schema.json +4 -4
- package/dist/schemas/machineNode2file.schema.json +23 -0
- package/dist/schemas/messenger_operation.output.json +752 -0
- package/dist/schemas/onchain_events.output.json +718 -0
- package/dist/schemas/onchain_operations.output.json +627 -18
- package/dist/schemas/onchain_operations.schema.json +115 -39
- package/dist/schemas/onchain_operations_allocation.schema.json +23 -0
- package/dist/schemas/onchain_operations_arbitration.schema.json +23 -0
- package/dist/schemas/onchain_operations_contact.schema.json +23 -0
- package/dist/schemas/onchain_operations_demand.schema.json +23 -0
- package/dist/schemas/onchain_operations_gen_passport.schema.json +46 -0
- package/dist/schemas/onchain_operations_guard.schema.json +26 -16
- package/dist/schemas/onchain_operations_machine.schema.json +89 -23
- package/dist/schemas/onchain_operations_order.schema.json +23 -0
- package/dist/schemas/onchain_operations_payment.schema.json +23 -0
- package/dist/schemas/onchain_operations_permission.schema.json +23 -0
- package/dist/schemas/onchain_operations_personal.schema.json +23 -0
- package/dist/schemas/onchain_operations_progress.schema.json +23 -0
- package/dist/schemas/onchain_operations_repository.schema.json +23 -0
- package/dist/schemas/onchain_operations_reward.schema.json +23 -0
- package/dist/schemas/onchain_operations_service.schema.json +23 -0
- package/dist/schemas/onchain_operations_treasury.schema.json +23 -0
- package/dist/schemas/onchain_table_data.output.json +939 -69
- package/dist/schemas/onchain_table_data.schema.json +2 -2
- package/dist/schemas/project_operation.output.json +18 -0
- package/dist/schemas/project_operation.schema.json +42 -0
- package/dist/schemas/query_toolkit.schema.json +360 -368
- package/dist/schemas/schema_query.schema.json +6 -3
- package/dist/schemas/trust_score.output.json +327 -0
- package/dist/schemas/trust_score.schema.json +46 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5,13 +5,19 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
5
5
|
import { readFileSync } from "fs";
|
|
6
6
|
import { resolve } from "path";
|
|
7
7
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
8
|
-
import { MachineNode2File_InputSchema, MachineNode2File_OutputWrappedSchema, Guard2File_InputSchema, Guard2File_OutputWrappedSchema, strictParse, CallOutputSchema, handleCallResult, createServerConfig, createCapabilitiesConfig, createToolMeta, transformSubmission, getEnvConfig, OnchainEventsInputSchema, OnchainEventsResultSchema, ProtocolInfoQuerySchema, ProtocolInfoResultSchema, AccountOperationOutputWrappedSchema, LocalMarkOperationOutputWrappedSchema, LocalInfoOperationOutputWrappedSchema, WipOperationOutputSchema, MessengerOperationOutputSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, parseMachineNodesFromText, formatNodeErrors as formatMachineNodeErrors, MessengerOperationInputSchema, BridgeOperationsSchema, BridgeCallOutputSchema, OnchainOperationsSchema, WipOperationsSchema, OnchainTableDataSchema, OnchainTableDataResultSchema, WatchQueryOperationsSchema, } from "./schema/index.js";
|
|
8
|
+
import { MachineNode2File_InputSchema, MachineNode2File_OutputWrappedSchema, Guard2File_InputSchema, Guard2File_OutputWrappedSchema, strictParse, CallOutputSchema, handleCallResult, createServerConfig, createCapabilitiesConfig, createToolMeta, transformSubmission, getEnvConfig, OnchainEventsInputSchema, OnchainEventsResultSchema, ProtocolInfoQuerySchema, ProtocolInfoResultSchema, AccountOperationOutputWrappedSchema, LocalMarkOperationOutputWrappedSchema, LocalInfoOperationOutputWrappedSchema, WipOperationOutputSchema, MessengerOperationOutputSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, parseMachineNodesFromText, formatNodeErrors as formatMachineNodeErrors, MessengerOperationInputSchema, BridgeOperationsSchema, BridgeCallOutputSchema, OnchainOperationsSchema, WipOperationsSchema, OnchainTableDataSchema, OnchainTableDataResultSchema, WatchQueryOperationsSchema, registerSuccessHook, SchemaQueryInputSchema, SchemaQueryOutputSchema, ProjectOperationInputSchema, ProjectOperationOutputSchema, ConfigOperationInputSchema, ConfigOperationOutputSchema, TrustScoreInputSchema, TrustScoreOutputSchema, checkClientSchemaCompatibility, } from "./schema/index.js";
|
|
9
9
|
import { handleBridgeOperations } from "./schema/call/bridge-handler.js";
|
|
10
10
|
import { buildDataSemantic, classifyError } from "./schema/call/semantic.js";
|
|
11
11
|
import { getHarness } from "./harness/index.js";
|
|
12
|
-
|
|
12
|
+
import { confirmGate } from "./safety/confirm-gate.js";
|
|
13
|
+
import { renderPreview } from "./safety/preview.js";
|
|
14
|
+
import { isProjectServiceEnabled, normalize as projectNormalize, observe as projectObserve, queryProjects, queryProjectObjects, queryShareableObjects, queryDependencies, queryReferencedBy, queryPrePublishCheck, queryCrossProjectReferences, queryGraphStats, saveGraph, loadGraph, } from "./project/index.js";
|
|
15
|
+
import { isEnabled as isRuntimeEnabled, listServices, getServiceInfo, toggle as toggleService, setEnabled as setServiceEnabled, reset as resetService, } from "./config/index.js";
|
|
16
|
+
import { validateOperation, hasBlockingViolations, getWarningViolations, computeServiceTrustScore, } from "./knowledge/index.js";
|
|
17
|
+
import { assembleInfoPuzzle, assessRisk, } from "./customer/index.js";
|
|
18
|
+
const HARNESS_ENABLED = () => isRuntimeEnabled("harness");
|
|
13
19
|
function withHarness(base, operation, intent) {
|
|
14
|
-
if (!HARNESS_ENABLED)
|
|
20
|
+
if (!HARNESS_ENABLED())
|
|
15
21
|
return base;
|
|
16
22
|
try {
|
|
17
23
|
const harness = getHarness();
|
|
@@ -27,7 +33,59 @@ function withHarness(base, operation, intent) {
|
|
|
27
33
|
return base;
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
|
-
|
|
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
|
+
};
|
|
87
|
+
}
|
|
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";
|
|
31
89
|
import { areSchemasAvailable, getSchemaIndex, processSchemaQuery, } from "./schema-query/index.js";
|
|
32
90
|
const SERVER_DESCRIPTION = `WoWok MCP Server - Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.
|
|
33
91
|
|
|
@@ -141,40 +199,73 @@ import { withTelemetry, setTelemetryEnabled } from "./telemetry/index.js";
|
|
|
141
199
|
if (process.env.WOWOK_TELEMETRY === "false" || process.env.WOWOK_TELEMETRY === "0") {
|
|
142
200
|
setTelemetryEnabled(false);
|
|
143
201
|
}
|
|
144
|
-
function
|
|
145
|
-
|
|
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;
|
|
146
211
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
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
|
+
]);
|
|
158
249
|
}
|
|
159
|
-
function
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (
|
|
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);
|
|
166
261
|
return {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
...guard.amount,
|
|
170
|
-
type: convertAmountType(guard.amount.type)
|
|
171
|
-
}
|
|
262
|
+
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
263
|
+
structuredContent,
|
|
172
264
|
};
|
|
173
265
|
}
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return transformed;
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
178
269
|
}
|
|
179
270
|
async function handleOnchainTableData(args) {
|
|
180
271
|
const validated = strictParse(OnchainTableDataSchema, args, "onchain_table_data input");
|
|
@@ -261,6 +352,7 @@ async function handleOnchainTableData(args) {
|
|
|
261
352
|
}
|
|
262
353
|
async function handleOnchainOperations(args) {
|
|
263
354
|
let validated;
|
|
355
|
+
let constraintWarnings = [];
|
|
264
356
|
try {
|
|
265
357
|
if (typeof args === 'object' && args !== null && args.description && !args.operation_type) {
|
|
266
358
|
const hasWrappedParams = typeof args.description === 'string' &&
|
|
@@ -273,6 +365,42 @@ async function handleOnchainOperations(args) {
|
|
|
273
365
|
}
|
|
274
366
|
validated = strictParse(OnchainOperationsSchema, args, "onchain_operations input");
|
|
275
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
|
+
}
|
|
276
404
|
switch (validated.operation_type) {
|
|
277
405
|
case "service": {
|
|
278
406
|
const callService = new CallService(validated.data);
|
|
@@ -281,7 +409,7 @@ async function handleOnchainOperations(args) {
|
|
|
281
409
|
: await callService.call(env);
|
|
282
410
|
const data = validated.data;
|
|
283
411
|
const intent = data?.publish ? "publish service" : data?.bPublished !== undefined ? "modify service" : "create service";
|
|
284
|
-
return handleCallResult(result, withHarness(
|
|
412
|
+
return handleCallResult(result, withHarness(buildCtx(data), "service", intent));
|
|
285
413
|
}
|
|
286
414
|
case "machine": {
|
|
287
415
|
if (validated.data.node && typeof validated.data.node === 'object' && 'json_or_markdown_file' in validated.data.node) {
|
|
@@ -312,62 +440,62 @@ async function handleOnchainOperations(args) {
|
|
|
312
440
|
const result = validated.submission
|
|
313
441
|
? await callMachine.call_with_submission(env, await transformSubmission(validated.submission))
|
|
314
442
|
: await callMachine.call(env);
|
|
315
|
-
return handleCallResult(result,
|
|
443
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
316
444
|
}
|
|
317
445
|
case "progress": {
|
|
318
446
|
const callProgress = new CallProgress(validated.data);
|
|
319
447
|
const result = validated.submission
|
|
320
448
|
? await callProgress.call_with_submission(env, await transformSubmission(validated.submission))
|
|
321
449
|
: await callProgress.call(env);
|
|
322
|
-
return handleCallResult(result,
|
|
450
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
323
451
|
}
|
|
324
452
|
case "repository": {
|
|
325
453
|
const callRepository = new CallRepository(validated.data);
|
|
326
454
|
const result = validated.submission
|
|
327
455
|
? await callRepository.call_with_submission(env, await transformSubmission(validated.submission))
|
|
328
456
|
: await callRepository.call(env);
|
|
329
|
-
return handleCallResult(result,
|
|
457
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
330
458
|
}
|
|
331
459
|
case "arbitration": {
|
|
332
460
|
const callArbitration = new CallArbitration(validated.data);
|
|
333
461
|
const result = validated.submission
|
|
334
462
|
? await callArbitration.call_with_submission(env, await transformSubmission(validated.submission))
|
|
335
463
|
: await callArbitration.call(env);
|
|
336
|
-
return handleCallResult(result,
|
|
464
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
337
465
|
}
|
|
338
466
|
case "contact": {
|
|
339
467
|
const callContact = new CallContact(validated.data);
|
|
340
468
|
const result = validated.submission
|
|
341
469
|
? await callContact.call_with_submission(env, await transformSubmission(validated.submission))
|
|
342
470
|
: await callContact.call(env);
|
|
343
|
-
return handleCallResult(result,
|
|
471
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
344
472
|
}
|
|
345
473
|
case "treasury": {
|
|
346
474
|
const callTreasury = new CallTreasury(validated.data);
|
|
347
475
|
const result = validated.submission
|
|
348
476
|
? await callTreasury.call_with_submission(env, await transformSubmission(validated.submission))
|
|
349
477
|
: await callTreasury.call(env);
|
|
350
|
-
return handleCallResult(result,
|
|
478
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
351
479
|
}
|
|
352
480
|
case "reward": {
|
|
353
|
-
const transformedData =
|
|
481
|
+
const transformedData = transformRewardInput(validated.data);
|
|
354
482
|
const callReward = new CallReward(transformedData);
|
|
355
483
|
const result = validated.submission
|
|
356
484
|
? await callReward.call_with_submission(env, await transformSubmission(validated.submission))
|
|
357
485
|
: await callReward.call(env);
|
|
358
|
-
return handleCallResult(result,
|
|
486
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
359
487
|
}
|
|
360
488
|
case "allocation": {
|
|
361
489
|
const callAllocation = new CallAllocation(validated.data);
|
|
362
490
|
const result = validated.submission
|
|
363
491
|
? await callAllocation.call_with_submission(env, await transformSubmission(validated.submission))
|
|
364
492
|
: await callAllocation.call(env);
|
|
365
|
-
return handleCallResult(result,
|
|
493
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
366
494
|
}
|
|
367
495
|
case "permission": {
|
|
368
496
|
const callPermission = new CallPermission(validated.data);
|
|
369
497
|
const result = await callPermission.call(env);
|
|
370
|
-
return handleCallResult(result,
|
|
498
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
371
499
|
}
|
|
372
500
|
case "guard": {
|
|
373
501
|
const validatedData = validated.data;
|
|
@@ -414,211 +542,120 @@ async function handleOnchainOperations(args) {
|
|
|
414
542
|
}
|
|
415
543
|
const callGuard = new CallGuard(validatedData);
|
|
416
544
|
const result = await callGuard.call(env);
|
|
417
|
-
return handleCallResult(result,
|
|
545
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
418
546
|
}
|
|
419
547
|
case "personal": {
|
|
420
|
-
const
|
|
421
|
-
const result = { ...data };
|
|
422
|
-
if (data.mark) {
|
|
423
|
-
const transformAddress = (addr) => {
|
|
424
|
-
if (typeof addr === 'string') {
|
|
425
|
-
return { name_or_address: addr, local_mark_first: true };
|
|
426
|
-
}
|
|
427
|
-
return addr;
|
|
428
|
-
};
|
|
429
|
-
if (data.mark.op === 'add' && data.mark.data) {
|
|
430
|
-
result.mark = {
|
|
431
|
-
...data.mark,
|
|
432
|
-
data: data.mark.data.map((item) => ({
|
|
433
|
-
...item,
|
|
434
|
-
address: transformAddress(item.address)
|
|
435
|
-
}))
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
else if (data.mark.op === 'remove' && data.mark.data) {
|
|
439
|
-
result.mark = {
|
|
440
|
-
...data.mark,
|
|
441
|
-
data: data.mark.data.map((item) => ({
|
|
442
|
-
...item,
|
|
443
|
-
address: transformAddress(item.address)
|
|
444
|
-
}))
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
else if (data.mark.op === 'clear' && data.mark.address) {
|
|
448
|
-
const addr = data.mark.address;
|
|
449
|
-
if (Array.isArray(addr) && addr.every((a) => typeof a === 'string')) {
|
|
450
|
-
result.mark = {
|
|
451
|
-
...data.mark,
|
|
452
|
-
address: {
|
|
453
|
-
entities: addr.map((a) => ({ name_or_address: a, local_mark_first: true }))
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
else if (data.mark.op === 'transfer' && data.mark.to) {
|
|
459
|
-
result.mark = {
|
|
460
|
-
...data.mark,
|
|
461
|
-
to: transformAddress(data.mark.to)
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
return result;
|
|
466
|
-
};
|
|
467
|
-
const transformedData = transformPersonalData(validated.data);
|
|
548
|
+
const transformedData = transformPersonalInput(validated.data);
|
|
468
549
|
const callPersonal = new CallPersonal(transformedData);
|
|
469
550
|
const result = await callPersonal.call(env);
|
|
470
|
-
return handleCallResult(result,
|
|
551
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
471
552
|
}
|
|
472
553
|
case "payment": {
|
|
473
554
|
const callPayment = new CallPayment(validated.data);
|
|
474
555
|
const result = await callPayment.call(env);
|
|
475
|
-
return handleCallResult(result,
|
|
556
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
476
557
|
}
|
|
477
558
|
case "demand": {
|
|
478
559
|
const callDemand = new CallDemand(validated.data);
|
|
479
560
|
const result = validated.submission
|
|
480
561
|
? await callDemand.call_with_submission(env, await transformSubmission(validated.submission))
|
|
481
562
|
: await callDemand.call(env);
|
|
482
|
-
return handleCallResult(result,
|
|
563
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
483
564
|
}
|
|
484
565
|
case "order": {
|
|
485
566
|
const callOrder = new CallOrder(validated.data);
|
|
486
567
|
const result = validated.submission
|
|
487
568
|
? await callOrder.call_with_submission(env, await transformSubmission(validated.submission))
|
|
488
569
|
: await callOrder.call(env);
|
|
489
|
-
return handleCallResult(result,
|
|
570
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
490
571
|
}
|
|
491
572
|
case "gen_passport": {
|
|
492
573
|
const result = await gen_passport(env, validated.guard, validated.info);
|
|
493
|
-
return handleCallResult(result,
|
|
574
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
494
575
|
}
|
|
495
576
|
case "proof": {
|
|
496
577
|
const callProof = new CallProof(validated.data);
|
|
497
578
|
const result = validated.submission
|
|
498
579
|
? await callProof.call_with_submission(env, await transformSubmission(validated.submission))
|
|
499
580
|
: await callProof.call(env);
|
|
500
|
-
return handleCallResult(result,
|
|
581
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
501
582
|
}
|
|
502
583
|
case "gen_proof": {
|
|
503
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);
|
|
504
|
-
return handleCallResult(result,
|
|
585
|
+
return handleCallResult(result, buildCtx(validated.data));
|
|
505
586
|
}
|
|
506
587
|
}
|
|
507
588
|
throw new Error(`Unknown on-chain operation type: ${validated.operation_type}`);
|
|
508
589
|
}
|
|
509
590
|
catch (error) {
|
|
510
591
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
511
|
-
return handleCallResult({ error: errorMessage }, validated ? {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
let validated;
|
|
516
|
-
try {
|
|
517
|
-
validated = strictParse(AccountOperationSchema, args, "account_operation input");
|
|
518
|
-
const result = await account_operation(validated);
|
|
519
|
-
const ctx = { operation_type: "account_" + validated.operation_type, data: validated };
|
|
520
|
-
return {
|
|
521
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
522
|
-
structuredContent: {
|
|
523
|
-
result: {
|
|
524
|
-
status: "success",
|
|
525
|
-
data: result,
|
|
526
|
-
},
|
|
527
|
-
semantic: buildDataSemantic(result, ctx),
|
|
528
|
-
},
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
catch (error) {
|
|
532
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
533
|
-
const ctx = validated ? { operation_type: "account_" + validated.operation_type, data: validated } : undefined;
|
|
534
|
-
const classified = classifyError(errorMessage);
|
|
535
|
-
return {
|
|
536
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
537
|
-
structuredContent: {
|
|
538
|
-
result: {
|
|
539
|
-
status: "error",
|
|
540
|
-
error: errorMessage,
|
|
541
|
-
error_code: classified.error_code,
|
|
542
|
-
retryable: classified.retryable,
|
|
543
|
-
recovery_hint: classified.recovery_hint,
|
|
544
|
-
},
|
|
545
|
-
semantic: buildDataSemantic(undefined, ctx, true, errorMessage),
|
|
546
|
-
},
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
async function handleMarkOperation(args) {
|
|
551
|
-
let validated;
|
|
552
|
-
try {
|
|
553
|
-
validated = strictParse(LocalMarkOperationSchema, args, "local_mark_operation input");
|
|
554
|
-
const result = await local_mark_operation(validated);
|
|
555
|
-
const ctx = { operation_type: "mark_" + validated.operation_type, data: validated };
|
|
556
|
-
return {
|
|
557
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
558
|
-
structuredContent: {
|
|
559
|
-
result: {
|
|
560
|
-
status: "success",
|
|
561
|
-
data: result,
|
|
562
|
-
},
|
|
563
|
-
semantic: buildDataSemantic(result, ctx),
|
|
564
|
-
},
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
catch (error) {
|
|
568
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
569
|
-
const ctx = validated ? { operation_type: "mark_" + validated.operation_type, data: validated } : undefined;
|
|
570
|
-
const classified = classifyError(errorMessage);
|
|
571
|
-
return {
|
|
572
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
573
|
-
structuredContent: {
|
|
574
|
-
result: {
|
|
575
|
-
status: "error",
|
|
576
|
-
error: errorMessage,
|
|
577
|
-
error_code: classified.error_code,
|
|
578
|
-
retryable: classified.retryable,
|
|
579
|
-
recovery_hint: classified.recovery_hint,
|
|
580
|
-
},
|
|
581
|
-
semantic: buildDataSemantic(undefined, ctx, true, errorMessage),
|
|
582
|
-
},
|
|
583
|
-
};
|
|
592
|
+
return handleCallResult({ error: errorMessage }, validated ? {
|
|
593
|
+
operation_type: validated.operation_type,
|
|
594
|
+
data: validated.data,
|
|
595
|
+
} : undefined);
|
|
584
596
|
}
|
|
585
597
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
validated
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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),
|
|
598
614
|
},
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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),
|
|
616
636
|
},
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
};
|
|
621
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
|
+
});
|
|
622
659
|
async function handleWipOperations(args) {
|
|
623
660
|
const validated = strictParse(WipOperationsSchema, args, "wip_file input");
|
|
624
661
|
let structuredContent;
|
|
@@ -780,168 +817,501 @@ async function handleOnchainEvents(args) {
|
|
|
780
817
|
},
|
|
781
818
|
};
|
|
782
819
|
}
|
|
783
|
-
function
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
return input;
|
|
788
|
-
}
|
|
789
|
-
function normalizeManyAccountOrMark(input) {
|
|
790
|
-
if (Array.isArray(input)) {
|
|
791
|
-
return {
|
|
792
|
-
entities: input.map(item => typeof item === 'string' ? { name_or_address: item, local_mark_first: true } : item),
|
|
793
|
-
check_all_founded: true
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
return input;
|
|
797
|
-
}
|
|
798
|
-
async function handleMessengerOperation(args) {
|
|
799
|
-
const validated = strictParse(MessengerOperationInputSchema, args, "messenger_operation input");
|
|
820
|
+
async function handleProjectOperation(args) {
|
|
821
|
+
const action = args.action;
|
|
822
|
+
const project = args.project;
|
|
823
|
+
const object = args.object;
|
|
800
824
|
let result;
|
|
801
|
-
switch (
|
|
802
|
-
case "
|
|
803
|
-
|
|
804
|
-
result = { operation: "watch_conversations", result: conversations };
|
|
825
|
+
switch (action) {
|
|
826
|
+
case "list_projects":
|
|
827
|
+
result = await queryProjects();
|
|
805
828
|
break;
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
...sendResult,
|
|
811
|
-
merkleData: sendResult.merkleData ? {
|
|
812
|
-
leafIndex: sendResult.merkleData.leafIndex,
|
|
813
|
-
prevRoot: sendResult.merkleData.prevRoot,
|
|
814
|
-
newRoot: sendResult.merkleData.newRoot,
|
|
815
|
-
serverSignature: sendResult.merkleData.serverSignature,
|
|
816
|
-
serverTimestamp: sendResult.merkleData.serverTimestamp,
|
|
817
|
-
serverPublicKey: sendResult.merkleData.serverPublicKey,
|
|
818
|
-
} : undefined,
|
|
819
|
-
};
|
|
820
|
-
result = { operation: "send_message", result: filteredResult };
|
|
829
|
+
case "list_objects":
|
|
830
|
+
if (!project)
|
|
831
|
+
throw new Error("'project' param is required for list_objects");
|
|
832
|
+
result = await queryProjectObjects(project);
|
|
821
833
|
break;
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const sendResult = await send_file(validated.from, normalizeAccountOrMark(validated.to), validated.filePath, validated.options);
|
|
825
|
-
const filteredResult = {
|
|
826
|
-
...sendResult,
|
|
827
|
-
merkleData: sendResult.merkleData ? {
|
|
828
|
-
leafIndex: sendResult.merkleData.leafIndex,
|
|
829
|
-
prevRoot: sendResult.merkleData.prevRoot,
|
|
830
|
-
newRoot: sendResult.merkleData.newRoot,
|
|
831
|
-
serverSignature: sendResult.merkleData.serverSignature,
|
|
832
|
-
serverTimestamp: sendResult.merkleData.serverTimestamp,
|
|
833
|
-
serverPublicKey: sendResult.merkleData.serverPublicKey,
|
|
834
|
-
} : undefined,
|
|
835
|
-
};
|
|
836
|
-
result = { operation: "send_file", result: filteredResult };
|
|
834
|
+
case "shareable":
|
|
835
|
+
result = await queryShareableObjects();
|
|
837
836
|
break;
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
peerAddress: validated.filter.peerAddress ? normalizeAccountOrMark(validated.filter.peerAddress) : undefined
|
|
843
|
-
} : undefined;
|
|
844
|
-
const messages = await watch_messages(filter);
|
|
845
|
-
result = { operation: "watch_messages", result: messages };
|
|
837
|
+
case "dependencies":
|
|
838
|
+
if (!object)
|
|
839
|
+
throw new Error("'object' param is required for dependencies");
|
|
840
|
+
result = queryDependencies(object);
|
|
846
841
|
break;
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
result =
|
|
842
|
+
case "referenced_by":
|
|
843
|
+
if (!object)
|
|
844
|
+
throw new Error("'object' param is required for referenced_by");
|
|
845
|
+
result = queryReferencedBy(object);
|
|
851
846
|
break;
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
peerAccount: normalizeAccountOrMark(validated.params.peerAccount)
|
|
857
|
-
} : undefined;
|
|
858
|
-
const wtsResult = await generate_wts(params);
|
|
859
|
-
result = { operation: "generate_wts", result: wtsResult };
|
|
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) };
|
|
860
851
|
break;
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
const verifyResult = await verify_wts(validated.wtsFilePath);
|
|
864
|
-
result = { operation: "verify_wts", result: verifyResult };
|
|
852
|
+
case "cross_project_refs":
|
|
853
|
+
result = queryCrossProjectReferences();
|
|
865
854
|
break;
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
const signedPath = await sign_wts(validated.wtsFilePath, validated.account, validated.outputPath);
|
|
869
|
-
result = { operation: "sign_wts", result: signedPath };
|
|
855
|
+
case "graph_stats":
|
|
856
|
+
result = queryGraphStats();
|
|
870
857
|
break;
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
const htmlResult = await wts2html(validated.wtsPath, validated.options);
|
|
874
|
-
result = { operation: "wts2html", result: htmlResult };
|
|
858
|
+
case "save_graph":
|
|
859
|
+
result = { saved: true, path: saveGraph() };
|
|
875
860
|
break;
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const proofResult = await proof_message(validated.account, validated.messageId, validated.network);
|
|
879
|
-
result = { operation: "proof_message", result: proofResult };
|
|
861
|
+
case "load_graph":
|
|
862
|
+
result = { loaded: loadGraph() };
|
|
880
863
|
break;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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() };
|
|
892
878
|
break;
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
friendslistParams.users = normalizeManyAccountOrMark(validated.friendslist.users);
|
|
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.`);
|
|
901
886
|
}
|
|
902
|
-
const
|
|
903
|
-
result = {
|
|
904
|
-
break;
|
|
905
|
-
}
|
|
906
|
-
case "guardlist": {
|
|
907
|
-
const guardlistResult = await guardlist({
|
|
908
|
-
account: validated.account,
|
|
909
|
-
...validated.guardlist
|
|
910
|
-
});
|
|
911
|
-
result = { operation: "guardlist", op: validated.guardlist.op, result: guardlistResult.result };
|
|
887
|
+
const newState = toggleService(service);
|
|
888
|
+
result = { service, enabled: newState, reminder: existing.reminder };
|
|
912
889
|
break;
|
|
913
890
|
}
|
|
914
|
-
case "
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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 };
|
|
920
900
|
break;
|
|
921
901
|
}
|
|
922
|
-
case "
|
|
923
|
-
const
|
|
924
|
-
|
|
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 };
|
|
925
911
|
break;
|
|
926
912
|
}
|
|
927
|
-
case "
|
|
928
|
-
const
|
|
929
|
-
|
|
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 };
|
|
930
922
|
break;
|
|
931
923
|
}
|
|
932
|
-
case "
|
|
933
|
-
const
|
|
934
|
-
|
|
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;
|
|
935
932
|
break;
|
|
936
933
|
}
|
|
937
934
|
default:
|
|
938
|
-
throw new Error(`Unknown
|
|
935
|
+
throw new Error(`Unknown config_operation action: ${action}`);
|
|
939
936
|
}
|
|
940
937
|
return {
|
|
941
|
-
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
938
|
+
content: [{ type: "text", text: JSON.stringify({ result }) }],
|
|
942
939
|
structuredContent: { result },
|
|
943
940
|
};
|
|
944
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
|
+
}
|
|
945
1315
|
async function handleGuard2File(args) {
|
|
946
1316
|
const validated = strictParse(Guard2File_InputSchema, args, "guard2file input");
|
|
947
1317
|
const env = getEnvConfig(validated.env);
|
|
@@ -980,6 +1350,24 @@ async function handleMachineNode2File(args) {
|
|
|
980
1350
|
const env = getEnvConfig(validated.env);
|
|
981
1351
|
try {
|
|
982
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
|
+
}
|
|
983
1371
|
const result = {
|
|
984
1372
|
result: {
|
|
985
1373
|
status: "success",
|
|
@@ -987,10 +1375,12 @@ async function handleMachineNode2File(args) {
|
|
|
987
1375
|
file_path: resolve(validated.file_path),
|
|
988
1376
|
format: validated.format || "json",
|
|
989
1377
|
machine_object: validated.machine,
|
|
990
|
-
node_count: 0,
|
|
991
1378
|
},
|
|
992
1379
|
},
|
|
993
1380
|
};
|
|
1381
|
+
if (node_count !== undefined) {
|
|
1382
|
+
result.result.data.node_count = node_count;
|
|
1383
|
+
}
|
|
994
1384
|
return {
|
|
995
1385
|
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
996
1386
|
structuredContent: result,
|
|
@@ -1020,9 +1410,19 @@ async function main() {
|
|
|
1020
1410
|
else {
|
|
1021
1411
|
console.error("Schema files not available. Run 'npm run generate:schemas' to generate them.");
|
|
1022
1412
|
}
|
|
1413
|
+
if (isProjectServiceEnabled()) {
|
|
1414
|
+
registerSuccessHook((result, context) => {
|
|
1415
|
+
if (context?.operation_type && context?.data) {
|
|
1416
|
+
projectObserve(context.operation_type, context.data, result);
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
console.error("ProjectService enabled — object graph observe active");
|
|
1420
|
+
}
|
|
1421
|
+
const activeServices = listServices().filter((s) => s.enabled).map((s) => s.name);
|
|
1422
|
+
console.error(`Phase 2 active services: ${activeServices.join(", ") || "none"}`);
|
|
1023
1423
|
reg("onchain_operations", {
|
|
1024
1424
|
title: "⛓️ On-chain Operations",
|
|
1025
|
-
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).",
|
|
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.",
|
|
1026
1426
|
inputSchema: OnchainOperationsSchema,
|
|
1027
1427
|
outputSchema: CallOutputSchema,
|
|
1028
1428
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
@@ -1030,31 +1430,31 @@ async function main() {
|
|
|
1030
1430
|
}, handleOnchainOperations);
|
|
1031
1431
|
reg("account_operation", {
|
|
1032
1432
|
title: "🔒 LOCAL ONLY: Account - Wallet Management",
|
|
1033
|
-
description: "🔒 100% LOCAL, NEVER ON-CHAIN 🔒 Manage WoWok accounts locally on device: generate, suspend, resume, faucet-test, operate assets, sign data, etc.",
|
|
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.",
|
|
1034
1434
|
inputSchema: AccountOperationSchema,
|
|
1035
1435
|
outputSchema: AccountOperationOutputWrappedSchema,
|
|
1036
1436
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1037
1437
|
_meta: createToolMeta("operation", ["account", "local", "private", "wallet", "off-chain"]),
|
|
1038
|
-
}, handleAccountOperation);
|
|
1438
|
+
}, handleAccountOperation, statusErrorShape);
|
|
1039
1439
|
reg("local_mark_operation", {
|
|
1040
1440
|
title: "🔒 LOCAL ONLY: LocalMark - Address Book Management",
|
|
1041
|
-
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.",
|
|
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.",
|
|
1042
1442
|
inputSchema: LocalMarkOperationSchema,
|
|
1043
1443
|
outputSchema: LocalMarkOperationOutputWrappedSchema,
|
|
1044
1444
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1045
1445
|
_meta: createToolMeta("operation", ["mark", "local", "private", "address-book", "off-chain"]),
|
|
1046
|
-
}, handleMarkOperation);
|
|
1446
|
+
}, handleMarkOperation, statusErrorShape);
|
|
1047
1447
|
reg("local_info_operation", {
|
|
1048
1448
|
title: "🔒 LOCAL ONLY: LocalInfo - Private Data Management",
|
|
1049
|
-
description: "100% LOCAL, NEVER ON-CHAIN 🔒 Manage sensitive personal information stored ONLY on your device: delivery addresses, phone numbers, contacts.",
|
|
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.",
|
|
1050
1450
|
inputSchema: LocalInfoOperationSchema,
|
|
1051
1451
|
outputSchema: LocalInfoOperationOutputWrappedSchema,
|
|
1052
1452
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
1053
1453
|
_meta: createToolMeta("operation", ["info", "local", "private", "data-management", "off-chain"]),
|
|
1054
|
-
}, handleInfoOperation);
|
|
1454
|
+
}, handleInfoOperation, statusErrorShape);
|
|
1055
1455
|
reg("wip_file", {
|
|
1056
1456
|
title: "🤝 Witness Immutable Promise File Operations",
|
|
1057
|
-
description: "generate (create WIP files from markdown and images), verify (integrity check), sign (add signatures), or wip2html (convert to HTML).",
|
|
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.",
|
|
1058
1458
|
inputSchema: WipOperationsSchema,
|
|
1059
1459
|
outputSchema: z.object({
|
|
1060
1460
|
result: WipOperationOutputSchema,
|
|
@@ -1064,28 +1464,28 @@ async function main() {
|
|
|
1064
1464
|
}, handleWipOperations);
|
|
1065
1465
|
reg("messenger_operation", {
|
|
1066
1466
|
title: "💬 Messenger Operations",
|
|
1067
|
-
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.",
|
|
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.",
|
|
1068
1468
|
inputSchema: MessengerOperationInputSchema,
|
|
1069
1469
|
outputSchema: MessengerOperationOutputSchema,
|
|
1070
1470
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
1071
1471
|
_meta: createToolMeta("operation", ["messenger", "message", "file", "wts", "blacklist", "friendslist", "guardlist", "settings", "proof", "communication"]),
|
|
1072
|
-
}, handleMessengerOperation);
|
|
1472
|
+
}, handleMessengerOperation, operationErrorShape, 30000);
|
|
1073
1473
|
reg("guard2file", {
|
|
1074
1474
|
title: "📄 Guard to File - Export Guard Definition",
|
|
1075
|
-
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.",
|
|
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.",
|
|
1076
1476
|
inputSchema: Guard2File_InputSchema,
|
|
1077
1477
|
outputSchema: Guard2File_OutputWrappedSchema,
|
|
1078
1478
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1079
1479
|
_meta: createToolMeta("generate file", ["guard", "export", "file", "json", "markdown", "on-chain"]),
|
|
1080
|
-
}, handleGuard2File);
|
|
1480
|
+
}, handleGuard2File, strictStatusErrorShape);
|
|
1081
1481
|
reg("machineNode2file", {
|
|
1082
1482
|
title: "⚙️ Machine Node to File - Export Machine Node Definition",
|
|
1083
|
-
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.",
|
|
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.",
|
|
1084
1484
|
inputSchema: MachineNode2File_InputSchema,
|
|
1085
1485
|
outputSchema: MachineNode2File_OutputWrappedSchema,
|
|
1086
1486
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1087
1487
|
_meta: createToolMeta("generate file", ["machine", "export", "file", "json", "markdown", "on-chain", "workflow"]),
|
|
1088
|
-
}, handleMachineNode2File);
|
|
1488
|
+
}, handleMachineNode2File, strictStatusErrorShape);
|
|
1089
1489
|
reg("query_toolkit", {
|
|
1090
1490
|
title: "🔍 Data Query Toolkit",
|
|
1091
1491
|
description: "WOWOK data query toolkit — 9 query types covering local device data and on-chain blockchain data:\n\n"
|
|
@@ -1100,10 +1500,12 @@ async function main() {
|
|
|
1100
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"
|
|
1101
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"
|
|
1102
1502
|
+ "9. onchain_received — Query objects (Payments, Tokens, NFTs) received by a specific object. Supports pagination and type filter.\n\n"
|
|
1103
|
-
+ "For dynamic table data queries (pagination, table items), use the 'onchain_table_data' tool
|
|
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.",
|
|
1104
1505
|
inputSchema: WatchQueryOperationsSchema,
|
|
1105
1506
|
outputSchema: z.object({
|
|
1106
|
-
result: z.
|
|
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"),
|
|
1107
1509
|
}),
|
|
1108
1510
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
1109
1511
|
_meta: createToolMeta("query", ["watch", "query", "on-chain", "local", "events", "objects", "tokens", "balance", "profile"]),
|
|
@@ -1122,7 +1524,8 @@ async function main() {
|
|
|
1122
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"
|
|
1123
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"
|
|
1124
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"
|
|
1125
|
-
+ "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
|
|
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.",
|
|
1126
1529
|
inputSchema: OnchainTableDataSchema,
|
|
1127
1530
|
outputSchema: OnchainTableDataResultSchema,
|
|
1128
1531
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
@@ -1130,7 +1533,7 @@ async function main() {
|
|
|
1130
1533
|
}, handleOnchainTableData);
|
|
1131
1534
|
reg("onchain_events", {
|
|
1132
1535
|
title: "📅 Watch WoWok On-chain Events",
|
|
1133
|
-
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.",
|
|
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.",
|
|
1134
1537
|
inputSchema: OnchainEventsInputSchema,
|
|
1135
1538
|
outputSchema: OnchainEventsResultSchema,
|
|
1136
1539
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
@@ -1155,19 +1558,8 @@ async function main() {
|
|
|
1155
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" +
|
|
1156
1559
|
" 'search' - Find schemas by keyword, matching name/title/description. Use with the 'query' param.\n" +
|
|
1157
1560
|
" 'list_operations' - Show only on-chain operation schemas (prefixed 'onchain_operations_'). Narrower than 'list'.",
|
|
1158
|
-
inputSchema:
|
|
1159
|
-
|
|
1160
|
-
.describe("Action to perform: 'list' to see all available schemas, 'get' to retrieve a specific input schema, 'get_output' to retrieve a tool's output schema, 'search' to find schemas by keyword, 'list_operations' to list all on-chain operations"),
|
|
1161
|
-
name: z.string().optional().describe("Schema/tool name for 'get'/'get_output' action (e.g., 'onchain_operations', 'account_operation', 'onchain_operations_permission')"),
|
|
1162
|
-
query: z.string().optional().describe("Search query for 'search' action"),
|
|
1163
|
-
}),
|
|
1164
|
-
outputSchema: z.object({
|
|
1165
|
-
success: z.boolean().describe("Whether the request was successful"),
|
|
1166
|
-
action: z.string().describe("The action that was performed"),
|
|
1167
|
-
data: z.any().describe("Response data - JSON Schema object for 'get'/'get_output', array of schema info for 'list'/'search'/'list_operations'"),
|
|
1168
|
-
message: z.string().describe("Human-readable message describing the result"),
|
|
1169
|
-
suggestions: z.array(z.string()).optional().describe("Suggested next steps or alternatives"),
|
|
1170
|
-
}),
|
|
1561
|
+
inputSchema: SchemaQueryInputSchema,
|
|
1562
|
+
outputSchema: SchemaQueryOutputSchema,
|
|
1171
1563
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1172
1564
|
_meta: createToolMeta("schema", ["schema", "json-schema", "types", "structure", "validation", "reference"]),
|
|
1173
1565
|
}, async (args) => {
|
|
@@ -1285,6 +1677,85 @@ async function main() {
|
|
|
1285
1677
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
1286
1678
|
_meta: createToolMeta("operation", ["bridge", "cross-chain", "evm", "ethereum", "wow", "transfer", "rpc"]),
|
|
1287
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);
|
|
1288
1759
|
const transport = new StdioServerTransport();
|
|
1289
1760
|
await server.connect(transport);
|
|
1290
1761
|
process.on("SIGINT", async () => {
|