@wowok/agent-mcp 2.6.0 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +5 -3
  2. package/dist/customer/info-puzzle.d.ts +1 -1
  3. package/dist/customer/info-puzzle.js +4 -2
  4. package/dist/customer/risk-assessment.js +26 -4
  5. package/dist/customer/types.d.ts +2 -0
  6. package/dist/examples/guard-template-balance-check.json +38 -0
  7. package/dist/examples/guard-template-time-lock.json +39 -0
  8. package/dist/examples/machine-template-7node-rental.json +114 -0
  9. package/dist/examples/rental-ziroom-machine-create.json +137 -0
  10. package/dist/examples/rental-ziroom-permission-create.json +35 -0
  11. package/dist/examples/rental-ziroom-service-create.json +80 -0
  12. package/dist/examples/retail-myshop-service-create.json +88 -0
  13. package/dist/extensions/capability-manifest.d.ts +125 -0
  14. package/dist/extensions/capability-manifest.js +594 -0
  15. package/dist/extensions/constraint-registry.d.ts +24 -0
  16. package/dist/extensions/constraint-registry.js +196 -0
  17. package/dist/extensions/index.d.ts +12 -0
  18. package/dist/extensions/index.js +6 -0
  19. package/dist/extensions/metric-registry.d.ts +26 -0
  20. package/dist/extensions/metric-registry.js +257 -0
  21. package/dist/extensions/mode-evaluator.d.ts +15 -0
  22. package/dist/extensions/mode-evaluator.js +170 -0
  23. package/dist/extensions/modes.d.ts +2 -0
  24. package/dist/extensions/modes.js +493 -0
  25. package/dist/extensions/registry.d.ts +50 -0
  26. package/dist/extensions/registry.js +662 -0
  27. package/dist/extensions/types.d.ts +219 -0
  28. package/dist/extensions/types.js +1 -0
  29. package/dist/index.js +50 -0
  30. package/dist/knowledge/deployment-scanner.d.ts +3 -0
  31. package/dist/knowledge/deployment-scanner.js +64 -3
  32. package/dist/knowledge/fund-layer.d.ts +72 -0
  33. package/dist/knowledge/fund-layer.js +420 -0
  34. package/dist/knowledge/guard-render.d.ts +57 -0
  35. package/dist/knowledge/guard-render.js +700 -0
  36. package/dist/knowledge/guard-risk.d.ts +13 -0
  37. package/dist/knowledge/guard-risk.js +57 -0
  38. package/dist/knowledge/guard-submission-prompt.d.ts +31 -0
  39. package/dist/knowledge/guard-submission-prompt.js +171 -0
  40. package/dist/knowledge/guard-templates.js +278 -0
  41. package/dist/knowledge/machine-ledger.js +1 -1
  42. package/dist/knowledge/machine-render.d.ts +41 -0
  43. package/dist/knowledge/machine-render.js +565 -0
  44. package/dist/knowledge/machine-templates.js +24 -5
  45. package/dist/knowledge/reward-confirm.js +2 -2
  46. package/dist/knowledge/reward-puzzle.js +1 -1
  47. package/dist/knowledge/reward-risk.js +9 -9
  48. package/dist/knowledge/reward-templates.js +2 -2
  49. package/dist/knowledge/service-confirm.d.ts +15 -6
  50. package/dist/knowledge/service-confirm.js +119 -11
  51. package/dist/knowledge/service-context.js +1 -1
  52. package/dist/knowledge/service-ledger.js +1 -1
  53. package/dist/knowledge/service-risk.d.ts +1 -1
  54. package/dist/knowledge/service-risk.js +3 -3
  55. package/dist/knowledge/service-templates.js +2 -2
  56. package/dist/knowledge/service-translation.d.ts +1 -1
  57. package/dist/knowledge/service-translation.js +7 -7
  58. package/dist/knowledge/tool-constraints.js +6 -2
  59. package/dist/project/deployment-bridge.d.ts +1 -1
  60. package/dist/project/deployment-bridge.js +31 -7
  61. package/dist/project/deployment-doc.d.ts +3 -0
  62. package/dist/project/deployment-doc.js +76 -14
  63. package/dist/project/edit-planner.d.ts +123 -0
  64. package/dist/project/edit-planner.js +1371 -0
  65. package/dist/project/evaluation.d.ts +2 -0
  66. package/dist/project/evaluation.js +873 -88
  67. package/dist/project/graph-builder.d.ts +4 -1
  68. package/dist/project/graph-builder.js +132 -62
  69. package/dist/project/graph.d.ts +1 -0
  70. package/dist/project/handlers.d.ts +317 -6
  71. package/dist/project/handlers.js +1171 -19
  72. package/dist/project/stage-gate.d.ts +4 -0
  73. package/dist/project/stage-gate.js +64 -5
  74. package/dist/project/task-tracker.d.ts +26 -0
  75. package/dist/project/task-tracker.js +78 -0
  76. package/dist/safety/preview.js +16 -0
  77. package/dist/schema/call/allocation.d.ts +16 -16
  78. package/dist/schema/call/allocation.js +2 -2
  79. package/dist/schema/call/arbitration.js +19 -6
  80. package/dist/schema/call/base.d.ts +21 -13
  81. package/dist/schema/call/base.js +27 -6
  82. package/dist/schema/call/bridge.d.ts +5 -5
  83. package/dist/schema/call/bridge.js +3 -1
  84. package/dist/schema/call/contact.js +2 -2
  85. package/dist/schema/call/demand.d.ts +23 -31
  86. package/dist/schema/call/demand.js +2 -2
  87. package/dist/schema/call/guard.js +2 -2
  88. package/dist/schema/call/machine.d.ts +1976 -752
  89. package/dist/schema/call/machine.js +50 -4
  90. package/dist/schema/call/order.d.ts +149 -228
  91. package/dist/schema/call/order.js +4 -3
  92. package/dist/schema/call/payment.d.ts +183 -3
  93. package/dist/schema/call/payment.js +21 -3
  94. package/dist/schema/call/permission.js +2 -2
  95. package/dist/schema/call/personal.d.ts +241 -52
  96. package/dist/schema/call/progress.d.ts +53 -61
  97. package/dist/schema/call/progress.js +18 -4
  98. package/dist/schema/call/repository.d.ts +23 -31
  99. package/dist/schema/call/repository.js +2 -2
  100. package/dist/schema/call/reward.js +3 -3
  101. package/dist/schema/call/semantic.d.ts +1 -1
  102. package/dist/schema/call/semantic.js +37 -2
  103. package/dist/schema/call/service.d.ts +275 -127
  104. package/dist/schema/call/service.js +89 -13
  105. package/dist/schema/call/treasury.js +3 -3
  106. package/dist/schema/common/index.d.ts +13 -2
  107. package/dist/schema/common/index.js +80 -15
  108. package/dist/schema/local/index.d.ts +32 -35
  109. package/dist/schema/local/index.js +28 -6
  110. package/dist/schema/messenger/index.d.ts +274 -46
  111. package/dist/schema/operations.d.ts +1264 -544
  112. package/dist/schema/operations.js +65 -7
  113. package/dist/schema/project/index.d.ts +2846 -167
  114. package/dist/schema/project/index.js +570 -16
  115. package/dist/schema/query/index.d.ts +922 -349
  116. package/dist/schema/query/index.js +205 -42
  117. package/dist/schema/schema-query/index.d.ts +65 -3
  118. package/dist/schema/schema-query/index.js +38 -5
  119. package/dist/schema/utils/node-parser.js +20 -4
  120. package/dist/schema/utils/object-type-utils.d.ts +12 -0
  121. package/dist/schema/utils/object-type-utils.js +35 -0
  122. package/dist/schema/utils/permission-machine-check.d.ts +49 -0
  123. package/dist/schema/utils/permission-machine-check.js +121 -0
  124. package/dist/schema/utils/skills-recommendation.d.ts +2 -0
  125. package/dist/schema/utils/skills-recommendation.js +76 -0
  126. package/dist/schema-query/index.d.ts +20 -1
  127. package/dist/schema-query/index.js +306 -4
  128. package/dist/schemas/account_operation.output.json +7 -1
  129. package/dist/schemas/account_operation.schema.json +3 -3
  130. package/dist/schemas/bridge_operation.output.json +6 -0
  131. package/dist/schemas/bridge_operation.schema.json +1 -1
  132. package/dist/schemas/guard-templates.json +379 -0
  133. package/dist/schemas/guard2file.schema.json +1 -1
  134. package/dist/schemas/index.json +1 -1
  135. package/dist/schemas/local_info_operation.output.json +6 -0
  136. package/dist/schemas/local_mark_operation.output.json +7 -1
  137. package/dist/schemas/local_mark_operation.schema.json +1 -1
  138. package/dist/schemas/machineNode2file.schema.json +1 -1
  139. package/dist/schemas/messenger_operation.schema.json +4 -4
  140. package/dist/schemas/onchain_events.output.json +1 -1
  141. package/dist/schemas/onchain_operations.output.json +2820 -0
  142. package/dist/schemas/onchain_operations.schema.json +444 -330
  143. package/dist/schemas/onchain_operations_allocation.schema.json +37 -28
  144. package/dist/schemas/onchain_operations_arbitration.schema.json +16 -14
  145. package/dist/schemas/onchain_operations_contact.schema.json +10 -10
  146. package/dist/schemas/onchain_operations_demand.schema.json +10 -10
  147. package/dist/schemas/onchain_operations_gen_passport.schema.json +16 -16
  148. package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
  149. package/dist/schemas/onchain_operations_guard.schema.json +2 -2
  150. package/dist/schemas/onchain_operations_machine.schema.json +43 -35
  151. package/dist/schemas/onchain_operations_order.schema.json +72 -78
  152. package/dist/schemas/onchain_operations_payment.schema.json +141 -111
  153. package/dist/schemas/onchain_operations_permission.schema.json +3 -3
  154. package/dist/schemas/onchain_operations_personal.schema.json +7 -7
  155. package/dist/schemas/onchain_operations_progress.schema.json +9 -9
  156. package/dist/schemas/onchain_operations_proof.schema.json +8 -8
  157. package/dist/schemas/onchain_operations_repository.schema.json +10 -10
  158. package/dist/schemas/onchain_operations_reward.schema.json +14 -14
  159. package/dist/schemas/onchain_operations_service.schema.json +119 -48
  160. package/dist/schemas/onchain_operations_treasury.schema.json +11 -11
  161. package/dist/schemas/onchain_table_data.output.json +33 -25
  162. package/dist/schemas/onchain_table_data.schema.json +22 -21
  163. package/dist/schemas/project_operation.output.json +2194 -23
  164. package/dist/schemas/project_operation.schema.json +84 -6
  165. package/dist/schemas/query_toolkit.output.json +108 -80
  166. package/dist/schemas/query_toolkit.schema.json +12 -12
  167. package/dist/schemas/schema_query.output.json +70 -3
  168. package/dist/schemas/schema_query.schema.json +18 -3
  169. package/dist/schemas/wowok_buildin_info.output.json +81 -8
  170. package/dist/schemas/wowok_buildin_info.schema.json +46 -2
  171. package/dist/tools/handlers/local.js +20 -5
  172. package/dist/tools/handlers/onchain.js +594 -6
  173. package/dist/tools/handlers/project.js +76 -4
  174. package/dist/tools/handlers/query.js +27 -0
  175. package/dist/tools/handlers/schema-query.js +43 -1
  176. package/dist/tools/handlers/task-status.d.ts +170 -0
  177. package/dist/tools/handlers/task-status.js +55 -0
  178. package/dist/tools/handlers/wip.js +47 -1
  179. package/dist/tools/index.d.ts +8 -0
  180. package/dist/tools/index.js +387 -12
  181. package/dist/tools/retry.d.ts +8 -0
  182. package/dist/tools/retry.js +85 -0
  183. package/dist/tools/wip-deploy-assist.d.ts +28 -0
  184. package/dist/tools/wip-deploy-assist.js +278 -0
  185. package/package.json +2 -2
  186. package/dist/schemas/guard-node-examples.md +0 -199
