wowok_agent
Version:
Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.
447 lines (446 loc) • 28.8 kB
JavaScript
import { z } from "zod";
import { NameOrAddressSchema, EntrypointSchema, AccountOrMark_AddressAISchema, ManyAccountOrMark_AddressAISchema } from "../common/index.js";
export const MessageStatusSchema = z.enum(["pending", "confirmed", "read", "failed", "rejected", "decrypted", "decrypt_failed"]);
export const MessageDirectionSchema = z.enum(["sent", "received"]);
export const MessageTypeSchema = z.union([z.literal(1), z.literal(3)]);
export const MessageContentTypeSchema = z.enum(["text", "zip", "wts", "wip"]);
export const MessageTimeFieldSchema = z.enum(["createdAt", "receivedAt", "serverTimestamp"]);
export const RangeTypeSchema = z.enum(["time", "messageId", "seqIndex"]);
export const ZipMetadataSchema = z.object({
fileName: z.string().describe("ZIP filename"),
fileSize: z.number().describe("File size in bytes"),
fileHash: z.string().describe("File SHA256 hash"),
contentType: MessageContentTypeSchema.describe("Content type"),
localCachePath: z.string().optional().describe("Local cache path"),
downloadedAt: z.number().optional().describe("Download timestamp"),
}).describe("ZIP file metadata");
export const MessageSchema = z.object({
messageId: z.string().describe("Message ID"),
fromAddress: z.string().describe("Sender address"),
toAddress: z.string().describe("Recipient address"),
plaintextHash: z.string().describe("Plaintext hash"),
plaintext: z.string().optional().describe("Decrypted plaintext (optional)"),
guardAddress: z.string().optional().describe("Guard address"),
passportAddress: z.string().optional().describe("Passport address"),
lastReceivedLeafIndex: z.number().optional().describe("Last received leaf index"),
direction: MessageDirectionSchema.describe("Message direction"),
status: MessageStatusSchema.describe("Message status"),
msgType: MessageTypeSchema.describe("Message type"),
leafIndex: z.number().optional().describe("Leaf index"),
prevRoot: z.string().optional().describe("Previous Merkle Root"),
newRoot: z.string().optional().describe("Current Merkle Root"),
serverSignature: z.string().optional().describe("Server signature"),
serverTimestamp: z.number().optional().describe("Server confirmation timestamp"),
serverPublicKey: z.string().optional().describe("Server public key"),
arkConfirmed: z.object({
recipient: z.string().describe("Recipient address"),
recipientPublicKey: z.string().describe("Recipient public key"),
signature: z.string().describe("Recipient signature"),
timestamp: z.number().describe("ARK confirmation time"),
}).optional().describe("ARK confirmation"),
createdAt: z.number().describe("Message creation time (client)"),
receivedAt: z.number().optional().describe("Local reception time"),
zipMetadata: ZipMetadataSchema.optional().describe("ZIP file metadata"),
proof: z.string().optional().describe("On-chain proof object address"),
decryptError: z.string().optional().describe("Decryption failure reason"),
decryptAttempts: z.number().optional().describe("Number of decryption attempts"),
lastDecryptAttemptAt: z.number().optional().describe("Last decryption attempt timestamp"),
viewedAt: z.number().optional().describe("Timestamp when the current user viewed this message (local storage). If present, indicates the message has been viewed by the user. Only applicable to received messages (direction === 'received')"),
}).describe("Message object");
export const ConversationInfoSchema = z.object({
peerAddress: z.string().describe("Peer address"),
lastMessageAt: z.number().describe("Last message time"),
messageCount: z.number().describe("Total message count"),
unreadCount: z.number().describe("Unread message count - count of received messages that have not been viewed (viewedAt is undefined)"),
lastMessagePreview: z.string().optional().describe("Last message preview text"),
previewMessages: z.array(MessageSchema).optional().describe("Preview messages for this conversation (default 2 messages, sorted by time descending)"),
}).describe("Conversation info with unread count and preview messages");
export const ConversationsFilterSchema = z.object({
account: z.string().optional().describe("Account name or address to query conversations for. If not specified, uses default account"),
unreadOnly: z.boolean().optional().describe("If true, only return conversations with unread messages (unreadCount > 0). Useful for quickly finding conversations needing attention"),
startTime: z.number().optional().describe("Start timestamp (ms) for filtering conversations by lastMessageAt. Only returns conversations where lastMessageAt >= this value"),
endTime: z.number().optional().describe("End timestamp (ms) for filtering conversations by lastMessageAt. Only returns conversations where lastMessageAt <= this value"),
previewMessageCount: z.number().optional().describe("Number of preview messages to include for each conversation (default: 2). Set to 0 to disable preview messages. If > 0, preview messages are automatically included"),
sortBy: z.enum(["lastMessageAt", "unreadCount", "messageCount"]).optional().describe("Sort conversations by: 'lastMessageAt' = most recent activity first, 'unreadCount' = most unread messages first, 'messageCount' = most total messages first"),
sortOrder: z.enum(["asc", "desc"]).optional().describe("Sort order: 'asc' = ascending (oldest/smallest first), 'desc' = descending (newest/largest first). Default is 'desc' for time-based sorting"),
skipAutoMarkViewed: z.boolean().optional().describe("If true, preview messages will NOT be automatically marked as viewed when retrieved. Default is false, meaning preview messages are auto-marked as viewed"),
}).describe("Conversations filter options - use unreadOnly to quickly find active conversations, and previewMessageCount to control how many recent messages are included");
export const MessageFilterSchema = z.object({
account: z.string().optional().describe("Account to filter messages for"),
direction: MessageDirectionSchema.optional().describe("Filter by message direction"),
status: MessageStatusSchema.optional().describe("Filter by message status"),
peerAddress: AccountOrMark_AddressAISchema.optional().describe("Filter by peer address - can be a string (name/address) or full object"),
msgType: MessageTypeSchema.optional().describe("Filter by message type"),
contentType: MessageContentTypeSchema.optional().describe("Filter by content type"),
decryptedOnly: z.boolean().optional().describe("Only return decrypted messages"),
confirmedOnly: z.boolean().optional().describe("Only return confirmed messages"),
keyword: z.string().optional().describe("Search keyword in plaintext"),
sortOrder: z.enum(["asc", "desc"]).optional().describe("Sort order: asc or desc"),
limit: z.number().optional().describe("Return limit"),
offset: z.number().optional().describe("Pagination offset"),
timeField: MessageTimeFieldSchema.optional().describe("Time field for time filtering"),
startTime: z.number().optional().describe("Start timestamp (ms)"),
endTime: z.number().optional().describe("End timestamp (ms)"),
createdAtStart: z.number().optional().describe("Created at start time"),
createdAtEnd: z.number().optional().describe("Created at end time"),
receivedAtStart: z.number().optional().describe("Received at start time"),
receivedAtEnd: z.number().optional().describe("Received at end time"),
serverTimestampStart: z.number().optional().describe("Server timestamp start time"),
serverTimestampEnd: z.number().optional().describe("Server timestamp end time"),
arkConfirmedOnly: z.boolean().optional().describe("Only return ARK confirmed messages"),
arkTimestampStart: z.number().optional().describe("ARK timestamp start"),
arkTimestampEnd: z.number().optional().describe("ARK timestamp end"),
proofedOnly: z.boolean().optional().describe("Only return messages with proof"),
hasLastReceivedIndexOnly: z.boolean().optional().describe("Only return messages with lastReceivedLeafIndex"),
lastReceivedIndexMin: z.number().optional().describe("Min lastReceivedLeafIndex"),
lastReceivedIndexMax: z.number().optional().describe("Max lastReceivedLeafIndex"),
listFilterMode: z.enum(["friends", "guard", "stranger", "any"]).optional().describe("List filter mode: 'friends' = only messages from friends list, 'guard' = only messages from Guard list, 'stranger' = only messages from strangers (not in friends/guard lists), 'any' = no filtering (default)"),
customListFilter: z.object({
includeAddresses: z.array(z.string()).optional().describe("Include addresses - only return messages from these addresses (highest priority)"),
excludeAddresses: z.array(z.string()).optional().describe("Exclude addresses - exclude messages from these addresses"),
relation: z.enum(["union", "intersection"]).optional().describe("Address list relation: 'union' = combine lists as union, 'intersection' = combine lists as intersection"),
}).optional().describe("Custom list filter for advanced address-based filtering, works in combination with listFilterMode"),
viewed: z.boolean().optional().describe("Filter by viewed status: true = only viewed messages, false = only unviewed messages. A message is considered 'viewed' if viewedAt field exists. Only applicable to received messages"),
viewedAtStart: z.number().optional().describe("Filter by viewed timestamp start (inclusive). Only returns messages where viewedAt >= this value. Useful for finding recently viewed messages"),
viewedAtEnd: z.number().optional().describe("Filter by viewed timestamp end (inclusive). Only returns messages where viewedAt <= this value. Useful for finding messages viewed before a certain time"),
skipAutoMarkViewed: z.boolean().optional().describe("If true, messages returned by this query will NOT be automatically marked as viewed. Default is false, meaning messages are auto-marked as viewed when retrieved through watch_messages"),
}).describe("Message filter options - all conditions are optional and combined with AND logic. Use viewed field to filter by read/unread status, and viewedAtStart/viewedAtEnd to filter by when messages were viewed");
export const SendMessageOptionsSchema = z.object({
guardAddress: NameOrAddressSchema.optional().describe("Guard address"),
passportAddress: NameOrAddressSchema.optional().describe("Passport address"),
force: z.boolean().optional().describe("Force send even if there are pending Guard messages"),
new_messenger_name: z.string().optional().describe("New messenger name for recipient"),
}).describe("Send message options");
export const SendFileOptionsSchema = z.object({
fileName: z.string().optional().describe("Custom file name"),
contentType: z.enum(["wts", "wip", "zip"]).optional().describe("Content type hint"),
guardAddress: NameOrAddressSchema.optional().describe("Guard address"),
passportAddress: NameOrAddressSchema.optional().describe("Passport address"),
force: z.boolean().optional().describe("Force send even if there are pending Guard messages"),
new_messenger_name: z.string().optional().describe("New messenger name for recipient"),
}).describe("Send file options");
export const SendMessageResultSchema = z.object({
messageId: z.string().describe("Message ID"),
status: MessageStatusSchema.describe("Message status"),
merkleData: z.object({
leafIndex: z.number().describe("Leaf index"),
prevRoot: z.string().describe("Previous Merkle Root"),
newRoot: z.string().describe("Current Merkle Root"),
serverSignature: z.string().describe("Server signature"),
serverTimestamp: z.number().describe("Server confirmation timestamp"),
serverPublicKey: z.string().describe("Server public key"),
}).optional().describe("Merkle Tree proof data"),
guardList: z.array(z.string()).optional().describe("Guard list (only returned on error)"),
lastReceivedLeafIndex: z.number().optional().describe("Last received leaf index (for message confirmation)"),
}).describe("Send message result");
const BaseRangeSchema = z.object({
type: RangeTypeSchema.describe("Range type"),
start: z.union([z.number(), z.string()]).describe("Start value"),
end: z.union([z.number(), z.string()]).describe("End value"),
});
export const TimeRangeSchema = BaseRangeSchema.extend({
type: z.literal("time"),
start: z.number(),
end: z.number(),
});
export const MessageIdRangeSchema = BaseRangeSchema.extend({
type: z.literal("messageId"),
start: z.string(),
end: z.string(),
});
export const SeqIndexRangeSchema = BaseRangeSchema.extend({
type: z.literal("seqIndex"),
start: z.number(),
end: z.number(),
});
export const WtsRangeSchema = z.discriminatedUnion("type", [
TimeRangeSchema,
MessageIdRangeSchema,
SeqIndexRangeSchema,
]).describe("WTS range filter parameters");
export const WtsGenerationParamsSchema = z.object({
myAccount: NameOrAddressSchema.describe("My account name or address (string)"),
peerAccount: AccountOrMark_AddressAISchema.describe("Peer account name or address - can be a string (name/address) or full object"),
range: WtsRangeSchema.optional().describe("Range filter parameters"),
excludePlaintext: z.boolean().optional().describe("Whether to exclude plaintext"),
outputDir: z.string().describe("Output directory path"),
}).describe("WTS generation parameters");
export const WtsFileResultSchema = z.object({
files: z.array(z.string()).describe("Generated WTS file paths"),
totalMessageCount: z.number().describe("Total message count"),
timeRange: z.object({
start: z.number().describe("Start time"),
end: z.number().describe("End time"),
}).describe("Time range"),
}).describe("WTS file result");
export const WtsSignatureVerificationSchema = z.object({
publicKey: z.string().describe("Signer public key"),
address: z.string().optional().describe("Signer address"),
valid: z.boolean().describe("Whether signature is valid"),
}).describe("WTS signature verification details");
export const WtsVerificationResultSchema = z.object({
valid: z.boolean().describe("Whether verification succeeded"),
error: z.string().optional().describe("Error message if verification failed"),
hashValid: z.boolean().optional().describe("Whether hash validation passed"),
hasSignature: z.boolean().optional().describe("Whether WTS has signatures"),
signatureValid: z.boolean().optional().describe("Whether signature validation passed"),
signatures: z.array(WtsSignatureVerificationSchema).optional().describe("Signature verification details"),
}).describe("WTS verification result");
export const WtsToHtmlOptionsSchema = z.object({
title: z.string().optional().describe("HTML document title"),
theme: z.enum(["light", "dark"]).optional().describe("HTML theme"),
outputPath: z.string().optional().describe("Output file path"),
}).describe("WTS to HTML conversion options");
export const AddressExistenceSchema = z.object({
address: z.string().describe("Address"),
exists: z.boolean().describe("Whether address exists in list"),
}).describe("Address existence check result");
export const GuardListItemSchema = z.object({
guardAddress: z.string().describe("Guard address"),
passportValiditySeconds: z.number().describe("Passport validity in seconds"),
}).describe("Guard list item");
export const ListOperationResponseSchema = z.object({
success: z.boolean().describe("Whether operation succeeded"),
operation: z.string().describe("Operation performed"),
modifiedCount: z.number().describe("Number of items modified"),
currentCount: z.number().describe("Current list size"),
maxCount: z.number().describe("Maximum list size"),
invalidAddresses: z.array(z.string()).optional().nullable().describe("Invalid addresses"),
existResults: z.array(AddressExistenceSchema).optional().nullable().describe("Existence check results"),
message: z.string().optional().nullable().describe("Operation message"),
currentList: z.array(z.string()).optional().nullable().describe("Current list content"),
currentGuardList: z.array(GuardListItemSchema).optional().nullable().describe("Current guard list content"),
}).describe("List operation response");
export const BlacklistOperationSchema = z.discriminatedUnion("op", [
z.object({
op: z.literal("add"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to add to blacklist - can be array of strings (names/addresses) or full object"),
}),
z.object({
op: z.literal("remove"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to remove from blacklist - can be array of strings (names/addresses) or full object"),
}),
z.object({
op: z.literal("clear"),
}),
z.object({
op: z.literal("get"),
}),
z.object({
op: z.literal("exist"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to check existence - can be array of strings (names/addresses) or full object"),
}),
]).describe("Blacklist management operation");
export const FriendslistOperationSchema = z.discriminatedUnion("op", [
z.object({
op: z.literal("add"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to add to friends list - can be array of strings (names/addresses) or full object"),
}),
z.object({
op: z.literal("remove"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to remove from friends list - can be array of strings (names/addresses) or full object"),
}),
z.object({
op: z.literal("clear"),
}),
z.object({
op: z.literal("get"),
}),
z.object({
op: z.literal("exist"),
users: ManyAccountOrMark_AddressAISchema.describe("Users to check existence - can be array of strings (names/addresses) or full object"),
}),
]).describe("Friends list management operation");
export const GuardParamSchema = z.object({
guard: NameOrAddressSchema.describe("Guard address or name"),
passportValiditySeconds: z.number().min(10).max(315360000).describe("Passport validity in seconds (10s to 10 years)"),
}).describe("Guard parameter");
export const GuardlistOperationSchema = z.discriminatedUnion("op", [
z.object({
op: z.literal("add"),
guards: z.array(GuardParamSchema).min(1).max(10).describe("Guards to add to guard list"),
}),
z.object({
op: z.literal("remove"),
guards: z.array(NameOrAddressSchema).min(1).max(10).describe("Guard addresses to remove from guard list"),
}),
z.object({
op: z.literal("get"),
}),
]).describe("Guard list management operation");
export const SettingsOperationSchema = z.discriminatedUnion("op", [
z.object({
op: z.literal("get"),
}),
z.object({
op: z.literal("set"),
allowStrangerMessages: z.boolean().optional().describe("Allow messages from strangers"),
maxInboxSize: z.number().min(1).optional().describe("Maximum inbox size"),
}),
]).describe("Settings management operation");
export const GetSettingsResponseSchema = z.object({
allowStrangerMessages: z.boolean().optional().describe("Whether messages from strangers are allowed"),
maxInboxSize: z.number().optional().describe("Current maximum inbox size"),
minUserInboxSize: z.number().describe("Server minimum allowed inbox size limit"),
maxUserInboxSize: z.number().describe("Server maximum allowed inbox size limit"),
defaultAllowStrangerMessages: z.boolean().describe("Server default setting for allowing stranger messages"),
}).describe("Get settings response");
export const MessengerOperationInputSchema = z.discriminatedUnion("operation", [
z.object({
operation: z.literal("watch_conversations"),
filter: ConversationsFilterSchema.optional().describe("Conversations filter options - use unreadOnly to find conversations with unread messages, previewMessageCount to control message previews (default 2), and sortBy/sortOrder to customize sorting"),
}),
z.object({
operation: z.literal("send_message"),
from: NameOrAddressSchema.optional().describe("Sender account name or address. If not specified, uses default account"),
to: AccountOrMark_AddressAISchema.describe("Recipient address or account name - can be a string (name/address) or full object"),
content: z.string().max(10000).describe("Message content text"),
options: SendMessageOptionsSchema.optional().describe("Optional message settings"),
}),
z.object({
operation: z.literal("send_file"),
from: NameOrAddressSchema.optional().describe("Sender account name or address. If not specified, uses default account"),
to: AccountOrMark_AddressAISchema.describe("Recipient address or account name - can be a string (name/address) or full object"),
filePath: z.string().describe("Local file path to send. File will be compressed as ZIP before sending"),
options: SendFileOptionsSchema.optional().describe("Optional file sending settings"),
}),
z.object({
operation: z.literal("watch_messages"),
filter: MessageFilterSchema.optional().describe("Message filter options"),
}),
z.object({
operation: z.literal("extract_zip_messages"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
messages: z.array(z.union([z.string(), MessageSchema])).describe("Array of message objects or message IDs to extract"),
outputDir: z.string().describe("Output directory path for extracted files"),
}),
z.object({
operation: z.literal("generate_wts"),
params: WtsGenerationParamsSchema.describe("WTS generation parameters"),
}),
z.object({
operation: z.literal("verify_wts"),
wtsFilePath: z.string().describe("WTS file path to verify"),
}),
z.object({
operation: z.literal("sign_wts"),
wtsFilePath: z.string().describe("WTS file path to sign"),
account: NameOrAddressSchema.optional().describe("Account name or address to sign with. If not specified, uses default account"),
outputPath: z.string().optional().describe("Output file path. If not specified, saves to signed_*.wts"),
}),
z.object({
operation: z.literal("wts2html"),
wtsPath: z.string().describe("WTS file path or directory to convert"),
options: WtsToHtmlOptionsSchema.optional().describe("Conversion options"),
}),
z.object({
operation: z.literal("proof_message"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
messageId: z.string().describe("Message ID to proof on-chain"),
network: EntrypointSchema.optional().describe("Network to use for on-chain proof"),
}),
z.object({
operation: z.literal("blacklist"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
blacklist: BlacklistOperationSchema.describe("Blacklist management operation"),
}),
z.object({
operation: z.literal("friendslist"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
friendslist: FriendslistOperationSchema.describe("Friends list management operation"),
}),
z.object({
operation: z.literal("guardlist"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
guardlist: GuardlistOperationSchema.describe("Guard list management operation"),
}),
z.object({
operation: z.literal("settings"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
settings: SettingsOperationSchema.describe("Settings management operation"),
}),
z.object({
operation: z.literal("mark_messages_as_viewed"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
messageIds: z.array(z.string()).min(1).max(1000).describe("Array of message IDs to mark as viewed (1-1000 messages). Only messages belonging to this account will be marked"),
}),
z.object({
operation: z.literal("mark_conversation_as_viewed"),
account: NameOrAddressSchema.optional().describe("Account name or address. If not specified, uses default account"),
peerAddress: AccountOrMark_AddressAISchema.describe("Peer address or account name - can be a string (name/address) or full object. All unviewed received messages from this peer will be marked as viewed"),
}),
]).describe("Messenger operation input schema");
export const MessengerOperationOutputSchema = z.object({
result: z.discriminatedUnion("operation", [
z.object({
operation: z.literal("watch_conversations"),
result: z.array(ConversationInfoSchema).describe("List of conversations"),
}),
z.object({
operation: z.literal("send_message"),
result: SendMessageResultSchema.describe("Send message result"),
}),
z.object({
operation: z.literal("send_file"),
result: SendMessageResultSchema.describe("Send file result"),
}),
z.object({
operation: z.literal("watch_messages"),
result: z.array(MessageSchema).describe("List of messages"),
}),
z.object({
operation: z.literal("extract_zip_messages"),
result: z.array(z.string()).describe("Extracted file paths"),
}),
z.object({
operation: z.literal("generate_wts"),
result: WtsFileResultSchema.describe("Generate WTS result"),
}),
z.object({
operation: z.literal("verify_wts"),
result: WtsVerificationResultSchema.describe("WTS verification result"),
}),
z.object({
operation: z.literal("sign_wts"),
result: z.string().describe("Signed WTS file path"),
}),
z.object({
operation: z.literal("wts2html"),
result: z.union([z.string(), z.array(z.string())]).describe("HTML string or file path(s)"),
}),
z.object({
operation: z.literal("proof_message"),
result: z.object({
proofAddress: z.string().describe("Proof object address on blockchain"),
}).describe("Proof message result"),
}),
z.object({
operation: z.literal("blacklist"),
op: z.enum(["add", "remove", "clear", "get", "exist"]).describe("Operation type"),
result: z.union([ListOperationResponseSchema, z.array(z.string())]).describe("Blacklist operation result"),
}),
z.object({
operation: z.literal("friendslist"),
op: z.enum(["add", "remove", "clear", "get", "exist"]).describe("Operation type"),
result: z.union([ListOperationResponseSchema, z.array(z.string())]).describe("Friends list operation result"),
}),
z.object({
operation: z.literal("guardlist"),
op: z.enum(["add", "remove", "get"]).describe("Operation type"),
result: ListOperationResponseSchema.describe("Guard list operation result"),
}),
z.object({
operation: z.literal("settings"),
op: z.enum(["get", "set"]).describe("Operation type"),
result: z.union([GetSettingsResponseSchema, z.boolean()]).describe("Settings operation result - GetSettingsResponse for 'get' operation, boolean for 'set' operation"),
}),
z.object({
operation: z.literal("mark_messages_as_viewed"),
result: z.number().describe("Number of messages successfully marked as viewed. Only messages that were previously unviewed are counted"),
}),
z.object({
operation: z.literal("mark_conversation_as_viewed"),
result: z.number().describe("Number of messages successfully marked as viewed in the conversation. Only received messages that were previously unviewed are counted"),
}),
]).describe("Messenger operation result discriminated union"),
}).describe("Messenger operation output schema");