chitin-openclaw-plugin 0.2.2 → 0.3.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/dist/index.js +87 -22
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -12,6 +12,12 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
12
12
|
import { baseSepolia } from "viem/chains";
|
|
13
13
|
import WebSocket from "ws";
|
|
14
14
|
import { execFile } from "child_process";
|
|
15
|
+
import { trace, SpanStatusCode } from "@opentelemetry/api";
|
|
16
|
+
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
17
|
+
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
|
|
18
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
19
|
+
import { Resource } from "@opentelemetry/resources";
|
|
20
|
+
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
15
21
|
var ERC20_ABI = parseAbi([
|
|
16
22
|
"function balanceOf(address) view returns (uint256)",
|
|
17
23
|
"function transferAndCall(address to, uint256 amount, bytes data) returns (bool)",
|
|
@@ -100,12 +106,18 @@ function connectToTable(gameServerUrl, roomCode, playerId, name, walletAddress,
|
|
|
100
106
|
}
|
|
101
107
|
function promptAgent(text, logger2) {
|
|
102
108
|
logger2.info(`[chitin] Prompting agent: ${text.slice(0, 100)}...`);
|
|
103
|
-
execFile("openclaw", ["agent", "--local", "--message", text],
|
|
109
|
+
const child = execFile("openclaw", ["agent", "--local", "--message", text], {
|
|
110
|
+
timeout: 12e4,
|
|
111
|
+
env: process.env
|
|
112
|
+
// Inherit HOME pointing to workspace
|
|
113
|
+
}, (err, stdout, stderr) => {
|
|
104
114
|
if (err) {
|
|
105
115
|
logger2.error(`[chitin] Agent prompt failed: ${err.message}`);
|
|
116
|
+
if (stderr) logger2.error(`[chitin] Agent stderr: ${stderr.slice(0, 500)}`);
|
|
106
117
|
return;
|
|
107
118
|
}
|
|
108
|
-
if (
|
|
119
|
+
if (stdout) logger2.info(`[chitin] Agent response: ${stdout.slice(0, 300)}`);
|
|
120
|
+
if (stderr) logger2.warn(`[chitin] Agent stderr: ${stderr.slice(0, 300)}`);
|
|
109
121
|
logger2.info(`[chitin] Agent prompted ok`);
|
|
110
122
|
});
|
|
111
123
|
}
|
|
@@ -115,6 +127,7 @@ function connectToTable(gameServerUrl, roomCode, playerId, name, walletAddress,
|
|
|
115
127
|
ws?.close();
|
|
116
128
|
};
|
|
117
129
|
}
|
|
130
|
+
var otelInitialized = false;
|
|
118
131
|
var plugin = {
|
|
119
132
|
id: "chitin-openclaw-plugin",
|
|
120
133
|
name: "Chitin Casino",
|
|
@@ -126,6 +139,58 @@ var plugin = {
|
|
|
126
139
|
},
|
|
127
140
|
register(api) {
|
|
128
141
|
api.logger.info("[chitin] Chitin Casino plugin loaded");
|
|
142
|
+
let tracer = trace.getTracer("chitin-plugin");
|
|
143
|
+
if (!otelInitialized) try {
|
|
144
|
+
otelInitialized = true;
|
|
145
|
+
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
146
|
+
const headers = process.env.OTEL_EXPORTER_OTLP_HEADERS;
|
|
147
|
+
if (endpoint) {
|
|
148
|
+
const headerObj = {};
|
|
149
|
+
if (headers) {
|
|
150
|
+
for (const pair of headers.split(",")) {
|
|
151
|
+
const [k, ...v] = pair.split("=");
|
|
152
|
+
if (k) headerObj[k.trim()] = v.join("=").trim();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const provider = new NodeTracerProvider({
|
|
156
|
+
resource: new Resource({ [ATTR_SERVICE_NAME]: "chitin-plugin" }),
|
|
157
|
+
spanProcessors: [
|
|
158
|
+
new BatchSpanProcessor(new OTLPTraceExporter({
|
|
159
|
+
url: `${endpoint}/v1/traces`,
|
|
160
|
+
headers: headerObj
|
|
161
|
+
}))
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
provider.register();
|
|
165
|
+
tracer = trace.getTracer("chitin-plugin");
|
|
166
|
+
api.logger.info(`[chitin] OTel initialized \u2014 endpoint=${endpoint}`);
|
|
167
|
+
const span = tracer.startSpan("plugin.loaded");
|
|
168
|
+
span.setAttributes({ "plugin.name": "chitin-openclaw-plugin" });
|
|
169
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
170
|
+
span.end();
|
|
171
|
+
api.logger.info("[chitin] OTel test span emitted: plugin.loaded");
|
|
172
|
+
} else {
|
|
173
|
+
api.logger.info("[chitin] OTel skipped \u2014 no OTEL_EXPORTER_OTLP_ENDPOINT");
|
|
174
|
+
}
|
|
175
|
+
} catch (err) {
|
|
176
|
+
api.logger.warn(`[chitin] OTel init failed (non-fatal): ${err.message}`);
|
|
177
|
+
}
|
|
178
|
+
function withSpan(spanName, attrs, fn) {
|
|
179
|
+
const span = tracer.startSpan(spanName, { attributes: attrs });
|
|
180
|
+
return fn().then(
|
|
181
|
+
(result) => {
|
|
182
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
183
|
+
span.end();
|
|
184
|
+
return result;
|
|
185
|
+
},
|
|
186
|
+
(err) => {
|
|
187
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
|
|
188
|
+
span.recordException(err);
|
|
189
|
+
span.end();
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
}
|
|
129
194
|
const gameServerUrl = process.env.GAME_SERVER_URL || "http://localhost:3665";
|
|
130
195
|
const adminServerUrl = process.env.ADMIN_SERVER_URL || "http://localhost:3667";
|
|
131
196
|
const activeConnections = /* @__PURE__ */ new Map();
|
|
@@ -134,11 +199,11 @@ var plugin = {
|
|
|
134
199
|
name: "chitin_wallet_address",
|
|
135
200
|
description: "Get your Chitin Casino wallet address",
|
|
136
201
|
parameters: {},
|
|
137
|
-
execute: async () => {
|
|
202
|
+
execute: async () => withSpan("plugin.tool.wallet_address", {}, async () => {
|
|
138
203
|
const { account } = getWalletClients();
|
|
139
204
|
api.logger.info(`[chitin] wallet_address: ${account.address}`);
|
|
140
205
|
return { address: account.address };
|
|
141
|
-
}
|
|
206
|
+
})
|
|
142
207
|
});
|
|
143
208
|
api.registerTool({
|
|
144
209
|
name: "chitin_wallet_balance",
|
|
@@ -149,7 +214,7 @@ var plugin = {
|
|
|
149
214
|
tokenAddress: { type: "string", description: "Token address (auto-fetched if omitted)" }
|
|
150
215
|
}
|
|
151
216
|
},
|
|
152
|
-
execute: async (_toolCallId, params) => {
|
|
217
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.wallet_balance", {}, async () => {
|
|
153
218
|
const { account, publicClient } = getWalletClients();
|
|
154
219
|
api.logger.info(`[chitin] wallet_balance: checking ${account.address}`);
|
|
155
220
|
const ethBalance = await publicClient.getBalance({ address: account.address });
|
|
@@ -180,13 +245,13 @@ var plugin = {
|
|
|
180
245
|
ethBalance: formatEther(ethBalance),
|
|
181
246
|
tokenBalance: formatEther(tokenBalance)
|
|
182
247
|
};
|
|
183
|
-
}
|
|
248
|
+
})
|
|
184
249
|
});
|
|
185
250
|
api.registerTool({
|
|
186
251
|
name: "chitin_faucet_claim",
|
|
187
252
|
description: "Claim NUMERO tokens from the faucet. Free \u2014 no gas needed.",
|
|
188
253
|
parameters: {},
|
|
189
|
-
execute: async () => {
|
|
254
|
+
execute: async () => withSpan("plugin.tool.faucet_claim", {}, async () => {
|
|
190
255
|
const { account } = getWalletClients();
|
|
191
256
|
api.logger.info(`[chitin] faucet_claim: wallet=${account.address} server=${adminServerUrl}`);
|
|
192
257
|
const res = await fetch(`${adminServerUrl}/faucet/claim`, {
|
|
@@ -198,7 +263,7 @@ var plugin = {
|
|
|
198
263
|
api.logger.info(`[chitin] faucet_claim: status=${res.status} response=${JSON.stringify(data)}`);
|
|
199
264
|
if (!res.ok) throw new Error(data.error || "Faucet claim failed");
|
|
200
265
|
return data;
|
|
201
|
-
}
|
|
266
|
+
})
|
|
202
267
|
});
|
|
203
268
|
api.registerTool({
|
|
204
269
|
name: "chitin_deposit",
|
|
@@ -212,7 +277,7 @@ var plugin = {
|
|
|
212
277
|
},
|
|
213
278
|
required: ["amount", "tableId", "gameId"]
|
|
214
279
|
},
|
|
215
|
-
execute: async (_toolCallId, params) => {
|
|
280
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.deposit", { "deposit.amount": params.amount, "deposit.table_id": params.tableId }, async () => {
|
|
216
281
|
api.logger.info(`[chitin] deposit: amount=${params.amount} tableId=${params.tableId} gameId=${params.gameId}`);
|
|
217
282
|
const { publicClient, walletClient } = getWalletClients();
|
|
218
283
|
api.logger.info(`[chitin] deposit: fetching contracts from ${gameServerUrl}/contracts`);
|
|
@@ -235,31 +300,31 @@ var plugin = {
|
|
|
235
300
|
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
236
301
|
api.logger.info(`[chitin] deposit: confirmed block=${receipt.blockNumber} status=${receipt.status}`);
|
|
237
302
|
return { txHash: hash, blockNumber: Number(receipt.blockNumber) };
|
|
238
|
-
}
|
|
303
|
+
})
|
|
239
304
|
});
|
|
240
305
|
api.registerTool({
|
|
241
306
|
name: "chitin_discover",
|
|
242
307
|
description: "Discover Chitin Casino \u2014 games, contracts, faucet info",
|
|
243
308
|
parameters: {},
|
|
244
|
-
execute: async () => {
|
|
309
|
+
execute: async () => withSpan("plugin.tool.discover", {}, async () => {
|
|
245
310
|
api.logger.info(`[chitin] discover: ${gameServerUrl}/discover`);
|
|
246
311
|
const res = await fetch(`${gameServerUrl}/discover`);
|
|
247
312
|
const data = await res.json();
|
|
248
313
|
api.logger.info(`[chitin] discover: status=${res.status}`);
|
|
249
314
|
return data;
|
|
250
|
-
}
|
|
315
|
+
})
|
|
251
316
|
});
|
|
252
317
|
api.registerTool({
|
|
253
318
|
name: "chitin_lobby",
|
|
254
319
|
description: "List poker tables with open seats",
|
|
255
320
|
parameters: {},
|
|
256
|
-
execute: async () => {
|
|
321
|
+
execute: async () => withSpan("plugin.tool.lobby", {}, async () => {
|
|
257
322
|
api.logger.info(`[chitin] lobby: ${gameServerUrl}/parties/pokerlobby/main/tables`);
|
|
258
323
|
const res = await fetch(`${gameServerUrl}/parties/pokerlobby/main/tables`);
|
|
259
324
|
const data = await res.json();
|
|
260
325
|
api.logger.info(`[chitin] lobby: status=${res.status} tables=${Array.isArray(data) ? data.length : "?"}`);
|
|
261
326
|
return data;
|
|
262
|
-
}
|
|
327
|
+
})
|
|
263
328
|
});
|
|
264
329
|
api.registerTool({
|
|
265
330
|
name: "chitin_create_table",
|
|
@@ -273,7 +338,7 @@ var plugin = {
|
|
|
273
338
|
maxBuyIn: { type: "number" }
|
|
274
339
|
}
|
|
275
340
|
},
|
|
276
|
-
execute: async (_toolCallId, params) => {
|
|
341
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.create_table", {}, async () => {
|
|
277
342
|
const settings = {
|
|
278
343
|
smallBlind: params.smallBlind || 1,
|
|
279
344
|
bigBlind: params.bigBlind || 2,
|
|
@@ -289,7 +354,7 @@ var plugin = {
|
|
|
289
354
|
const data = await res.json();
|
|
290
355
|
api.logger.info(`[chitin] create_table: status=${res.status} response=${JSON.stringify(data)}`);
|
|
291
356
|
return data;
|
|
292
|
-
}
|
|
357
|
+
})
|
|
293
358
|
});
|
|
294
359
|
api.registerTool({
|
|
295
360
|
name: "chitin_register",
|
|
@@ -303,7 +368,7 @@ var plugin = {
|
|
|
303
368
|
},
|
|
304
369
|
required: ["roomCode"]
|
|
305
370
|
},
|
|
306
|
-
execute: async (_toolCallId, params) => {
|
|
371
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.register", { "register.room": params.roomCode }, async () => {
|
|
307
372
|
const { account } = getWalletClients();
|
|
308
373
|
const botName = params.name || "ClawBot";
|
|
309
374
|
api.logger.info(`[chitin] register: room=${params.roomCode} name=${botName} buyIn=${params.buyIn || 200} wallet=${account.address}`);
|
|
@@ -330,7 +395,7 @@ var plugin = {
|
|
|
330
395
|
);
|
|
331
396
|
activeConnections.set(params.roomCode, { cleanup });
|
|
332
397
|
return { ...result, wsConnected: true };
|
|
333
|
-
}
|
|
398
|
+
})
|
|
334
399
|
});
|
|
335
400
|
api.registerTool({
|
|
336
401
|
name: "chitin_poker_action",
|
|
@@ -344,7 +409,7 @@ var plugin = {
|
|
|
344
409
|
},
|
|
345
410
|
required: ["roomCode", "action"]
|
|
346
411
|
},
|
|
347
|
-
execute: async (_toolCallId, params) => {
|
|
412
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.poker_action", { "action.room": params.roomCode, "action.type": params.action, "action.amount": params.amount ?? 0 }, async () => {
|
|
348
413
|
api.logger.info(`[chitin] poker_action: room=${params.roomCode} action=${params.action} amount=${params.amount ?? "n/a"}`);
|
|
349
414
|
const ws = wsInstances.get(params.roomCode);
|
|
350
415
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
@@ -356,7 +421,7 @@ var plugin = {
|
|
|
356
421
|
ws.send(JSON.stringify({ type: "action", action }));
|
|
357
422
|
api.logger.info(`[chitin] poker_action: sent ${JSON.stringify(action)}`);
|
|
358
423
|
return { ok: true, sent: action };
|
|
359
|
-
}
|
|
424
|
+
})
|
|
360
425
|
});
|
|
361
426
|
api.registerTool({
|
|
362
427
|
name: "chitin_leave_table",
|
|
@@ -369,7 +434,7 @@ var plugin = {
|
|
|
369
434
|
},
|
|
370
435
|
required: ["roomCode", "token"]
|
|
371
436
|
},
|
|
372
|
-
execute: async (_toolCallId, params) => {
|
|
437
|
+
execute: async (_toolCallId, params) => withSpan("plugin.tool.leave_table", { "leave.room": params.roomCode }, async () => {
|
|
373
438
|
api.logger.info(`[chitin] leave_table: room=${params.roomCode}`);
|
|
374
439
|
const ws = wsInstances.get(params.roomCode);
|
|
375
440
|
if (ws?.readyState === WebSocket.OPEN) {
|
|
@@ -391,7 +456,7 @@ var plugin = {
|
|
|
391
456
|
return await res.json();
|
|
392
457
|
}
|
|
393
458
|
return { ok: true };
|
|
394
|
-
}
|
|
459
|
+
})
|
|
395
460
|
});
|
|
396
461
|
}
|
|
397
462
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chitin-openclaw-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "OpenClaw plugin for Chitin Casino — wallet management and poker game connection",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"prepublishOnly": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"@opentelemetry/api": "^1.9.0",
|
|
34
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
|
|
35
|
+
"@opentelemetry/resources": "^1.30.0",
|
|
36
|
+
"@opentelemetry/sdk-trace-node": "^1.30.0",
|
|
37
|
+
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
33
38
|
"viem": "^2.0.0",
|
|
34
39
|
"ws": "^8.0.0"
|
|
35
40
|
},
|