@@ -24,6 +24,7 @@ import { handleBridgeOperations } from "./handlers/bridge.js";
24
24
  import { handleProjectOperation } from "./handlers/project.js";
25
25
  import { handleConfigOperation } from "./handlers/config.js";
26
26
  import { handleTrustScore } from "./handlers/trust.js";
27
+ import { handleQueryTaskStatus, QueryTaskStatusInputSchema, QueryTaskStatusOutputSchema } from "./handlers/task-status.js";
27
28
  import { applyOnchainRules } from "./rules-hook.js";
28
29
  import { createToolMeta, OnchainOperationsSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, WipOperationsSchema, MessengerOperationInputSchema, Guard2File_InputSchema, MachineNode2File_InputSchema, WatchQueryOperationsSchema, WatchQueryOperationsResultSchema, OnchainTableDataSchema, OnchainEventsInputSchema, ProtocolInfoQuerySchema, SchemaQueryInputSchema, BridgeOperationsSchema, ProjectOperationInputSchema, ConfigOperationInputSchema, TrustScoreInputSchema, CallOutputSchema, AccountOperationOutputWrappedSchema, LocalMarkOperationOutputWrappedSchema, LocalInfoOperationOutputWrappedSchema, WipOperationOutputSchema, MessengerOperationOutputSchema, Guard2File_OutputWrappedSchema, MachineNode2File_OutputWrappedSchema, OnchainTableDataResultSchema, OnchainEventsResultSchema, ProtocolInfoResultSchema, SchemaQueryOutputSchema, BridgeCallOutputSchema, ProjectOperationOutputSchema, ConfigOperationOutputSchema, TrustScoreOutputSchema, } from "../schema/index.js";
