chitin-openclaw-plugin 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.
Files changed (2) hide show
  1. package/dist/index.js +69 -21
  2. package/package.json +10 -5
package/dist/index.js CHANGED
@@ -18,6 +18,11 @@ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
18
18
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
19
19
  import { Resource } from "@opentelemetry/resources";
20
20
  import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
21
+ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
22
+ import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici";
23
+ import { logs, SeverityNumber } from "@opentelemetry/api-logs";
24
+ import { LoggerProvider, BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
25
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
21
26
  var ERC20_ABI = parseAbi([
22
27
  "function balanceOf(address) view returns (uint256)",
23
28
  "function transferAndCall(address to, uint256 amount, bytes data) returns (bool)",
@@ -127,6 +132,7 @@ function connectToTable(gameServerUrl, roomCode, playerId, name, walletAddress,
127
132
  ws?.close();
128
133
  };
129
134
  }
135
+ var otelInitialized = false;
130
136
  var plugin = {
131
137
  id: "chitin-openclaw-plugin",
132
138
  name: "Chitin Casino",
@@ -139,7 +145,8 @@ var plugin = {
139
145
  register(api) {
140
146
  api.logger.info("[chitin] Chitin Casino plugin loaded");
141
147
  let tracer = trace.getTracer("chitin-plugin");
142
- try {
148
+ if (!otelInitialized) try {
149
+ otelInitialized = true;
143
150
  const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
144
151
  const headers = process.env.OTEL_EXPORTER_OTLP_HEADERS;
145
152
  if (endpoint) {
@@ -160,6 +167,17 @@ var plugin = {
160
167
  ]
161
168
  });
162
169
  provider.register();
170
+ new HttpInstrumentation().enable();
171
+ new UndiciInstrumentation().enable();
172
+ const logProvider = new LoggerProvider({
173
+ resource: new Resource({ [ATTR_SERVICE_NAME]: "chitin-plugin" }),
174
+ processors: [
175
+ new BatchLogRecordProcessor(
176
+ new OTLPLogExporter({ url: `${endpoint}/v1/logs`, headers: headerObj })
177
+ )
178
+ ]
179
+ });
180
+ logs.setGlobalLoggerProvider(logProvider);
163
181
  tracer = trace.getTracer("chitin-plugin");
164
182
  api.logger.info(`[chitin] OTel initialized \u2014 endpoint=${endpoint}`);
165
183
  const span = tracer.startSpan("plugin.loaded");
@@ -173,6 +191,36 @@ var plugin = {
173
191
  } catch (err) {
174
192
  api.logger.warn(`[chitin] OTel init failed (non-fatal): ${err.message}`);
175
193
  }
194
+ const otelLogger = logs.getLogger("chitin-plugin");
195
+ const originalLogger = { ...api.logger };
196
+ const severityMap = {
197
+ info: SeverityNumber.INFO,
198
+ warn: SeverityNumber.WARN,
199
+ error: SeverityNumber.ERROR,
200
+ debug: SeverityNumber.DEBUG
201
+ };
202
+ for (const level of ["info", "warn", "error", "debug"]) {
203
+ api.logger[level] = (msg, ...args) => {
204
+ originalLogger[level](msg, ...args);
205
+ otelLogger.emit({ severityNumber: severityMap[level], severityText: level.toUpperCase(), body: msg });
206
+ };
207
+ }
208
+ function withSpan(spanName, attrs, fn) {
209
+ const span = tracer.startSpan(spanName, { attributes: attrs });
210
+ return fn().then(
211
+ (result) => {
212
+ span.setStatus({ code: SpanStatusCode.OK });
213
+ span.end();
214
+ return result;
215
+ },
216
+ (err) => {
217
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
218
+ span.recordException(err);
219
+ span.end();
220
+ throw err;
221
+ }
222
+ );
223
+ }
176
224
  const gameServerUrl = process.env.GAME_SERVER_URL || "http://localhost:3665";
177
225
  const adminServerUrl = process.env.ADMIN_SERVER_URL || "http://localhost:3667";
178
226
  const activeConnections = /* @__PURE__ */ new Map();
@@ -181,11 +229,11 @@ var plugin = {
181
229
  name: "chitin_wallet_address",
182
230
  description: "Get your Chitin Casino wallet address",
183
231
  parameters: {},
184
- execute: async () => {
232
+ execute: async () => withSpan("plugin.tool.wallet_address", {}, async () => {
185
233
  const { account } = getWalletClients();
186
234
  api.logger.info(`[chitin] wallet_address: ${account.address}`);
187
235
  return { address: account.address };
188
- }
236
+ })
189
237
  });
190
238
  api.registerTool({
191
239
  name: "chitin_wallet_balance",
@@ -196,7 +244,7 @@ var plugin = {
196
244
  tokenAddress: { type: "string", description: "Token address (auto-fetched if omitted)" }
197
245
  }
198
246
  },
199
- execute: async (_toolCallId, params) => {
247
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.wallet_balance", {}, async () => {
200
248
  const { account, publicClient } = getWalletClients();
201
249
  api.logger.info(`[chitin] wallet_balance: checking ${account.address}`);
202
250
  const ethBalance = await publicClient.getBalance({ address: account.address });
@@ -227,13 +275,13 @@ var plugin = {
227
275
  ethBalance: formatEther(ethBalance),
228
276
  tokenBalance: formatEther(tokenBalance)
229
277
  };
230
- }
278
+ })
231
279
  });
232
280
  api.registerTool({
233
281
  name: "chitin_faucet_claim",
234
282
  description: "Claim NUMERO tokens from the faucet. Free \u2014 no gas needed.",
235
283
  parameters: {},
236
- execute: async () => {
284
+ execute: async () => withSpan("plugin.tool.faucet_claim", {}, async () => {
237
285
  const { account } = getWalletClients();
238
286
  api.logger.info(`[chitin] faucet_claim: wallet=${account.address} server=${adminServerUrl}`);
239
287
  const res = await fetch(`${adminServerUrl}/faucet/claim`, {
@@ -245,7 +293,7 @@ var plugin = {
245
293
  api.logger.info(`[chitin] faucet_claim: status=${res.status} response=${JSON.stringify(data)}`);
246
294
  if (!res.ok) throw new Error(data.error || "Faucet claim failed");
247
295
  return data;
248
- }
296
+ })
249
297
  });
250
298
  api.registerTool({
251
299
  name: "chitin_deposit",
@@ -259,7 +307,7 @@ var plugin = {
259
307
  },
260
308
  required: ["amount", "tableId", "gameId"]
261
309
  },
262
- execute: async (_toolCallId, params) => {
310
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.deposit", { "deposit.amount": params.amount, "deposit.table_id": params.tableId }, async () => {
263
311
  api.logger.info(`[chitin] deposit: amount=${params.amount} tableId=${params.tableId} gameId=${params.gameId}`);
264
312
  const { publicClient, walletClient } = getWalletClients();
265
313
  api.logger.info(`[chitin] deposit: fetching contracts from ${gameServerUrl}/contracts`);
@@ -282,31 +330,31 @@ var plugin = {
282
330
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
283
331
  api.logger.info(`[chitin] deposit: confirmed block=${receipt.blockNumber} status=${receipt.status}`);
284
332
  return { txHash: hash, blockNumber: Number(receipt.blockNumber) };
285
- }
333
+ })
286
334
  });
287
335
  api.registerTool({
288
336
  name: "chitin_discover",
289
337
  description: "Discover Chitin Casino \u2014 games, contracts, faucet info",
290
338
  parameters: {},
291
- execute: async () => {
339
+ execute: async () => withSpan("plugin.tool.discover", {}, async () => {
292
340
  api.logger.info(`[chitin] discover: ${gameServerUrl}/discover`);
293
341
  const res = await fetch(`${gameServerUrl}/discover`);
294
342
  const data = await res.json();
295
343
  api.logger.info(`[chitin] discover: status=${res.status}`);
296
344
  return data;
297
- }
345
+ })
298
346
  });
299
347
  api.registerTool({
300
348
  name: "chitin_lobby",
301
349
  description: "List poker tables with open seats",
302
350
  parameters: {},
303
- execute: async () => {
351
+ execute: async () => withSpan("plugin.tool.lobby", {}, async () => {
304
352
  api.logger.info(`[chitin] lobby: ${gameServerUrl}/parties/pokerlobby/main/tables`);
305
353
  const res = await fetch(`${gameServerUrl}/parties/pokerlobby/main/tables`);
306
354
  const data = await res.json();
307
355
  api.logger.info(`[chitin] lobby: status=${res.status} tables=${Array.isArray(data) ? data.length : "?"}`);
308
356
  return data;
309
- }
357
+ })
310
358
  });
311
359
  api.registerTool({
312
360
  name: "chitin_create_table",
@@ -320,7 +368,7 @@ var plugin = {
320
368
  maxBuyIn: { type: "number" }
321
369
  }
322
370
  },
323
- execute: async (_toolCallId, params) => {
371
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.create_table", {}, async () => {
324
372
  const settings = {
325
373
  smallBlind: params.smallBlind || 1,
326
374
  bigBlind: params.bigBlind || 2,
@@ -336,7 +384,7 @@ var plugin = {
336
384
  const data = await res.json();
337
385
  api.logger.info(`[chitin] create_table: status=${res.status} response=${JSON.stringify(data)}`);
338
386
  return data;
339
- }
387
+ })
340
388
  });
341
389
  api.registerTool({
342
390
  name: "chitin_register",
@@ -350,7 +398,7 @@ var plugin = {
350
398
  },
351
399
  required: ["roomCode"]
352
400
  },
353
- execute: async (_toolCallId, params) => {
401
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.register", { "register.room": params.roomCode }, async () => {
354
402
  const { account } = getWalletClients();
355
403
  const botName = params.name || "ClawBot";
356
404
  api.logger.info(`[chitin] register: room=${params.roomCode} name=${botName} buyIn=${params.buyIn || 200} wallet=${account.address}`);
@@ -377,7 +425,7 @@ var plugin = {
377
425
  );
378
426
  activeConnections.set(params.roomCode, { cleanup });
379
427
  return { ...result, wsConnected: true };
380
- }
428
+ })
381
429
  });
