@wowok/agent-mcp 2.6.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/extensions/capability-manifest.d.ts +125 -0
- package/dist/extensions/capability-manifest.js +594 -0
- package/dist/extensions/constraint-registry.d.ts +24 -0
- package/dist/extensions/constraint-registry.js +196 -0
- package/dist/extensions/index.d.ts +12 -0
- package/dist/extensions/index.js +6 -0
- package/dist/extensions/metric-registry.d.ts +26 -0
- package/dist/extensions/metric-registry.js +257 -0
- package/dist/extensions/mode-evaluator.d.ts +15 -0
- package/dist/extensions/mode-evaluator.js +170 -0
- package/dist/extensions/modes.d.ts +2 -0
- package/dist/extensions/modes.js +407 -0
- package/dist/extensions/registry.d.ts +48 -0
- package/dist/extensions/registry.js +629 -0
- package/dist/extensions/types.d.ts +218 -0
- package/dist/extensions/types.js +1 -0
- package/dist/knowledge/deployment-scanner.d.ts +3 -0
- package/dist/knowledge/deployment-scanner.js +64 -3
- package/dist/knowledge/guard-risk.d.ts +13 -0
- package/dist/knowledge/guard-risk.js +57 -0
- package/dist/knowledge/guard-templates.js +278 -0
- package/dist/knowledge/machine-templates.js +20 -1
- package/dist/knowledge/service-confirm.d.ts +14 -5
- package/dist/knowledge/service-confirm.js +116 -8
- package/dist/knowledge/tool-constraints.js +6 -2
- package/dist/project/deployment-bridge.d.ts +1 -1
- package/dist/project/deployment-bridge.js +27 -4
- package/dist/project/deployment-doc.d.ts +3 -0
- package/dist/project/deployment-doc.js +72 -10
- package/dist/project/evaluation.d.ts +2 -0
- package/dist/project/evaluation.js +569 -84
- package/dist/project/graph-builder.d.ts +4 -1
- package/dist/project/graph-builder.js +126 -61
- package/dist/project/graph.d.ts +1 -0
- package/dist/project/handlers.d.ts +219 -5
- package/dist/project/handlers.js +819 -9
- package/dist/project/stage-gate.d.ts +4 -0
- package/dist/project/stage-gate.js +64 -5
- package/dist/project/task-tracker.d.ts +26 -0
- package/dist/project/task-tracker.js +78 -0
- package/dist/safety/preview.js +16 -0
- package/dist/schema/call/allocation.d.ts +16 -16
- package/dist/schema/call/base.d.ts +21 -13
- package/dist/schema/call/base.js +27 -6
- package/dist/schema/call/bridge.d.ts +5 -5
- package/dist/schema/call/bridge.js +3 -1
- package/dist/schema/call/demand.d.ts +23 -31
- package/dist/schema/call/guard.js +1 -1
- package/dist/schema/call/machine.d.ts +402 -376
- package/dist/schema/call/order.d.ts +149 -228
- package/dist/schema/call/order.js +7 -3
- package/dist/schema/call/payment.d.ts +183 -3
- package/dist/schema/call/payment.js +21 -3
- package/dist/schema/call/personal.d.ts +241 -52
- package/dist/schema/call/progress.d.ts +53 -61
- package/dist/schema/call/progress.js +18 -4
- package/dist/schema/call/repository.d.ts +23 -31
- package/dist/schema/call/semantic.d.ts +1 -1
- package/dist/schema/call/semantic.js +30 -1
- package/dist/schema/call/service.d.ts +95 -119
- package/dist/schema/call/service.js +22 -1
- package/dist/schema/common/index.d.ts +11 -2
- package/dist/schema/common/index.js +43 -14
- package/dist/schema/local/index.d.ts +32 -35
- package/dist/schema/local/index.js +23 -5
- package/dist/schema/messenger/index.d.ts +274 -46
- package/dist/schema/operations.d.ts +680 -539
- package/dist/schema/operations.js +22 -0
- package/dist/schema/project/index.d.ts +1796 -80
- package/dist/schema/project/index.js +304 -14
- package/dist/schema/query/index.d.ts +705 -349
- package/dist/schema/query/index.js +164 -31
- package/dist/schema/schema-query/index.d.ts +15 -3
- package/dist/schema/schema-query/index.js +23 -5
- package/dist/schema/utils/node-parser.js +7 -4
- package/dist/schema-query/index.d.ts +7 -1
- package/dist/schema-query/index.js +204 -4
- package/dist/schemas/account_operation.output.json +7 -1
- package/dist/schemas/account_operation.schema.json +2 -2
- package/dist/schemas/bridge_operation.output.json +6 -0
- package/dist/schemas/bridge_operation.schema.json +1 -1
- package/dist/schemas/guard-templates.json +379 -0
- package/dist/schemas/guard2file.schema.json +1 -1
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/local_info_operation.output.json +6 -0
- package/dist/schemas/local_mark_operation.output.json +7 -1
- package/dist/schemas/local_mark_operation.schema.json +1 -1
- package/dist/schemas/machineNode2file.schema.json +1 -1
- package/dist/schemas/messenger_operation.schema.json +4 -4
- package/dist/schemas/onchain_events.output.json +1 -1
- package/dist/schemas/onchain_operations.schema.json +348 -296
- package/dist/schemas/onchain_operations_allocation.schema.json +34 -25
- package/dist/schemas/onchain_operations_arbitration.schema.json +8 -8
- package/dist/schemas/onchain_operations_contact.schema.json +8 -8
- package/dist/schemas/onchain_operations_demand.schema.json +8 -8
- package/dist/schemas/onchain_operations_gen_passport.schema.json +14 -14
- package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
- package/dist/schemas/onchain_operations_guard.schema.json +1 -1
- package/dist/schemas/onchain_operations_machine.schema.json +41 -33
- package/dist/schemas/onchain_operations_order.schema.json +71 -77
- package/dist/schemas/onchain_operations_payment.schema.json +141 -111
- package/dist/schemas/onchain_operations_permission.schema.json +2 -2
- package/dist/schemas/onchain_operations_personal.schema.json +7 -7
- package/dist/schemas/onchain_operations_progress.schema.json +8 -8
- package/dist/schemas/onchain_operations_proof.schema.json +7 -7
- package/dist/schemas/onchain_operations_repository.schema.json +8 -8
- package/dist/schemas/onchain_operations_reward.schema.json +10 -10
- package/dist/schemas/onchain_operations_service.schema.json +46 -35
- package/dist/schemas/onchain_operations_treasury.schema.json +8 -8
- package/dist/schemas/onchain_table_data.output.json +33 -25
- package/dist/schemas/onchain_table_data.schema.json +12 -12
- package/dist/schemas/project_operation.output.json +1175 -23
- package/dist/schemas/project_operation.schema.json +40 -4
- package/dist/schemas/query_toolkit.output.json +104 -76
- package/dist/schemas/query_toolkit.schema.json +9 -9
- package/dist/schemas/schema_query.output.json +7 -3
- package/dist/schemas/schema_query.schema.json +17 -3
- package/dist/tools/handlers/local.js +20 -5
- package/dist/tools/handlers/onchain.js +23 -0
- package/dist/tools/handlers/project.js +52 -3
- package/dist/tools/handlers/query.js +27 -0
- package/dist/tools/handlers/schema-query.js +19 -0
- package/dist/tools/handlers/task-status.d.ts +170 -0
- package/dist/tools/handlers/task-status.js +55 -0
- package/dist/tools/handlers/wip.js +47 -1
- package/dist/tools/index.js +211 -7
- package/dist/tools/retry.d.ts +8 -0
- package/dist/tools/retry.js +85 -0
- package/dist/tools/wip-deploy-assist.d.ts +28 -0
- package/dist/tools/wip-deploy-assist.js +278 -0
- package/package.json +2 -2
- package/dist/schemas/guard-node-examples.md +0 -199
package/dist/tools/index.js
CHANGED
|
@@ -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);
|
|
@@ -478,12 +501,71 @@ 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) {
|
|
482
505
|
return error.issues.map(issue => {
|
|
483
|
-
const path = issue.path.length > 0
|
|
484
|
-
|
|
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}`;
|
|
485
546
|
});
|
|
486
547
|
}
|
|
548
|
+
function extractValueAtPath(input, path) {
|
|
549
|
+
if (input === undefined || input === null || path.length === 0) {
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
let current = input;
|
|
553
|
+
for (const key of path) {
|
|
554
|
+
if (current === undefined || current === null)
|
|
555
|
+
return undefined;
|
|
556
|
+
if (typeof key === "number") {
|
|
557
|
+
if (!Array.isArray(current))
|
|
558
|
+
return undefined;
|
|
559
|
+
current = current[key];
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
if (typeof current !== "object")
|
|
563
|
+
return undefined;
|
|
564
|
+
current = current[key];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return current;
|
|
568
|
+
}
|
|
487
569
|
function checkUnknownFields(schema, input) {
|
|
488
570
|
let innerSchema = schema;
|
|
489
571
|
while (true) {
|
|
@@ -518,6 +600,109 @@ function isSchemaValidationError(message) {
|
|
|
518
600
|
message.includes("Invalid input") ||
|
|
519
601
|
message.includes("Required"));
|
|
520
602
|
}
|
|
603
|
+
function buildSchemaPreview(schema, toolName, data) {
|
|
604
|
+
try {
|
|
605
|
+
const lines = [`Schema preview for ${toolName}:`];
|
|
606
|
+
let topProps;
|
|
607
|
+
let topRequired = [];
|
|
608
|
+
let topDescription = "";
|
|
609
|
+
if (schema.properties && typeof schema.properties === "object") {
|
|
610
|
+
topProps = schema.properties;
|
|
611
|
+
topRequired = Array.isArray(schema.required) ? schema.required : [];
|
|
612
|
+
topDescription = typeof schema.description === "string" ? schema.description : "";
|
|
613
|
+
}
|
|
614
|
+
else if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
|
|
615
|
+
const variants = (schema.oneOf ?? schema.anyOf);
|
|
616
|
+
for (const v of variants) {
|
|
617
|
+
if (v && typeof v === "object") {
|
|
618
|
+
const vo = v;
|
|
619
|
+
if (vo.properties && typeof vo.properties === "object") {
|
|
620
|
+
topProps = vo.properties;
|
|
621
|
+
topRequired = Array.isArray(vo.required) ? vo.required : [];
|
|
622
|
+
topDescription = typeof vo.description === "string" ? vo.description : "";
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (!topProps) {
|
|
628
|
+
lines.push(` (discriminated union with ${variants.length} variants — see structuredContent for full schema)`);
|
|
629
|
+
return lines.join("\n");
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (topDescription && topDescription.length > 0 && topDescription.length < 200) {
|
|
633
|
+
lines.push(` ${topDescription}`);
|
|
634
|
+
}
|
|
635
|
+
if (!topProps) {
|
|
636
|
+
lines.push(" (no properties available — see structuredContent for full schema)");
|
|
637
|
+
return lines.join("\n");
|
|
638
|
+
}
|
|
639
|
+
const requiredSet = new Set(topRequired);
|
|
640
|
+
const requiredList = topRequired.length > 0 ? topRequired.join(", ") : "(none)";
|
|
641
|
+
const optionalList = Object.keys(topProps).filter(k => !requiredSet.has(k)).join(", ");
|
|
642
|
+
lines.push(`Required: ${requiredList}`);
|
|
643
|
+
if (optionalList) {
|
|
644
|
+
lines.push(`Optional: ${optionalList}`);
|
|
645
|
+
}
|
|
646
|
+
lines.push("Fields:");
|
|
647
|
+
for (const [fieldName, fieldSchema] of Object.entries(topProps)) {
|
|
648
|
+
if (fieldSchema && typeof fieldSchema === "object") {
|
|
649
|
+
const f = fieldSchema;
|
|
650
|
+
const type = describeSchemaType(f);
|
|
651
|
+
const required = requiredSet.has(fieldName) ? "required" : "optional";
|
|
652
|
+
let desc = typeof f.description === "string" ? f.description : "";
|
|
653
|
+
if (desc.length > 120)
|
|
654
|
+
desc = desc.slice(0, 117) + "...";
|
|
655
|
+
let subFields = "";
|
|
656
|
+
if (f.properties && typeof f.properties === "object") {
|
|
657
|
+
const subProps = Object.keys(f.properties);
|
|
658
|
+
if (subProps.length > 0) {
|
|
659
|
+
subFields = ` { ${subProps.slice(0, 8).join(", ")}${subProps.length > 8 ? ", ..." : ""} }`;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (f.items && typeof f.items === "object") {
|
|
663
|
+
const items = f.items;
|
|
664
|
+
const itemType = describeSchemaType(items);
|
|
665
|
+
subFields = ` (array of ${itemType})`;
|
|
666
|
+
}
|
|
667
|
+
if (Array.isArray(f.enum)) {
|
|
668
|
+
subFields = ` (enum: ${f.enum.slice(0, 6).map(v => JSON.stringify(v)).join(", ")}${f.enum.length > 6 ? ", ..." : ""})`;
|
|
669
|
+
}
|
|
670
|
+
lines.push(` - ${fieldName} (${type}, ${required})${subFields}${desc ? ` — ${desc}` : ""}`);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (toolName === "onchain_operations" && typeof data === "object" && data !== null) {
|
|
674
|
+
const opType = data.operation_type;
|
|
675
|
+
if (typeof opType === "string") {
|
|
676
|
+
lines.push(``);
|
|
677
|
+
lines.push(`operation_type-specific schema: onchain_operations_${opType}`);
|
|
678
|
+
lines.push(`(Use schema_query with action='get' and name='onchain_operations_${opType}' for the full sub-schema.)`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return lines.join("\n");
|
|
682
|
+
}
|
|
683
|
+
catch {
|
|
684
|
+
return `Schema preview for ${toolName}: (unable to build preview — see structuredContent for full schema)`;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function describeSchemaType(schema) {
|
|
688
|
+
if (typeof schema.type === "string")
|
|
689
|
+
return schema.type;
|
|
690
|
+
if (Array.isArray(schema.type))
|
|
691
|
+
return schema.type.join("|");
|
|
692
|
+
if (schema.$ref)
|
|
693
|
+
return "$ref";
|
|
694
|
+
if (Array.isArray(schema.oneOf))
|
|
695
|
+
return "oneOf";
|
|
696
|
+
if (Array.isArray(schema.anyOf))
|
|
697
|
+
return "anyOf";
|
|
698
|
+
if (Array.isArray(schema.allOf))
|
|
699
|
+
return "allOf";
|
|
700
|
+
if (schema.enum)
|
|
701
|
+
return "enum";
|
|
702
|
+
if (schema.const)
|
|
703
|
+
return `const(${JSON.stringify(schema.const)})`;
|
|
704
|
+
return "object";
|
|
705
|
+
}
|
|
521
706
|
export async function dispatchToolCall(name, args, options) {
|
|
522
707
|
if (name === "wowok") {
|
|
523
708
|
return handleWowok(args);
|
|
@@ -647,17 +832,28 @@ async function handleWowok(args) {
|
|
|
647
832
|
if (!validationResult.success || unknownFields.length > 0) {
|
|
648
833
|
const allErrors = [];
|
|
649
834
|
if (!validationResult.success) {
|
|
650
|
-
allErrors.push(...formatZodErrors(validationResult.error));
|
|
835
|
+
allErrors.push(...formatZodErrors(validationResult.error, normalizedData));
|
|
651
836
|
}
|
|
652
837
|
if (unknownFields.length > 0) {
|
|
653
838
|
allErrors.push(`Unknown field(s): ${unknownFields.join(", ")}`);
|
|
654
839
|
}
|
|
655
840
|
const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
|
|
656
841
|
const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
|
|
842
|
+
const errorPreview = allErrors.slice(0, 5).map((e, i) => ` ${i + 1}. ${e}`).join("\n");
|
|
843
|
+
const schemaPreview = buildSchemaPreview(relevantSchema, normalizedToolName, normalizedData);
|
|
844
|
+
const textContent = [
|
|
845
|
+
`Schema mismatch for ${normalizedToolName}. ${allErrors.length} error(s):`,
|
|
846
|
+
errorPreview,
|
|
847
|
+
"",
|
|
848
|
+
schemaPreview,
|
|
849
|
+
"",
|
|
850
|
+
"Fix the parameters based on the errors above and the schema summary, then retry.",
|
|
851
|
+
`Full JSON Schema is in the structuredContent.schema.input field (cache it for future ${normalizedToolName} calls).`,
|
|
852
|
+
].filter(Boolean).join("\n");
|
|
657
853
|
return {
|
|
658
854
|
content: [{
|
|
659
855
|
type: "text",
|
|
660
|
-
text:
|
|
856
|
+
text: textContent,
|
|
661
857
|
}],
|
|
662
858
|
structuredContent: {
|
|
663
859
|
result: {
|
|
@@ -706,10 +902,18 @@ async function handleWowok(args) {
|
|
|
706
902
|
if (isSchemaValidationError(errorMessage)) {
|
|
707
903
|
const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
|
|
708
904
|
const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
|
|
905
|
+
const schemaPreview = buildSchemaPreview(relevantSchema, normalizedToolName, normalizedData);
|
|
906
|
+
const textContent = [
|
|
907
|
+
`Schema mismatch for ${normalizedToolName}: ${errorMessage}`,
|
|
908
|
+
"",
|
|
909
|
+
schemaPreview,
|
|
910
|
+
"",
|
|
911
|
+
"Fix the parameters and retry. Full JSON Schema is in structuredContent.schema.input.",
|
|
912
|
+
].join("\n");
|
|
709
913
|
return {
|
|
710
914
|
content: [{
|
|
711
915
|
type: "text",
|
|
712
|
-
text:
|
|
916
|
+
text: textContent,
|
|
713
917
|
}],
|
|
714
918
|
structuredContent: {
|
|
715
919
|
result: {
|
|
@@ -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;
|