29
30
  export const TOOL_REGISTRY = [
@@ -84,7 +85,7 @@ export const TOOL_REGISTRY = [
84
85
  handler: handleWipOperations,
85
86
  config: {
86
87
  title: "🤝 Witness Immutable Promise File Operations",
87
- 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.",
88
+ description: "generate (create WIP files from markdown and images), verify (integrity check), sign (add signatures), or wip2html (convert to HTML).\n\n⚠️ IMPORTANT — On-chain WIP URL requirement: When using a WIP file URL in `service.sales[].wip` (stored on-chain), the URL MUST be publicly reachable. Local file paths (e.g., 'C:\\\\path\\\\file.wip' or '/home/user/file.wip') are NOT acceptable on-chain — they only work locally and will fail verification for buyers.\n\nDeployment options for the .wip file:\n • GitHub Pages: https://raw.githubusercontent.com/<user>/<repo>/<branch>/<file>.wip\n • IPFS: https://ipfs.io/ipfs/<CID> or https://cloudflare-ipfs.com/ipfs/<CID> (upload via pinata.cloud)\n • User's own static website URL\n\nUse type='generate' to create the WIP file first, upload it to any of the above, then use the resulting URL in service.sales[].wip.\n\n💡 Schema hint: Use schema_query with action='get' and name='wip_file' to retrieve the exact parameter schema before calling.",
88
89
  inputSchema: WipOperationsSchema,
89
90
  outputSchema: z.object({
90
91
  result: WipOperationOutputSchema,
@@ -360,6 +361,28 @@ export const TOOL_REGISTRY = [
360
361
  _meta: createToolMeta("trust", ["trust", "score", "risk", "service", "merchant", "reputation", "safety", "evaluate"]),
361
362
  },
362
363
  },
364
+ {
365
+ name: "query_task_status",
366
+ handler: handleQueryTaskStatus,
367
+ config: {
368
+ title: "📊 Task Status - Async Operation Tracking",
369
+ description: "Query the status of a long-running async task (created by build_graph or evaluate_project " +
370
+ "with async_mode=true). Returns progress percentage, current status, and the final result " +
371
+ "when completed.\n\n" +
372
+ "Tasks are ephemeral (retained 5 minutes after completion, in-memory only).\n\n" +
373
+ "Usage:\n" +
374
+ " • Pass task_id to query a single task's status.\n" +
375
+ " • Omit task_id to list all recent tasks (max 50, most recent first).\n" +
376
+ " • Pass project_id (with task_id omitted) to filter by project.\n\n" +
377
+ "This tool is read-only and always safe to call. Use it to check if a long-running " +
378
+ "operation (e.g. build_graph with enablePotential=true) has completed.\n\n" +
379
+ "💡 Schema hint: Use schema_query with action='get' and name='query_task_status' to retrieve the exact parameter schema.",
380
+ inputSchema: QueryTaskStatusInputSchema,
381
+ outputSchema: QueryTaskStatusOutputSchema,
382
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
383
+ _meta: createToolMeta("task", ["task", "status", "async", "progress", "background", "tracker"]),
384
+ },
385
+ },
363
386
  ];
364
387
  export const TOOL_REGISTRY_MAP = new Map(TOOL_REGISTRY.map(t => [t.name, t]));
365
388
  const SUB_TOOL_NAMES = TOOL_REGISTRY.map(t => t.name);
@@ -439,10 +462,10 @@ const WOWOK_TOOL_DESCRIPTION = [
439
462
  "Projects are the core organizing unit for all WoWok workflows. The policy is context-aware:",
440
463
  "",
441
464
  "CASE 1 — COMPLEX REQUIREMENT (user wants to build/deploy a full service):",
442
- " Examples: '搭建旅行地陪服务', '开一个玩具店', '创建租赁服务'",
465
+ " Examples: 'build a travel guide service', 'open a toy store', 'create a rental service'",
443
466
  " → You MUST auto-create a project FIRST, then create objects.",
444
467
  " → Check for similar existing projects first: project_operation action='list_projects'",
445
- " If similar projects exist (same industry), remind the user: '发现类似项目 X, 是否复用或新建?'",
468
+ " If similar projects exist (same industry), remind the user: 'Found similar project X. Reuse or create new?'",
446
469
  " → Workflow:",
447
470
  " 1. project_operation action='create_project' (perspective='producer', project_industry=<best match>)",
448
471
  " 2. Create on-chain objects via onchain_operations with env.project='<prefix>' (auto-tags + auto-associates to SQLite project)",
@@ -452,11 +475,11 @@ const WOWOK_TOOL_DESCRIPTION = [
452
475
  " 6. Report results, fix critical findings, then publish Service",
453
476
  "",
454
477
  "CASE 2 — SINGLE OBJECT CREATION (user wants one specific object):",
455
- " Examples: '创建一个Permission', '添加一个Contact', '建一个Guard'",
478
+ " Examples: 'create a Permission', 'add a Contact', 'build a Guard'",
456
479
  " → Do NOT auto-create a project. If the user has an existing project, create with env.project='<prefix>' to auto-associate.",
457
480
  " → If no existing project, after creation, REMIND the user:",
458
- " '此对象已创建。建议将其加入一个项目以便管理: project_operation action=\"add_object\"",
459
- " 如还没有项目, 可用 action=\"create_project\" 新建。现有项目: [list projects if any]'",
481
+ " 'This object has been created. Consider adding it to a project for management: project_operation action=\"add_object\"",
482
+ " If no project exists yet, use action=\"create_project\" to create one. Existing projects: [list projects if any]'",
460
483
  " → If the user then says 'yes, create a project' or 'add to project X', proceed accordingly.",
461
484
  "",
462
485
  "CASE 3 — CONSUMER FLOW (user wants to buy/evaluate a service):",
@@ -478,12 +501,215 @@ const WOWOK_TOOL_DESCRIPTION = [
478
501
  " general → fallback for unclear industry",
479
502
  "═══════════════════════════════════════════════════════════════",
480
503
  ].join("\n");
481
- function formatZodErrors(error) {
504
+ function formatZodErrors(error, input) {
505
+ return error.issues.map(issue => {
506
+ const path = issue.path.length > 0
507
+ ? issue.path.map(p => typeof p === "number" ? `[${p}]` : p).join(".").replace(".[", "[")
508
+ : "(root)";
509
+ const code = issue.code;
510
+ const message = issue.message;
511
+ let extras = "";
512
+ const issueAny = issue;
513
+ if (code === "invalid_type") {
514
+ const expected = issueAny.expected;
515
+ const received = issueAny.received;
516
+ if (typeof expected === "string" && typeof received === "string") {
517
+ extras = ` (expected: ${expected}; received: ${received})`;
518
+ }
519
+ }
520
+ else if (code === "invalid_literal" || code === "invalid_enum_value") {
521
+ const expected = issueAny.expected;
522
+ if (expected !== undefined) {
523
+ const expStr = typeof expected === "string" ? expected : JSON.stringify(expected);
524
+ extras = ` (expected: ${expStr.slice(0, 60)})`;
525
+ }
526
+ }
527
+ else if (code === "too_big" || code === "too_small") {
528
+ const maximum = issueAny.maximum ?? issueAny.minimum;
529
+ const origin = issueAny.origin;
530
+ if (maximum !== undefined && origin !== undefined) {
531
+ extras = ` (${origin}: ${maximum})`;
532
+ }
533
+ }
534
+ const receivedVal = extractValueAtPath(input, issue.path);
535
+ if (receivedVal !== undefined) {
536
+ const valStr = typeof receivedVal === "string"
537
+ ? `"${receivedVal.slice(0, 60)}"`
538
+ : typeof receivedVal === "object"
539
+ ? JSON.stringify(receivedVal).slice(0, 60)
540
+ : String(receivedVal);
541
+ if (!extras.includes("received:")) {
542
+ extras += ` (received value: ${valStr})`;
543
+ }
544
+ }
545
+ return `${path} [${code}]: ${message}${extras}`;
546
+ });
547
+ }
548
+ function generateSuggestion(code, issue, receivedValue) {
549
+ const issueAny = issue;
550
+ switch (code) {
551
+ case "invalid_type": {
552
+ const expected = issueAny.expected;
553
+ const received = issueAny.received;
554
+ if (expected === "number" && typeof receivedValue === "string") {
555
+ return `Convert to number: ${Number(receivedValue)}`;
556
+ }
557
+ if (expected === "string") {
558
+ return `Wrap in quotes or call String(...)`;
559
+ }
560
+ if (expected === "array") {
561
+ return `Wrap in array: [${JSON.stringify(receivedValue)}]`;
562
+ }
563
+ if (expected === "object") {
564
+ return `Provide an object, not a primitive`;
565
+ }
566
+ return `Convert value to ${expected ?? "the expected type"}`;
567
+ }
568
+ case "invalid_enum_value": {
569
+ const options = issueAny.options;
570
+ const optionsStr = Array.isArray(options)
571
+ ? options.map((v) => JSON.stringify(v)).join(" | ")
572
+ : String(options);
573
+ return `Use one of: ${optionsStr}`;
574
+ }
575
+ case "invalid_literal": {
576
+ const expected = issueAny.expected;
577
+ return `Use the exact value: ${JSON.stringify(expected)}`;
578
+ }
579
+ case "too_small": {
580
+ const minimum = issueAny.minimum;
581
+ const type = issueAny.type;
582
+ if (type === "array") {
583
+ return `Add at least ${minimum} element(s) to the array`;
584
+ }
585
+ if (type === "string") {
586
+ return `String must be at least ${minimum} character(s) long`;
587
+ }
588
+ if (type === "number") {
589
+ return `Use a value >= ${minimum}`;
590
+ }
591
+ return `Value must be >= ${minimum}`;
592
+ }
593
+ case "too_big": {
594
+ const maximum = issueAny.maximum;
595
+ const type = issueAny.type;
596
+ if (type === "array") {
597
+ return `Reduce array to at most ${maximum} element(s)`;
598
+ }
599
+ if (type === "string") {
600
+ return `Shorten string to at most ${maximum} character(s)`;
601
+ }
602
+ if (type === "number") {
603
+ return `Use a value <= ${maximum}`;
604
+ }
605
+ return `Value must be <= ${maximum}`;
606
+ }
607
+ case "unrecognized_keys": {
608
+ const keys = issueAny.keys;
609
+ return `Remove unknown field(s): ${(keys ?? []).join(", ")}. Check the schema for valid field names.`;
610
+ }
611
+ case "invalid_union": {
612
+ return `Value does not match any of the union variants. Check the schema for valid shapes.`;
613
+ }
614
+ case "invalid_string": {
615
+ const validation = issueAny.validation;
616
+ if (validation === "url")
617
+ return `Provide a valid URL string`;
618
+ if (validation === "email")
619
+ return `Provide a valid email string`;
620
+ if (validation === "uuid")
621
+ return `Provide a valid UUID string`;
622
+ if (validation === "regex")
623
+ return `String does not match the required pattern`;
624
+ return `Provide a valid string matching the validation: ${validation ?? "unknown"}`;
625
+ }
626
+ case "invalid_date": {
627
+ return `Provide a valid Date object or ISO date string`;
628
+ }
629
+ case "not_finite": {
630
+ return `Use a finite number (not Infinity or NaN)`;
631
+ }
632
+ case "invalid_arguments": {
633
+ return `Arguments do not match the expected schema`;
634
+ }
635
+ case "invalid_return_type": {
636
+ return `Return type does not match the expected schema`;
637
+ }
638
+ case "custom": {
639
+ return `Custom validation failed — see the field's description in the schema`;
640
+ }
641
+ default: {
642
+ return `Fix the value at '${issue.path.join(".")}' based on the schema`;
643
+ }
644
+ }
645
+ }
646
+ function formatZodErrorsStructured(error, input) {
482
647
  return error.issues.map(issue => {
483
- const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
484
- return `${path}: ${issue.message}`;
648
+ const path = issue.path.length > 0
649
+ ? issue.path.map(p => typeof p === "number" ? `[${p}]` : p).join(".").replace(".[", "[")
650
+ : "(root)";
651
+ const code = issue.code;
652
+ const message = issue.message;
653
+ const issueAny = issue;
654
+ let expected;
655
+ if (code === "invalid_type") {
656
+ const exp = issueAny.expected;
657
+ const rec = issueAny.received;
658
+ if (typeof exp === "string" && typeof rec === "string") {
659
+ expected = exp;
660
+ }
661
+ }
662
+ else if (code === "invalid_literal") {
663
+ const exp = issueAny.expected;
664
+ if (exp !== undefined) {
665
+ expected = typeof exp === "string" ? exp : JSON.stringify(exp);
666
+ }
667
+ }
668
+ else if (code === "invalid_enum_value") {
669
+ const options = issueAny.options;
670
+ if (Array.isArray(options)) {
671
+ expected = options.map((v) => JSON.stringify(v)).join(" | ");
672
+ }
673
+ }
674
+ else if (code === "too_big" || code === "too_small") {
675
+ const threshold = issueAny.maximum ?? issueAny.minimum;
676
+ if (threshold !== undefined) {
677
+ expected = String(threshold);
678
+ }
679
+ }
680
+ const receivedVal = extractValueAtPath(input, issue.path);
681
+ const suggestion = generateSuggestion(code, issue, receivedVal);
682
+ return {
683
+ path,
684
+ code,
685
+ message,
686
+ expected,
687
+ received_value: receivedVal,
688
+ suggestion,
689
+ };
485
690
  });
486
691
  }
692
+ function extractValueAtPath(input, path) {
693
+ if (input === undefined || input === null || path.length === 0) {
694
+ return undefined;
695
+ }
696
+ let current = input;
697
+ for (const key of path) {
698
+ if (current === undefined || current === null)
699
+ return undefined;
700
+ if (typeof key === "number") {
701
+ if (!Array.isArray(current))
702
+ return undefined;
703
+ current = current[key];
704
+ }
705
+ else {
706
+ if (typeof current !== "object")
707
+ return undefined;
708
+ current = current[key];
709
+ }
710
+ }
711
+ return current;
712
+ }
487
713
  function checkUnknownFields(schema, input) {
488
714
  let innerSchema = schema;
489
715
  while (true) {
@@ -518,6 +744,109 @@ function isSchemaValidationError(message) {
518
744
  message.includes("Invalid input") ||
519
745
  message.includes("Required"));
520
746
  }
747
+ function buildSchemaPreview(schema, toolName, data) {
748
+ try {
749
+ const lines = [`Schema preview for ${toolName}:`];
750
+ let topProps;
751
+ let topRequired = [];
752
+ let topDescription = "";
753
+ if (schema.properties && typeof schema.properties === "object") {
754
+ topProps = schema.properties;
755
+ topRequired = Array.isArray(schema.required) ? schema.required : [];
756
+ topDescription = typeof schema.description === "string" ? schema.description : "";
757
+ }
758
+ else if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
759
+ const variants = (schema.oneOf ?? schema.anyOf);
760
+ for (const v of variants) {
761
+ if (v && typeof v === "object") {
762
+ const vo = v;
763
+ if (vo.properties && typeof vo.properties === "object") {
764
+ topProps = vo.properties;
765
+ topRequired = Array.isArray(vo.required) ? vo.required : [];
766
+ topDescription = typeof vo.description === "string" ? vo.description : "";
767
+ break;
768
+ }
769
+ }
770
+ }
771
+ if (!topProps) {
772
+ lines.push(` (discriminated union with ${variants.length} variants — see structuredContent for full schema)`);
773
+ return lines.join("\n");
774
+ }
775
+ }
776
+ if (topDescription && topDescription.length > 0 && topDescription.length < 200) {
777
+ lines.push(` ${topDescription}`);
778
+ }
779
+ if (!topProps) {
780
+ lines.push(" (no properties available — see structuredContent for full schema)");
781
+ return lines.join("\n");
782
+ }
783
+ const requiredSet = new Set(topRequired);
784
+ const requiredList = topRequired.length > 0 ? topRequired.join(", ") : "(none)";
785
+ const optionalList = Object.keys(topProps).filter(k => !requiredSet.has(k)).join(", ");
786
+ lines.push(`Required: ${requiredList}`);
787
+ if (optionalList) {
788
+ lines.push(`Optional: ${optionalList}`);
789
+ }
790
+ lines.push("Fields:");
791
+ for (const [fieldName, fieldSchema] of Object.entries(topProps)) {
792
+ if (fieldSchema && typeof fieldSchema === "object") {
793
+ const f = fieldSchema;
794
+ const type = describeSchemaType(f);
795
+ const required = requiredSet.has(fieldName) ? "required" : "optional";
796
+ let desc = typeof f.description === "string" ? f.description : "";
797
+ if (desc.length > 120)
798
+ desc = desc.slice(0, 117) + "...";
799
+ let subFields = "";
800
+ if (f.properties && typeof f.properties === "object") {
801
+ const subProps = Object.keys(f.properties);
802
+ if (subProps.length > 0) {
803
+ subFields = ` { ${subProps.slice(0, 8).join(", ")}${subProps.length > 8 ? ", ..." : ""} }`;
804
+ }
805
+ }
806
+ if (f.items && typeof f.items === "object") {
807
+ const items = f.items;
808
+ const itemType = describeSchemaType(items);
809
+ subFields = ` (array of ${itemType})`;
810
+ }
811
+ if (Array.isArray(f.enum)) {
812
+ subFields = ` (enum: ${f.enum.slice(0, 6).map(v => JSON.stringify(v)).join(", ")}${f.enum.length > 6 ? ", ..." : ""})`;
813
+ }
814
+ lines.push(` - ${fieldName} (${type}, ${required})${subFields}${desc ? ` — ${desc}` : ""}`);
815
+ }
816
+ }
817
+ if (toolName === "onchain_operations" && typeof data === "object" && data !== null) {
818
+ const opType = data.operation_type;
819
+ if (typeof opType === "string") {
820
+ lines.push(``);
821
+ lines.push(`operation_type-specific schema: onchain_operations_${opType}`);
822
+ lines.push(`(Use schema_query with action='get' and name='onchain_operations_${opType}' for the full sub-schema.)`);
823
+ }
824
+ }
825
+ return lines.join("\n");
826
+ }
827
+ catch {
828
+ return `Schema preview for ${toolName}: (unable to build preview — see structuredContent for full schema)`;
829
+ }
830
+ }
831
+ function describeSchemaType(schema) {
832
+ if (typeof schema.type === "string")
833
+ return schema.type;
834
+ if (Array.isArray(schema.type))
835
+ return schema.type.join("|");
836
+ if (schema.$ref)
837
+ return "$ref";
838
+ if (Array.isArray(schema.oneOf))
839
+ return "oneOf";
840
+ if (Array.isArray(schema.anyOf))
841
+ return "anyOf";
842
+ if (Array.isArray(schema.allOf))
843
+ return "allOf";
844
+ if (schema.enum)
845
+ return "enum";
846
+ if (schema.const)
847
+ return `const(${JSON.stringify(schema.const)})`;
848
+ return "object";
849
+ }
521
850
  export async function dispatchToolCall(name, args, options) {
522
851
  if (name === "wowok") {
523
852
  return handleWowok(args);
@@ -647,22 +976,52 @@ async function handleWowok(args) {
647
976
  if (!validationResult.success || unknownFields.length > 0) {
648
977
  const allErrors = [];
649
978
  if (!validationResult.success) {
650
- allErrors.push(...formatZodErrors(validationResult.error));
979
+ allErrors.push(...formatZodErrors(validationResult.error, normalizedData));
651
980
  }
652
981
  if (unknownFields.length > 0) {
653
982
  allErrors.push(`Unknown field(s): ${unknownFields.join(", ")}`);
654
983
  }
984
+ const structuredErrors = [];
985
+ if (!validationResult.success) {
986
+ structuredErrors.push(...formatZodErrorsStructured(validationResult.error, normalizedData));
987
+ }
988
+ if (unknownFields.length > 0) {
989
+ for (const f of unknownFields) {
990
+ structuredErrors.push({
991
+ path: f,
992
+ code: "unrecognized_keys",
993
+ message: `Unknown field '${f}' is not allowed`,
994
+ suggestion: `Remove field '${f}' or check the schema for valid field names`,
995
+ });
996
+ }
997
+ }
655
998
  const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
656
999
  const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
1000
+ const firstSuggestion = structuredErrors[0]?.suggestion
1001
+ ? ` FIRST ERROR SUGGESTION: ${structuredErrors[0].suggestion}`
1002
+ : '';
1003
+ const errorPreview = allErrors.slice(0, 5).map((e, i) => ` ${i + 1}. ${e}`).join("\n");
1004
+ const schemaPreview = buildSchemaPreview(relevantSchema, normalizedToolName, normalizedData);
1005
+ const textContent = [
1006
+ `Schema mismatch for ${normalizedToolName}. ${allErrors.length} error(s).${firstSuggestion}`,
1007
+ errorPreview,
1008
+ "",
1009
+ schemaPreview,
1010
+ "",
1011
+ "Fix the parameters based on the errors above and the schema summary, then retry.",
1012
+ `Full JSON Schema is in the structuredContent.schema.input field (cache it for future ${normalizedToolName} calls).`,
1013
+ `Structured errors with fix suggestions are in structuredContent.result.structured_errors (ARCH-02).`,
1014
+ ].filter(Boolean).join("\n");
657
1015
  return {
658
1016
  content: [{
659
1017
  type: "text",
660
- text: `Schema mismatch for ${normalizedToolName}. ${allErrors.length} error(s). Read the schema below, fix your params, and retry.`,
1018
+ text: textContent,
661
1019
  }],
662
1020
  structuredContent: {
663
1021
  result: {
664
1022
  status: "schema_mismatch",
665
1023
  errors: allErrors,
1024
+ structured_errors: structuredErrors,
666
1025
  hint: `Fix your parameters based on the schema below and retry. CACHE THIS SCHEMA for future ${normalizedToolName} calls — you don't need to query it again.`,
667
1026
  },
668
1027
  schema: {
@@ -706,15 +1065,31 @@ async function handleWowok(args) {
706
1065
  if (isSchemaValidationError(errorMessage)) {
707
1066
  const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
708
1067
  const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
1068
+ const schemaPreview = buildSchemaPreview(relevantSchema, normalizedToolName, normalizedData);
1069
+ const structuredErrors = [{
1070
+ path: "(runtime)",
1071
+ code: "schema_validation_error",
1072
+ message: errorMessage,
1073
+ suggestion: "Check the error message and the schema below for the correct field format",
1074
+ }];
1075
+ const textContent = [
1076
+ `Schema mismatch for ${normalizedToolName}: ${errorMessage}`,
1077
+ "",
1078
+ schemaPreview,
1079
+ "",
1080
+ "Fix the parameters and retry. Full JSON Schema is in structuredContent.schema.input.",
1081
+ "Structured errors with fix suggestions are in structuredContent.result.structured_errors (ARCH-02).",
1082
+ ].join("\n");
709
1083
  return {
710
1084
  content: [{
711
1085
  type: "text",
712
- text: `Schema mismatch for ${normalizedToolName}: ${errorMessage}`,
1086
+ text: textContent,
713
1087
  }],
714
1088
  structuredContent: {
715
1089
  result: {
716
1090
  status: "schema_mismatch",
717
1091
  errors: [errorMessage],
1092
+ structured_errors: structuredErrors,
718
1093
  hint: `Fix your parameters based on the schema below and retry. CACHE THIS SCHEMA for future ${normalizedToolName} calls.`,
719
1094
  },
720
1095
  schema: {
@@ -0,0 +1,8 @@
1
+ export interface RetryConfig {
2
+ maxRetries: number;
3
+ intervalMs: number;
4
+ }
5
+ export declare const DEFAULT_FAUCET_RETRY_CONFIG: RetryConfig;
6
+ export declare function loadFaucetRetryConfig(): RetryConfig;
7
+ export declare function isFaucetRateLimitError(error: unknown): boolean;
8
+ export declare function withFaucetRetry<T, R>(fn: (input: T) => Promise<R>, config?: RetryConfig): (input: T) => Promise<R>;
@@ -0,0 +1,85 @@
1
+ export const DEFAULT_FAUCET_RETRY_CONFIG = {
2
+ maxRetries: 5,
3
+ intervalMs: 3000,
4
+ };
5
+ export function loadFaucetRetryConfig() {
6
+ const maxRetries = Number(process.env.WOWOK_FAUCET_RETRY_COUNT);
7
+ const intervalMs = Number(process.env.WOWOK_FAUCET_RETRY_INTERVAL_MS);
8
+ return {
9
+ maxRetries: Number.isFinite(maxRetries) && maxRetries > 0
10
+ ? Math.floor(maxRetries)
11
+ : DEFAULT_FAUCET_RETRY_CONFIG.maxRetries,
12
+ intervalMs: Number.isFinite(intervalMs) && intervalMs > 0
13
+ ? Math.floor(intervalMs)
14
+ : DEFAULT_FAUCET_RETRY_CONFIG.intervalMs,
15
+ };
16
+ }
17
+ export function isFaucetRateLimitError(error) {
18
+ if (!error)
19
+ return false;
20
+ const msg = error instanceof Error ? error.message : String(error);
21
+ const lower = msg.toLowerCase();
22
+ if (lower.includes("429"))
23
+ return true;
24
+ if (lower.includes("rate limit"))
25
+ return true;
26
+ if (lower.includes("rate-limit"))
27
+ return true;
28
+ if (lower.includes("too many requests"))
29
+ return true;
30
+ if (lower.includes("try again in"))
31
+ return true;
32
+ if (lower.includes("throttle"))
33
+ return true;
34
+ return false;
35
+ }
36
+ function isFaucetOperation(input) {
37
+ if (typeof input !== "object" || input === null)
38
+ return false;
39
+ const obj = input;
40
+ return obj.faucet !== undefined && obj.faucet !== null;
41
+ }
42
+ export function withFaucetRetry(fn, config = loadFaucetRetryConfig()) {
43
+ return async (input) => {
44
+ if (!isFaucetOperation(input)) {
45
+ return fn(input);
46
+ }
47
+ let lastError;
48
+ for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
49
+ try {
50
+ const result = await fn(input);
51
+ if (result && typeof result === "object" && !Array.isArray(result)) {
52
+ const obj = result;
53
+ if (obj.faucet_retry_count === undefined && attempt > 1) {
54
+ obj.faucet_retry_count = attempt;
55
+ }
56
+ }
57
+ return result;
58
+ }
59
+ catch (error) {
60
+ lastError = error;
61
+ if (!isFaucetRateLimitError(error)) {
62
+ throw error;
63
+ }
64
+ if (attempt === config.maxRetries) {
65
+ break;
66
+ }
67
+ await new Promise((resolve) => setTimeout(resolve, config.intervalMs));
68
+ }
69
+ }
70
+ const lastMsg = lastError instanceof Error ? lastError.message : String(lastError);
71
+ const err = new Error(`Faucet request failed after ${config.maxRetries} attempts ` +
72
+ `(interval ${config.intervalMs}ms). Last error: ${lastMsg}. ` +
73
+ `The faucet endpoint is currently rate-limiting this account. ` +
74
+ `Suggestions:\n` +
75
+ ` 1. Wait a few minutes and try again.\n` +
76
+ ` 2. Use a different faucet network if available.\n` +
77
+ ` 3. Override retry config via env vars: ` +
78
+ `WOWOK_FAUCET_RETRY_COUNT (default 5), ` +
79
+ `WOWOK_FAUCET_RETRY_INTERVAL_MS (default 3000).`);
80
+ if (lastError instanceof Error && lastError.code) {
81
+ err.code = lastError.code;
82
+ }
83
+ throw err;
84
+ };
85
+ }
@@ -0,0 +1,28 @@
1
+ export type WipPathType = "local_unix" | "local_windows" | "local_relative" | "http_url" | "ipfs" | "data_url" | "unknown";
2
+ export interface WipPathClassification {
3
+ type: WipPathType;
4
+ is_local: boolean;
5
+ is_network: boolean;
6
+ description: string;
7
+ }
8
+ export declare function classifyWipPath(path: string): WipPathClassification;
9
+ export interface WipDeployOption {
10
+ name: string;
11
+ description: string;
12
+ difficulty: "easy" | "medium" | "hard";
13
+ free: boolean;
14
+ result_url_pattern: string;
15
+ steps: string[];
16
+ notes?: string[];
17
+ }
18
+ export declare function getDeployOptions(localFilePath: string): WipDeployOption[];
19
+ export interface WipDeploySuggestion {
20
+ path: string;
21
+ classification: WipPathClassification;
22
+ needs_deployment: boolean;
23
+ reason: string;
24
+ options: WipDeployOption[];
25
+ remind_update_hash: boolean;
26
+ }
27
+ export declare function analyzeWipDeployment(path: string): WipDeploySuggestion;
28
+ export declare function formatDeployHints(suggestion: WipDeploySuggestion): string;