382
430
  api.registerTool({
383
431
  name: "chitin_poker_action",
@@ -391,7 +439,7 @@ var plugin = {
391
439
  },
392
440
  required: ["roomCode", "action"]
393
441
  },
394
- execute: async (_toolCallId, params) => {
442
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.poker_action", { "action.room": params.roomCode, "action.type": params.action, "action.amount": params.amount ?? 0 }, async () => {
395
443
  api.logger.info(`[chitin] poker_action: room=${params.roomCode} action=${params.action} amount=${params.amount ?? "n/a"}`);
396
444
  const ws = wsInstances.get(params.roomCode);
397
445
  if (!ws || ws.readyState !== WebSocket.OPEN) {
@@ -403,7 +451,7 @@ var plugin = {
403
451
  ws.send(JSON.stringify({ type: "action", action }));
404
452
  api.logger.info(`[chitin] poker_action: sent ${JSON.stringify(action)}`);
405
453
  return { ok: true, sent: action };
406
- }
454
+ })
407
455
  });
408
456
  api.registerTool({
409
457
  name: "chitin_leave_table",
@@ -416,7 +464,7 @@ var plugin = {
416
464
  },
417
465
  required: ["roomCode", "token"]
418
466
  },
419
- execute: async (_toolCallId, params) => {
467
+ execute: async (_toolCallId, params) => withSpan("plugin.tool.leave_table", { "leave.room": params.roomCode }, async () => {
420
468
  api.logger.info(`[chitin] leave_table: room=${params.roomCode}`);
421
469
  const ws = wsInstances.get(params.roomCode);
422
470
  if (ws?.readyState === WebSocket.OPEN) {
@@ -438,7 +486,7 @@ var plugin = {
438
486
  return await res.json();
439
487
  }
440
488
  return { ok: true };
441
- }
489
+ })
442
490
  });
443
491
  }
444
492
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chitin-openclaw-plugin",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "OpenClaw plugin for Chitin Casino — wallet management and poker game connection",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,15 +25,20 @@
25
25
  "extensions": ["./dist/index.js"]
26
26
  },
27
27
  "scripts": {
28
- "build": "tsup src/index.ts --format esm --dts",
28
+ "build": "tsup src/index.ts --format esm",
29
29
  "dev": "tsup src/index.ts --format esm --watch",
30
30
  "prepublishOnly": "npm run build"
31
31
  },
32
32
  "dependencies": {
33
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",
34
+ "@opentelemetry/api-logs": "^0.214.0",
35
+ "@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
36
+ "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
37
+ "@opentelemetry/instrumentation-http": "^0.214.0",
38
+ "@opentelemetry/instrumentation-undici": "^0.24.0",
39
+ "@opentelemetry/resources": "^2.6.0",
40
+ "@opentelemetry/sdk-logs": "^0.214.0",
41
+ "@opentelemetry/sdk-trace-node": "^2.6.0",
37
42
  "@opentelemetry/semantic-conventions": "^1.28.0",
38
43
  "viem": "^2.0.0",
39
44
  "ws": "^8.0.0"