@xpr-agents/openclaw 0.3.0 → 0.3.2
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 +22 -7
- package/package.json +1 -1
- package/skills/code-sandbox/dist/index.js +188 -0
- package/skills/creative/dist/index.js +667 -0
- package/skills/defi/dist/index.js +1744 -0
- package/skills/nft/dist/index.js +1526 -0
- package/skills/shellbook/dist/index.js +381 -0
- package/skills/smart-contracts/dist/index.js +1225 -0
- package/skills/tax/dist/index.js +1565 -0
- package/skills/xpr-agent-operator/SKILL.md +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @xpr-agents/openclaw
|
|
2
2
|
|
|
3
|
-
OpenClaw plugin for the XPR Network Trustless Agent Registry —
|
|
3
|
+
OpenClaw plugin for the XPR Network Trustless Agent Registry — 72 MCP tools for AI assistants to autonomously manage agents, jobs, feedback, validations, and escrow on-chain.
|
|
4
4
|
|
|
5
5
|
## XPR Agents Ecosystem
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ OpenClaw plugin for the XPR Network Trustless Agent Registry — 55 MCP tools fo
|
|
|
8
8
|
|---------|-------------|
|
|
9
9
|
| [`create-xpr-agent`](https://www.npmjs.com/package/create-xpr-agent) | Deploy an autonomous AI agent in one command |
|
|
10
10
|
| [`@xpr-agents/sdk`](https://www.npmjs.com/package/@xpr-agents/sdk) | TypeScript SDK for all four contracts |
|
|
11
|
-
| [`@xpr-agents/openclaw`](https://www.npmjs.com/package/@xpr-agents/openclaw) |
|
|
11
|
+
| [`@xpr-agents/openclaw`](https://www.npmjs.com/package/@xpr-agents/openclaw) | 72 MCP tools for AI assistants |
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
@@ -42,16 +42,31 @@ cd my-agent
|
|
|
42
42
|
|
|
43
43
|
## Configuration
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
The plugin signs transactions by shelling out to the [proton CLI](https://www.npmjs.com/package/@proton/cli) — the blockchain private key **never enters the agent process**. Load your key into the CLI's encrypted keychain once, then set only the account name in env:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# One-time keychain setup
|
|
49
|
+
npm i -g @proton/cli
|
|
50
|
+
proton chain:set proton # or proton-test
|
|
51
|
+
proton key:add # paste your PVT_K1_ key; stored encrypted
|
|
52
|
+
# Or for hosted consoles without a real TTY:
|
|
53
|
+
# echo "no" | proton key:add PVT_K1_yourkey
|
|
54
|
+
```
|
|
46
55
|
|
|
47
56
|
```env
|
|
48
57
|
XPR_ACCOUNT=myagent
|
|
49
|
-
|
|
50
|
-
XPR_RPC_ENDPOINT=https://
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
XPR_NETWORK=mainnet # or testnet
|
|
59
|
+
XPR_RPC_ENDPOINT=https://proton.eosusa.io
|
|
60
|
+
MAX_TRANSFER_AMOUNT=10000000 # smallest units, 10000000 = 1000 XPR
|
|
61
|
+
|
|
62
|
+
# Optional: separate key for A2A request signing (proton CLI can't sign
|
|
63
|
+
# arbitrary digests). Register on a custom permission with NO on-chain
|
|
64
|
+
# powers so a leak only damages reputation, not funds.
|
|
65
|
+
# A2A_SIGNING_KEY=PVT_K1_a2a_only_key
|
|
53
66
|
```
|
|
54
67
|
|
|
68
|
+
> **There is no `XPR_PRIVATE_KEY` env var.** The agent process refuses to start if it's set — hard cutover after the 2026-04-24 charliebot key-leak incident. See [`docs/A2A.md`](https://github.com/XPRNetwork/xpr-agents/blob/main/docs/A2A.md) for the A2A signing key model.
|
|
69
|
+
|
|
55
70
|
## License
|
|
56
71
|
|
|
57
72
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xpr-agents/openclaw",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "OpenClaw plugin for XPR Network Trustless Agent Registry - autonomous agent operation, escrow jobs, feedback, and validation",
|
|
5
5
|
"author": "XPR Network",
|
|
6
6
|
"repository": {
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Code Sandbox Skill — execute JavaScript in a sandboxed V8 context
|
|
4
|
+
*
|
|
5
|
+
* Zero external dependencies — uses Node.js built-in `vm` module.
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.default = codeSandboxSkill;
|
|
12
|
+
const vm_1 = __importDefault(require("vm"));
|
|
13
|
+
// ── Constants ───────────────────────────────────
|
|
14
|
+
const DEFAULT_TIMEOUT = 5000;
|
|
15
|
+
const MAX_TIMEOUT = 30000;
|
|
16
|
+
const MAX_OUTPUT_SIZE = 10 * 1024 * 1024; // 10MB
|
|
17
|
+
// ── Sandbox helpers ─────────────────────────────
|
|
18
|
+
function createSandboxGlobals(input, logs) {
|
|
19
|
+
// Capture console methods
|
|
20
|
+
const consoleMock = {
|
|
21
|
+
log: (...args) => {
|
|
22
|
+
logs.push(args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
|
|
23
|
+
},
|
|
24
|
+
warn: (...args) => {
|
|
25
|
+
logs.push('[warn] ' + args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
|
|
26
|
+
},
|
|
27
|
+
error: (...args) => {
|
|
28
|
+
logs.push('[error] ' + args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
INPUT: input,
|
|
33
|
+
console: consoleMock,
|
|
34
|
+
JSON,
|
|
35
|
+
Math,
|
|
36
|
+
Date,
|
|
37
|
+
Array,
|
|
38
|
+
Object,
|
|
39
|
+
String,
|
|
40
|
+
Number,
|
|
41
|
+
RegExp,
|
|
42
|
+
Map,
|
|
43
|
+
Set,
|
|
44
|
+
parseInt,
|
|
45
|
+
parseFloat,
|
|
46
|
+
isNaN,
|
|
47
|
+
isFinite,
|
|
48
|
+
encodeURIComponent,
|
|
49
|
+
decodeURIComponent,
|
|
50
|
+
atob: (s) => Buffer.from(s, 'base64').toString('binary'),
|
|
51
|
+
btoa: (s) => Buffer.from(s, 'binary').toString('base64'),
|
|
52
|
+
// Explicitly undefined — blocked
|
|
53
|
+
require: undefined,
|
|
54
|
+
process: undefined,
|
|
55
|
+
globalThis: undefined,
|
|
56
|
+
global: undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function serializeResult(value) {
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
return 'undefined';
|
|
62
|
+
try {
|
|
63
|
+
const str = JSON.stringify(value, null, 2);
|
|
64
|
+
if (str.length > MAX_OUTPUT_SIZE) {
|
|
65
|
+
return str.slice(0, MAX_OUTPUT_SIZE) + '\n... [truncated at 10MB]';
|
|
66
|
+
}
|
|
67
|
+
return str;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return String(value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// ── Skill entry point ───────────────────────────
|
|
74
|
+
function codeSandboxSkill(api) {
|
|
75
|
+
// ── execute_js ──
|
|
76
|
+
api.registerTool({
|
|
77
|
+
name: 'execute_js',
|
|
78
|
+
description: [
|
|
79
|
+
'Run JavaScript code in a sandboxed V8 context.',
|
|
80
|
+
'Pass data via "input" (JSON), access it as INPUT in code.',
|
|
81
|
+
'console.log/warn/error are captured in the "logs" array.',
|
|
82
|
+
'Available: JSON, Math, Date, Array, Object, String, Number, RegExp, Map, Set,',
|
|
83
|
+
'parseInt, parseFloat, isNaN, isFinite, encodeURIComponent, decodeURIComponent, atob, btoa.',
|
|
84
|
+
'No network, filesystem, require, or import access. Max 30s timeout, 10MB output.',
|
|
85
|
+
].join(' '),
|
|
86
|
+
parameters: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
required: ['code'],
|
|
89
|
+
properties: {
|
|
90
|
+
code: { type: 'string', description: 'JavaScript code to execute. The last expression value is returned as the result.' },
|
|
91
|
+
input: { description: 'Optional JSON data available as INPUT in the code.' },
|
|
92
|
+
timeout: { type: 'number', description: 'Execution timeout in milliseconds (default 5000, max 30000).' },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
handler: async ({ code, input, timeout }) => {
|
|
96
|
+
if (!code || typeof code !== 'string') {
|
|
97
|
+
return { error: 'code parameter is required and must be a string' };
|
|
98
|
+
}
|
|
99
|
+
const timeoutMs = Math.min(Math.max(timeout || DEFAULT_TIMEOUT, 100), MAX_TIMEOUT);
|
|
100
|
+
const logs = [];
|
|
101
|
+
const startTime = Date.now();
|
|
102
|
+
try {
|
|
103
|
+
const globals = createSandboxGlobals(input, logs);
|
|
104
|
+
const context = vm_1.default.createContext(globals, {
|
|
105
|
+
codeGeneration: { strings: false, wasm: false },
|
|
106
|
+
});
|
|
107
|
+
// Wrap code so the last expression is returned
|
|
108
|
+
const wrapped = `(function() {\n${code}\n})()`;
|
|
109
|
+
const script = new vm_1.default.Script(wrapped, { filename: 'sandbox.js' });
|
|
110
|
+
const result = script.runInContext(context, { timeout: timeoutMs });
|
|
111
|
+
const durationMs = Date.now() - startTime;
|
|
112
|
+
const serialized = serializeResult(result);
|
|
113
|
+
if (serialized.length > MAX_OUTPUT_SIZE) {
|
|
114
|
+
return {
|
|
115
|
+
result: serialized.slice(0, 1000) + '... [truncated]',
|
|
116
|
+
logs,
|
|
117
|
+
duration_ms: durationMs,
|
|
118
|
+
warning: 'Output exceeded 10MB limit and was truncated',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Parse back to preserve types (arrays, objects)
|
|
122
|
+
let parsed;
|
|
123
|
+
try {
|
|
124
|
+
parsed = JSON.parse(serialized);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
parsed = serialized === 'undefined' ? undefined : serialized;
|
|
128
|
+
}
|
|
129
|
+
return { result: parsed, logs, duration_ms: durationMs };
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
const durationMs = Date.now() - startTime;
|
|
133
|
+
const message = err.message || String(err);
|
|
134
|
+
// Provide helpful error context
|
|
135
|
+
if (message.includes('Script execution timed out')) {
|
|
136
|
+
return { error: `Execution timed out after ${timeoutMs}ms. Keep code efficient or increase timeout (max ${MAX_TIMEOUT}ms).`, logs, duration_ms: durationMs };
|
|
137
|
+
}
|
|
138
|
+
if (message.includes('Code generation from strings disallowed')) {
|
|
139
|
+
return { error: 'eval() and Function() constructor are blocked in the sandbox. Use direct code instead.', logs, duration_ms: durationMs };
|
|
140
|
+
}
|
|
141
|
+
return { error: message, logs, duration_ms: durationMs };
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
// ── eval_expression ──
|
|
146
|
+
api.registerTool({
|
|
147
|
+
name: 'eval_expression',
|
|
148
|
+
description: [
|
|
149
|
+
'Evaluate a single JavaScript expression and return the result.',
|
|
150
|
+
'Lightweight alternative to execute_js for quick calculations.',
|
|
151
|
+
'Examples: "15 * 4500 * 0.01", "new Date().toISOString()", "[1,2,3].map(x => x*x)".',
|
|
152
|
+
].join(' '),
|
|
153
|
+
parameters: {
|
|
154
|
+
type: 'object',
|
|
155
|
+
required: ['expression'],
|
|
156
|
+
properties: {
|
|
157
|
+
expression: { type: 'string', description: 'A JavaScript expression to evaluate.' },
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
handler: async ({ expression }) => {
|
|
161
|
+
if (!expression || typeof expression !== 'string') {
|
|
162
|
+
return { error: 'expression parameter is required and must be a string' };
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
const globals = createSandboxGlobals(undefined, []);
|
|
166
|
+
const context = vm_1.default.createContext(globals, {
|
|
167
|
+
codeGeneration: { strings: false, wasm: false },
|
|
168
|
+
});
|
|
169
|
+
const script = new vm_1.default.Script(`(${expression})`, { filename: 'expr.js' });
|
|
170
|
+
const result = script.runInContext(context, { timeout: DEFAULT_TIMEOUT });
|
|
171
|
+
let serialized;
|
|
172
|
+
try {
|
|
173
|
+
serialized = JSON.parse(JSON.stringify(result));
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
serialized = String(result);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
result: serialized,
|
|
180
|
+
type: result === null ? 'null' : Array.isArray(result) ? 'array' : typeof result,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
return { error: err.message || String(err) };
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|