@wowok/skills 1.1.3 → 1.1.4
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 +46 -7
- package/dist/cli.js +150 -35
- package/dist/cli.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -1
- package/examples/MyShop_Advanced/MyShop_Advanced.md +220 -228
- package/examples/MyShop_Advanced/three_body_signature.wip +30 -0
- package/package.json +3 -1
- package/scripts/install.js +126 -15
- package/wowok-messenger/SKILL.md +293 -0
- package/wowok-output/SKILL.md +142 -0
- package/wowok-safety/SKILL.md +3 -57
- package/wowok-tools/SKILL.md +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wowok/skills",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "WoWok AI Skills for Claude and other AI assistants - Helping AI use WoWok MCP tools correctly",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"wowok-safety/",
|
|
17
17
|
"wowok-machine/",
|
|
18
18
|
"wowok-order/",
|
|
19
|
+
"wowok-messenger/",
|
|
20
|
+
"wowok-output/",
|
|
19
21
|
"examples/",
|
|
20
22
|
"scripts/install.js",
|
|
21
23
|
"README.md"
|
package/scripts/install.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
* WoWok Skills installer
|
|
3
3
|
*
|
|
4
4
|
* npm lifecycle integration:
|
|
5
|
-
* postinstall → copy SKILL.md folders to ~/.claude/skills/
|
|
6
|
-
* preuninstall → remove SKILL.md folders from
|
|
5
|
+
* postinstall → copy SKILL.md folders to ~/.claude/skills/ (and more via env)
|
|
6
|
+
* preuninstall → remove SKILL.md folders from all installed client dirs
|
|
7
|
+
*
|
|
8
|
+
* Environment variables:
|
|
9
|
+
* WOWOK_SKILLS_TARGETS Comma-separated client targets (claude,agents,codebuddy)
|
|
10
|
+
* Defaults to "claude". Example: "claude,agents"
|
|
7
11
|
*/
|
|
8
12
|
|
|
9
13
|
const fs = require('fs');
|
|
@@ -21,7 +25,13 @@ const SKILL_DIRS = [
|
|
|
21
25
|
'wowok-safety',
|
|
22
26
|
];
|
|
23
27
|
|
|
24
|
-
const
|
|
28
|
+
const CLIENT_DIRS = {
|
|
29
|
+
claude: path.join(os.homedir(), '.claude', 'skills'),
|
|
30
|
+
agents: path.join(os.homedir(), '.agents', 'skills'),
|
|
31
|
+
codebuddy: path.join(os.homedir(), '.codebuddy', 'skills'),
|
|
32
|
+
cursor: path.join(os.homedir(), '.cursor', 'rules'),
|
|
33
|
+
copilot: path.join(os.homedir(), '.github', 'prompts'),
|
|
34
|
+
};
|
|
25
35
|
|
|
26
36
|
function getPackageRoot() {
|
|
27
37
|
return path.resolve(__dirname, '..');
|
|
@@ -57,26 +67,91 @@ function removeDir(dir) {
|
|
|
57
67
|
fs.rmdirSync(dir);
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
function
|
|
70
|
+
function getFileExt(target) {
|
|
71
|
+
const exts = { claude: '.md', agents: '.md', codebuddy: '.md', cursor: '.mdc', copilot: '.prompt.md' };
|
|
72
|
+
return exts[target] || '.md';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseFrontmatter(content) {
|
|
76
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
77
|
+
if (!match) return null;
|
|
78
|
+
const frontmatterStr = match[1];
|
|
79
|
+
const body = match[2];
|
|
80
|
+
const frontmatter = {};
|
|
81
|
+
let currentKey = null;
|
|
82
|
+
let currentValue = '';
|
|
83
|
+
for (const line of frontmatterStr.split('\n')) {
|
|
84
|
+
const kvMatch = line.match(/^(\w[\w-]*)\s*:\s*(.*)$/);
|
|
85
|
+
if (kvMatch) {
|
|
86
|
+
if (currentKey) {
|
|
87
|
+
frontmatter[currentKey] = currentValue.trim();
|
|
88
|
+
}
|
|
89
|
+
currentKey = kvMatch[1];
|
|
90
|
+
currentValue = kvMatch[2];
|
|
91
|
+
} else if (currentKey) {
|
|
92
|
+
currentValue += '\n' + line;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (currentKey) {
|
|
96
|
+
frontmatter[currentKey] = currentValue.trim();
|
|
97
|
+
}
|
|
98
|
+
return { frontmatter, body };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function convertSkill(content, target, skillDir) {
|
|
102
|
+
if (target === 'cursor') {
|
|
103
|
+
const parsed = parseFrontmatter(content);
|
|
104
|
+
if (!parsed) return content;
|
|
105
|
+
const { frontmatter, body } = parsed;
|
|
106
|
+
let description = (frontmatter.description || frontmatter.name || skillDir);
|
|
107
|
+
if (typeof description === 'string') {
|
|
108
|
+
description = description.replace(/\n/g, ' ');
|
|
109
|
+
}
|
|
110
|
+
const isAlways = frontmatter.loading === 'always' || frontmatter.always === true;
|
|
111
|
+
const alwaysApply = isAlways ? 'true' : 'false';
|
|
112
|
+
const newFrontmatter = [
|
|
113
|
+
'---',
|
|
114
|
+
`description: "${description}"`,
|
|
115
|
+
`alwaysApply: ${alwaysApply}`,
|
|
116
|
+
'---',
|
|
117
|
+
].join('\n');
|
|
118
|
+
return newFrontmatter + '\n' + body;
|
|
119
|
+
}
|
|
120
|
+
if (target === 'copilot') {
|
|
121
|
+
const parsed = parseFrontmatter(content);
|
|
122
|
+
if (!parsed) return content;
|
|
123
|
+
return parsed.body;
|
|
124
|
+
}
|
|
125
|
+
return content;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function installSkills(targetDir, target) {
|
|
61
129
|
const pkgRoot = getPackageRoot();
|
|
130
|
+
const ext = getFileExt(target);
|
|
62
131
|
let count = 0;
|
|
63
132
|
|
|
64
133
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
65
134
|
|
|
66
135
|
for (const dir of SKILL_DIRS) {
|
|
67
136
|
const src = path.join(pkgRoot, dir, 'SKILL.md');
|
|
68
|
-
const destDir = path.join(targetDir, dir);
|
|
69
|
-
const dest = path.join(destDir, 'SKILL.md');
|
|
70
137
|
|
|
71
138
|
if (!fs.existsSync(src)) {
|
|
72
139
|
console.warn(`[wowok-skills] WARN: SKILL.md not found for ${dir}`);
|
|
73
140
|
continue;
|
|
74
141
|
}
|
|
75
142
|
|
|
143
|
+
const content = fs.readFileSync(src, 'utf-8');
|
|
144
|
+
const converted = convertSkill(content, target, dir);
|
|
145
|
+
const basename = (target === 'cursor' || target === 'copilot')
|
|
146
|
+
? `wowok-${dir.replace('wowok-', '')}${ext}`
|
|
147
|
+
: 'SKILL.md';
|
|
148
|
+
const destDir = path.join(targetDir, dir);
|
|
149
|
+
const dest = path.join(destDir, basename);
|
|
150
|
+
|
|
76
151
|
fs.mkdirSync(destDir, { recursive: true });
|
|
77
|
-
fs.
|
|
152
|
+
fs.writeFileSync(dest, converted, 'utf-8');
|
|
78
153
|
count++;
|
|
79
|
-
console.log(`[wowok-skills] installed: ${dir} → ${
|
|
154
|
+
console.log(`[wowok-skills] installed: ${dir} → ${dest}`);
|
|
80
155
|
}
|
|
81
156
|
|
|
82
157
|
return count;
|
|
@@ -97,19 +172,55 @@ function uninstallSkills(targetDir) {
|
|
|
97
172
|
return count;
|
|
98
173
|
}
|
|
99
174
|
|
|
175
|
+
function getTargets() {
|
|
176
|
+
const envTargets = process.env.WOWOK_SKILLS_TARGETS;
|
|
177
|
+
if (!envTargets) {
|
|
178
|
+
return ['claude'];
|
|
179
|
+
}
|
|
180
|
+
return envTargets.split(',').map(t => t.trim()).filter(t => CLIENT_DIRS[t]);
|
|
181
|
+
}
|
|
182
|
+
|
|
100
183
|
function main() {
|
|
101
184
|
const event = process.env.npm_lifecycle_event || '';
|
|
102
185
|
|
|
103
186
|
if (event === 'postinstall') {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
187
|
+
const targets = getTargets();
|
|
188
|
+
console.log(`[wowok-skills] Installing skills to ${targets.length} client(s)...`);
|
|
189
|
+
|
|
190
|
+
let total = 0;
|
|
191
|
+
for (const target of targets) {
|
|
192
|
+
const dir = CLIENT_DIRS[target];
|
|
193
|
+
console.log(`[wowok-skills] → ${dir}`);
|
|
194
|
+
const count = installSkills(dir, target);
|
|
195
|
+
total += count;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
console.log(`[wowok-skills] Done — ${total} skills installed across ${targets.length} client(s).`);
|
|
108
199
|
} else if (event === 'preuninstall') {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
200
|
+
const targets = Object.keys(CLIENT_DIRS);
|
|
201
|
+
console.log('[wowok-skills] Removing skills from all client dirs...');
|
|
202
|
+
|
|
203
|
+
let total = 0;
|
|
204
|
+
for (const target of targets) {
|
|
205
|
+
const dir = CLIENT_DIRS[target];
|
|
206
|
+
if (countExisting(dir) > 0) {
|
|
207
|
+
console.log(`[wowok-skills] → ${dir}`);
|
|
208
|
+
total += uninstallSkills(dir);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
console.log(`[wowok-skills] Done — ${total} skills removed.`);
|
|
112
213
|
}
|
|
113
214
|
}
|
|
114
215
|
|
|
216
|
+
function countExisting(targetDir) {
|
|
217
|
+
let count = 0;
|
|
218
|
+
for (const dir of SKILL_DIRS) {
|
|
219
|
+
if (fs.existsSync(path.join(targetDir, dir))) {
|
|
220
|
+
count++;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return count;
|
|
224
|
+
}
|
|
225
|
+
|
|
115
226
|
main();
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wowok-messenger
|
|
3
|
+
description: |
|
|
4
|
+
WoWok Messenger — end-to-end encrypted communication for pre-order negotiation,
|
|
5
|
+
evidence collection, and dispute resolution.
|
|
6
|
+
|
|
7
|
+
Core features: send/receive encrypted messages, generate WTS evidence files,
|
|
8
|
+
verify message authenticity, manage conversation lists, and integrate with
|
|
9
|
+
arbitration workflows.
|
|
10
|
+
|
|
11
|
+
Used by customers, service providers, and arbitrators for secure off-chain
|
|
12
|
+
communication that creates tamper-proof audit trails.
|
|
13
|
+
when_to_use:
|
|
14
|
+
- User needs to communicate with another party (buyer, seller, arbitrator)
|
|
15
|
+
- User wants to send encrypted messages for negotiation
|
|
16
|
+
- User needs to generate WTS evidence files from conversations
|
|
17
|
+
- User wants to verify message authenticity
|
|
18
|
+
- User needs to manage conversation lists (friends, blacklist, guard)
|
|
19
|
+
- User mentions "messenger", "message", "chat", "communication", "WTS", "evidence"
|
|
20
|
+
always: false
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# WoWok Messenger Guide
|
|
24
|
+
|
|
25
|
+
End-to-end encrypted messaging for secure off-chain business communication with tamper-proof audit trails.
|
|
26
|
+
|
|
27
|
+
> **Role**: Any WoWok participant (customer, service provider, arbitrator)
|
|
28
|
+
> **Prerequisites**: Understand the tool pattern — use `schema_query({ action: "get", name: "messenger_operation" })`
|
|
29
|
+
> **Guard Design**: See [wowok-guard](../wowok-guard/SKILL.md) if configuring guard-based spam protection
|
|
30
|
+
> **Tool Reference**: See [wowok-tools](../wowok-tools/SKILL.md) for MCP tool schemas
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Core Concepts
|
|
35
|
+
|
|
36
|
+
### Trust Model
|
|
37
|
+
|
|
38
|
+
The messenger operates on a **triple-trust model**. For detailed architecture and communication mechanisms, see the [Messenger Deep Dive Documentation](https://github.com/wowok-ai/docs/blob/main/docs/stage-03b-messenger.md).
|
|
39
|
+
|
|
40
|
+
**Key Design Decisions**:
|
|
41
|
+
- Messages are **NOT on-chain**. Communication is off-chain for privacy and cost efficiency.
|
|
42
|
+
- The server **cannot read** messages. Ciphertext is opaque; only endpoints hold decryption keys.
|
|
43
|
+
- The server **proves message order**. Its Falcon512 signature on the Merkle tree is verifiable by anyone.
|
|
44
|
+
- On-chain proof is **optional**. A message's Merkle root can be anchored to the blockchain via `proof_message`.
|
|
45
|
+
|
|
46
|
+
### Evidence Closure Principle
|
|
47
|
+
|
|
48
|
+
> **A message becomes valid evidence ONLY when the recipient explicitly responds to or decrypts it.**
|
|
49
|
+
|
|
50
|
+
One-sided claims are not evidence. The system enforces this through cryptographic and behavioral rules:
|
|
51
|
+
- A message alone proves nothing about the recipient's awareness.
|
|
52
|
+
- ARK confirmation (recipient-signed receipt) creates cryptographic proof both parties acknowledge the message.
|
|
53
|
+
- A reply is the strongest form of acknowledgment — it proves the recipient held the session key and acted on the message.
|
|
54
|
+
- WTS files include both sides of the conversation for complete context.
|
|
55
|
+
- Arbitration requires **confirmed**, reciprocated evidence — never unilateral claims.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 1. Message Delivery Mechanism
|
|
60
|
+
|
|
61
|
+
### 1.1 Message Delivery & Stranger Rules
|
|
62
|
+
Messages from **strangers** (addresses not in the recipient's friends list) are subject to additional restrictions:
|
|
63
|
+
|
|
64
|
+
- **One-message limit**: A stranger may send exactly one message. Until the recipient replies, any further messages from the same stranger are rejected.
|
|
65
|
+
- **Reply unlocks**: When the recipient replies, the stranger is automatically added to the recipient's friends list, and both parties can message freely thereafter.
|
|
66
|
+
- **Cool-down window**: The one-message restriction persists for a configurable duration. If the recipient does not reply within this window, the stranger may retry one message.
|
|
67
|
+
- **Recipient opt-out**: A recipient can disable stranger messages entirely. When blocked, the sender receives the recipient's guard list as an alternative contact path.
|
|
68
|
+
|
|
69
|
+
**Rationale**: This design prevents unsolicited spam while allowing legitimate first contact. The one-message limit forces the stranger to make their opening message count, and auto-friend-on-reply ensures smooth continuation once the recipient engages.
|
|
70
|
+
|
|
71
|
+
### 1.2 Guard Message Flow (Spam-Bypass Path)
|
|
72
|
+
|
|
73
|
+
When a sender provides both `guardAddress` and `passportAddress`, the server verifies the guard and passport are valid. On success the message is delivered; on failure the sender is notified.
|
|
74
|
+
|
|
75
|
+
**When to use**: When the recipient has disabled stranger messages and you are not in their friends list, the rejection response includes the recipient's guard list. Obtain a valid passport from one of those guards and resend with both `guardAddress` and `passportAddress`.
|
|
76
|
+
|
|
77
|
+
### 1.3 Session and Message Sequence
|
|
78
|
+
|
|
79
|
+
Every conversation between two addresses has a deterministic session, ensuring both parties share the same session context. Messages are ordered by a monotonically increasing index starting from zero, establishing their absolute position in the conversation.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 2. Anti-Spam Mechanism
|
|
84
|
+
|
|
85
|
+
### 2.1 Protection Model
|
|
86
|
+
|
|
87
|
+
Messages are evaluated in four sequential layers: **Blacklist** → **Friends List** → **Guard Verification** → **Stranger Rules**. See the [technical documentation](https://github.com/wowok-ai/docs/blob/main/docs/stage-03b-messenger.md) for implementation details.
|
|
88
|
+
|
|
89
|
+
### 2.2 List Management
|
|
90
|
+
|
|
91
|
+
Three independently managed lists control who can reach you:
|
|
92
|
+
|
|
93
|
+
| List | Purpose | Operations | Hard Limits |
|
|
94
|
+
|------|---------|------------|-------------|
|
|
95
|
+
| **Blacklist** | Block specific addresses completely | `add`, `remove`, `clear`, `get`, `exist` | Server-configured max (default 1000) |
|
|
96
|
+
| **Friends List** | Allow trusted contacts to bypass all checks | `add`, `remove`, `clear`, `get`, `exist` | Server-configured max (default 1000) |
|
|
97
|
+
| **Guard List** | Specify which guards can verify strangers | `add`, `remove`, `get` | Server-configured max (default 100) |
|
|
98
|
+
|
|
99
|
+
**Tool**: `messenger_operation` with `blacklist`, `friendslist`, or `guardlist` operation.
|
|
100
|
+
|
|
101
|
+
**Guard List Configuration**: Each entry requires:
|
|
102
|
+
- `guard`: The on-chain Guard object ID or name (see [wowok-guard](../wowok-guard/SKILL.md) for Guard design)
|
|
103
|
+
- `passportValiditySeconds`: How long a passport from this guard remains valid for messaging (typically 60s to 7 days)
|
|
104
|
+
|
|
105
|
+
Strangers with a valid passport from any guard in your list can message you. Passports are generated via `onchain_operations` with `gen_passport`.
|
|
106
|
+
|
|
107
|
+
### 2.3 Settings Control
|
|
108
|
+
|
|
109
|
+
Each user can configure two spam-protection parameters:
|
|
110
|
+
|
|
111
|
+
**Tool**: `messenger_operation` with `settings` operation (`get` or `set`).
|
|
112
|
+
|
|
113
|
+
- **`allowStrangerMessages`**: Toggle whether strangers (non-friends, non-guard-verified) can send you messages at all.
|
|
114
|
+
- `true` (default): Strangers can send one message each (subject to the one-message limit).
|
|
115
|
+
- `false`: All stranger messages are rejected. The rejection response includes your `guard_list` so the sender can obtain a passport and retry.
|
|
116
|
+
|
|
117
|
+
- **`maxInboxSize`**: Maximum messages retained in your inbox (typically 10–1000). Older messages are removed when the limit is reached.
|
|
118
|
+
|
|
119
|
+
**Note**: The server also has global defaults for these settings.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 3. WTS (Witness Timestamped Sequence) Mechanism
|
|
124
|
+
|
|
125
|
+
### 3.1 What WTS Is
|
|
126
|
+
|
|
127
|
+
A WTS file is a **tamper-proof, self-verifying export** of a **continuous** conversation message sequence between two parties. Every message in the chain is cryptographically linked to its predecessor; any gap or modification breaks the entire chain, making tampering immediately detectable. Participant signatures can be added for non-repudiation. Anyone can use a WTS file to verify the authenticity, continuity, and integrity of the conversation content.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### 3.2 The Reciprocity Principle
|
|
131
|
+
|
|
132
|
+
> **Only messages that the other party has replied to have evidentiary value.**
|
|
133
|
+
|
|
134
|
+
A message alone proves nothing about the recipient's awareness. When the **recipient replies**, their reply references the last message they received, creating cryptographic proof of receipt. A WTS file shows the full conversation — which messages were acknowledged and which were not.
|
|
135
|
+
|
|
136
|
+
**In practice**: When generating WTS for arbitration, include the full conversation so the arbitrator can see who said what, who acknowledged what, and the exact sequence of events.
|
|
137
|
+
|
|
138
|
+
### 3.3 WTS Workflow
|
|
139
|
+
|
|
140
|
+
**Step 1 — Generate WTS**:
|
|
141
|
+
|
|
142
|
+
**Tool**: `messenger_operation` with `generate_wts` operation.
|
|
143
|
+
|
|
144
|
+
Key decisions:
|
|
145
|
+
- **Range selection**: Choose which messages to include by time range, message ID range, or sequence index (leafIndex) range.
|
|
146
|
+
- **Output**: One or more `.wts` files are written to the specified output directory (files are split if the total exceeds file size limits).
|
|
147
|
+
|
|
148
|
+
**Step 2 — Sign WTS**:
|
|
149
|
+
|
|
150
|
+
**Tool**: `messenger_operation` with `sign_wts` operation.
|
|
151
|
+
|
|
152
|
+
Adds your Falcon512 (post-quantum) signature to the WTS metadata, proving you endorse the conversation record as accurate. Multiple signatures from any party are supported — participants, arbitrators, or other third parties can all sign to attest to the content.
|
|
153
|
+
|
|
154
|
+
**Step 3 — Verify WTS**:
|
|
155
|
+
|
|
156
|
+
**Tool**: `messenger_operation` with `verify_wts` operation.
|
|
157
|
+
|
|
158
|
+
Verification validates each message's authenticity, the sequence's continuity, the payload's integrity, and all signatures added in Step 2. When all pass, the WTS is **proven authentic, complete, and untampered** — admissible as cryptographic evidence.
|
|
159
|
+
|
|
160
|
+
**Step 4 — Convert to HTML (optional)**:
|
|
161
|
+
|
|
162
|
+
**Tool**: `messenger_operation` with `wts2html` operation. Produces a human-readable HTML document.
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
**Step 5 — Submit as evidence**:
|
|
166
|
+
|
|
167
|
+
Use `send_file` to send the signed WTS file to an arbitrator's messenger address. The arbitrator can then independently verify the WTS using their own `verify_wts` call.
|
|
168
|
+
|
|
169
|
+
### 3.4 On-Chain Proof (Optional)
|
|
170
|
+
|
|
171
|
+
**Tool**: `messenger_operation` with `proof_message` operation.
|
|
172
|
+
|
|
173
|
+
Anchors a message to the WoWok blockchain, creating an **immutable on-chain timestamp** that proves the message existed before that point in time. Anyone can verify the message against this on-chain record independently.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 4. Role-Specific Patterns
|
|
178
|
+
|
|
179
|
+
### 4.1 Customer → Service Provider
|
|
180
|
+
|
|
181
|
+
**Order creation and information delivery**:
|
|
182
|
+
|
|
183
|
+
1. **Discover the service's messenger contact**:
|
|
184
|
+
- Query the Service object via `query_toolkit` with `query_type: "onchain_objects"` to extract `service.um` (Contact object ID)
|
|
185
|
+
- Query the Contact object to get `ims[].at` (list of messenger addresses the provider accepts messages at)
|
|
186
|
+
|
|
187
|
+
2. **Send required customer information** (post-order):
|
|
188
|
+
- After order creation, check the Service's `customer_required` field (phone, email, delivery address, etc.)
|
|
189
|
+
- **AI should prompt**: Ask if the user wants to save this information to `local_info` for future use, or retrieve existing info from `local_info_list` to avoid re-entry
|
|
190
|
+
- Retrieve matching private information from local storage using `query_toolkit` → `local_info_list`
|
|
191
|
+
- Send via `messenger_operation` with `send_message` to the provider's customer service address
|
|
192
|
+
- **Request explicit confirmation** — unconfirmed delivery may stall order progress
|
|
193
|
+
- If this is first contact, you have exactly one message — make it count
|
|
194
|
+
|
|
195
|
+
3. **WTS is for disputes only**: Generate WTS only when a disagreement escalates and arbitration evidence is required. Normal conversations are already preserved.
|
|
196
|
+
|
|
197
|
+
### 4.2 Service Provider → Customer
|
|
198
|
+
|
|
199
|
+
**Customer service response**:
|
|
200
|
+
|
|
201
|
+
1. **Check conversations**: Use `watch_conversations` to see pending inquiries.
|
|
202
|
+
2. **Respond promptly**: Use `send_message` to reply. Your reply automatically adds the customer to your friends list if they were a stranger.
|
|
203
|
+
3. **Document agreements**: For any commitments (pricing, timeline changes, custom work), confirm them in messages. These become evidence if disputes arise.
|
|
204
|
+
4. **WTS for disputes**: If a disagreement escalates, the provider may generate and sign WTS to demonstrate good faith and support their position.
|
|
205
|
+
|
|
206
|
+
**Best practices for providers**:
|
|
207
|
+
- Respond promptly to maintain trust
|
|
208
|
+
- Document all agreements and changes in messages
|
|
209
|
+
- Confirm understanding before proceeding with orders
|
|
210
|
+
- Use guard list to allow verified strangers to reach you without opening to all strangers
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 5. Operation Order and Dependencies
|
|
215
|
+
|
|
216
|
+
### 5.1 Account Setup Prerequisites
|
|
217
|
+
|
|
218
|
+
Before using the messenger, the account must be properly initialized:
|
|
219
|
+
|
|
220
|
+
1. **Account must exist**: Created via `account_operation` (LOCAL operation).
|
|
221
|
+
2. **Messenger must be enabled**: Set a messenger name on the account via `account_operation` to enable Messenger functionality; clear it to disable.
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
### 5.2 List and Settings Order
|
|
225
|
+
|
|
226
|
+
When configuring spam protection:
|
|
227
|
+
1. **Get current state**: Use `settings` (`get`) and list operations (`get`) to see the current configuration.
|
|
228
|
+
2. **Add trusted contacts**: Use `friendslist` (`add`) for known counterparties.
|
|
229
|
+
3. **Configure guards**: Use `guardlist` (`add`) if you want to accept verified strangers. The Guard objects must already exist on-chain (see [wowok-guard](../wowok-guard/SKILL.md)).
|
|
230
|
+
4. **Set stranger policy**: Use `settings` (`set`) with `allowStrangerMessages` to toggle stranger access.
|
|
231
|
+
5. **Block unwanted**: Use `blacklist` (`add`) for addresses you never want to hear from.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 6. Schema Reference
|
|
236
|
+
|
|
237
|
+
All messenger operations and their parameters are defined in a single schema:
|
|
238
|
+
|
|
239
|
+
**Query**: `schema_query({ action: "get", name: "messenger_operation" })`
|
|
240
|
+
|
|
241
|
+
This returns the complete discriminated union schema covering all 16 sub-operations with their parameter shapes and constraints.
|
|
242
|
+
|
|
243
|
+
Related schemas for cross-workflow operations:
|
|
244
|
+
|
|
245
|
+
| Purpose | Schema Name |
|
|
246
|
+
|---------|-------------|
|
|
247
|
+
| All messenger operations | `messenger_operation` |
|
|
248
|
+
| Query on-chain objects (services, guards, contacts) | `query_toolkit` |
|
|
249
|
+
| On-chain operations (gen_passport for guard) | `onchain_operations` |
|
|
250
|
+
| Local account management | `account_operation` |
|
|
251
|
+
| Local address book (marks) | `local_mark_operation` |
|
|
252
|
+
| Local private info storage | `local_info_operation` |
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 7. Quick Reference
|
|
256
|
+
|
|
257
|
+
### Messaging
|
|
258
|
+
|
|
259
|
+
| Goal | Operation | Key Parameters |
|
|
260
|
+
|------|-----------|----------------|
|
|
261
|
+
| Send text | `send_message` | `from`, `to`, `content`, `options.guardAddress?`, `options.passportAddress?` |
|
|
262
|
+
| Send file | `send_file` | `from`, `to`, `filePath`, `options.contentType?` |
|
|
263
|
+
| View conversations | `watch_conversations` | `filter.unreadOnly?`, `filter.previewMessageCount?`, `filter.sortBy?` |
|
|
264
|
+
| View messages | `watch_messages` | `filter.peerAddress?`, `filter.direction?`, `filter.contentType?`, `filter.keyword?` |
|
|
265
|
+
| Mark as read | `mark_messages_as_viewed` | `messageIds`, `account?` |
|
|
266
|
+
| Mark convo read | `mark_conversation_as_viewed` | `peerAddress`, `account?` |
|
|
267
|
+
|
|
268
|
+
### Evidence (WTS)
|
|
269
|
+
|
|
270
|
+
| Goal | Operation | Key Parameters |
|
|
271
|
+
|------|-----------|----------------|
|
|
272
|
+
| Export | `generate_wts` | `params.myAccount`, `params.peerAccount`, `params.range?`, `params.outputDir` |
|
|
273
|
+
| Sign | `sign_wts` | `wtsFilePath`, `account`, `outputPath?` |
|
|
274
|
+
| Verify | `verify_wts` | `wtsFilePath` |
|
|
275
|
+
| View HTML | `wts2html` | `wtsPath`, `options.title?`, `options.theme?` |
|
|
276
|
+
| Prove on-chain | `proof_message` | `account`, `messageId`, `network` |
|
|
277
|
+
| Extract ZIP | `extract_zip_messages` | `account`, `messages`, `outputDir` |
|
|
278
|
+
|
|
279
|
+
### List Management
|
|
280
|
+
|
|
281
|
+
| Goal | Operation | Key Parameters |
|
|
282
|
+
|------|-----------|----------------|
|
|
283
|
+
| Add friend | `friendslist` (`add`) | `account`, `users` (addresses/names) |
|
|
284
|
+
| Block user | `blacklist` (`add`) | `account`, `users` (addresses/names) |
|
|
285
|
+
| Add guard | `guardlist` (`add`) | `account`, `guards[].guard`, `guards[].passportValiditySeconds` |
|
|
286
|
+
| Toggle strangers | `settings` (`set`) | `account`, `allowStrangerMessages` |
|
|
287
|
+
|
|
288
|
+
### Local Storage
|
|
289
|
+
|
|
290
|
+
| Goal | Tool | Key Parameters |
|
|
291
|
+
|------|------|----------------|
|
|
292
|
+
| Write private info | `local_info_operation` (add) | `data`: array of `{ name, default, contents }` |
|
|
293
|
+
| Read private info | `query_toolkit` → `local_info_list` | `filter.name?` |
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wowok-output
|
|
3
|
+
description: |
|
|
4
|
+
WoWok output processing and display — post-processes all WoWok tool responses
|
|
5
|
+
for human-readable presentation. Handles address resolution, name mapping,
|
|
6
|
+
amount formatting, and data visualization.
|
|
7
|
+
when_to_use:
|
|
8
|
+
- AI has received response from any WoWok MCP tool
|
|
9
|
+
- Response contains addresses requiring name resolution
|
|
10
|
+
- Response contains amounts requiring human-readable formatting
|
|
11
|
+
- User queries on-chain data (events, objects, tables)
|
|
12
|
+
always: true
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Address Display Rules
|
|
16
|
+
|
|
17
|
+
## Override Condition
|
|
18
|
+
|
|
19
|
+
If user explicitly requests full/long addresses (e.g., "show full addresses", "do not abbreviate"),
|
|
20
|
+
this skill's shortening rules are DISABLED — display complete 66-character addresses.
|
|
21
|
+
|
|
22
|
+
## Short Address Format
|
|
23
|
+
|
|
24
|
+
**MUST APPLY TO ALL ADDRESSES** (0x prefix + 64 hex chars = 66 chars total):
|
|
25
|
+
1. Remove `0x` prefix
|
|
26
|
+
2. Take first 5 characters
|
|
27
|
+
3. Convert to UPPERCASE
|
|
28
|
+
4. Wrap in parentheses `()`
|
|
29
|
+
|
|
30
|
+
**Example**: `0xa1d421902a3e5f2e4da7590e8f243712b3b3479d1a07c48c2de543184fc97a33` → `(A1D42)`
|
|
31
|
+
|
|
32
|
+
## Resolution Priority & Display Format
|
|
33
|
+
|
|
34
|
+
**Query Tool**: `query_toolkit` with `query_type: "local_names"`
|
|
35
|
+
|
|
36
|
+
Returns: `{ account?: string, local_mark?: string, address: string }`
|
|
37
|
+
|
|
38
|
+
### Display Format Rules (STRICT)
|
|
39
|
+
|
|
40
|
+
| Condition | Display Format | Example |
|
|
41
|
+
|-----------|----------------|---------|
|
|
42
|
+
| **Both account AND local_mark exist** | `{account_name} \| {local_mark_name} (ABCDE)` | `alice \| my_mark (A1D42)` |
|
|
43
|
+
| **Only account exists** | `{account_name} (ABCDE)` | `alice_wallet (A1D42)` |
|
|
44
|
+
| **Only local_mark exists** | `{local_mark_name} (ABCDE)` | `my_service (A1D42)` |
|
|
45
|
+
| **Neither exists** | `(ABCDE)` | `(A1D42)` |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Name Length Limit
|
|
50
|
+
|
|
51
|
+
- **Maximum display length**: 20 characters
|
|
52
|
+
- **Overflow handling**: Truncate to 17 chars + `...`
|
|
53
|
+
- **Example**: `three_body_signature_service_v2` → `three_body_sig...`
|
|
54
|
+
|
|
55
|
+
# Amount Formatting Rules
|
|
56
|
+
|
|
57
|
+
## Conservative Principle
|
|
58
|
+
|
|
59
|
+
**When in doubt, display raw value.**
|
|
60
|
+
|
|
61
|
+
| Condition | Display | Example |
|
|
62
|
+
|-----------|---------|---------|
|
|
63
|
+
| Token info UNAVAILABLE | Raw amount | `500000000` |
|
|
64
|
+
| Token info AVAILABLE | Converted + symbol + precision | `0.5 WOW (9P)` |
|
|
65
|
+
|
|
66
|
+
## Conversion Requirements
|
|
67
|
+
|
|
68
|
+
ONLY convert when ALL conditions met:
|
|
69
|
+
1. Token type explicitly identified
|
|
70
|
+
2. Successfully queried via `query_toolkit` with `query_type: "token_list"`
|
|
71
|
+
3. Metadata contains valid `decimals` and `symbol`
|
|
72
|
+
|
|
73
|
+
**Formula**: `converted = raw / (10 ^ decimals)`
|
|
74
|
+
**Format**: `{amount} {symbol} ({decimals}P)`
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
# Event Display Format
|
|
79
|
+
|
|
80
|
+
## Table Format
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
| # | Time | Sender | Service | Amount | Order |
|
|
84
|
+
|---|------|--------|---------|--------|-------|
|
|
85
|
+
| 1 | {time} | {name} (ABCDE) | {name} (ABCDE) | {amount} | (ABCDE) |
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Note**: `{name}` follows Display Format Rules above (account | local_mark). If no name, show only `(ABCDE)`.
|
|
89
|
+
|
|
90
|
+
## Event Type Fields
|
|
91
|
+
|
|
92
|
+
| Event Type | Key Fields |
|
|
93
|
+
|------------|------------|
|
|
94
|
+
| `NewOrderEvent` | sender, service, amount, object |
|
|
95
|
+
| `ProgressEvent` | order, operator, machine |
|
|
96
|
+
| `ArbEvent` | arbitration, voter, order, service |
|
|
97
|
+
| `DemandPresentEvent` | demand, presenter, service |
|
|
98
|
+
| `DemandFeedbackEvent` | demand, feedbacker |
|
|
99
|
+
| `NewEntityEvent` | entity |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
# Field Explanations
|
|
104
|
+
|
|
105
|
+
When user asks about field meanings:
|
|
106
|
+
|
|
107
|
+
## Addresses
|
|
108
|
+
- **Sender**: Account that initiated the transaction
|
|
109
|
+
- **Service**: Service object being ordered/interacted with
|
|
110
|
+
- **Order Object**: Unique on-chain identifier for this order
|
|
111
|
+
- **Short Address (ABCDE)**: First 5 chars for quick visual identification
|
|
112
|
+
|
|
113
|
+
## Amounts
|
|
114
|
+
- **Raw**: Actual U64 integer stored on-chain
|
|
115
|
+
- **Converted**: Human-readable after applying decimals
|
|
116
|
+
- **Precision (XP)**: Number of decimal places
|
|
117
|
+
|
|
118
|
+
## Time
|
|
119
|
+
- **Timestamp**: Unix milliseconds since epoch
|
|
120
|
+
- **Human-readable**: Converted local time
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
# Implementation Checklist
|
|
125
|
+
|
|
126
|
+
- [ ] Extract unique addresses from response
|
|
127
|
+
- [ ] Query `local_names` for resolution
|
|
128
|
+
- [ ] Query `token_list` for amount formatting
|
|
129
|
+
- [ ] Apply address format rules
|
|
130
|
+
- [ ] Apply amount format rules (conservative)
|
|
131
|
+
- [ ] Render final output
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
# Related Skills
|
|
136
|
+
|
|
137
|
+
| Skill | Purpose |
|
|
138
|
+
|-------|---------|
|
|
139
|
+
| [wowok-safety](../wowok-safety/SKILL.md) | Pre-operation safety checks |
|
|
140
|
+
| [wowok-tools](../wowok-tools/SKILL.md) | Tool selection patterns |
|
|
141
|
+
| [wowok-order](../wowok-order/SKILL.md) | Order lifecycle (buyer) |
|
|
142
|
+
| [wowok-provider](../wowok-provider/SKILL.md) | Service management (merchant) |
|