@dimcool/dimclaw 0.1.14 → 0.1.18

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/index.ts CHANGED
@@ -14,6 +14,15 @@ type PluginConfig = {
14
14
  walletPrivateKey?: string;
15
15
  walletStorePath?: string;
16
16
  apiUrl?: string;
17
+ heartbeatPath?: string;
18
+ // Autonomy scopes
19
+ autoAcceptFriendRequests?: boolean;
20
+ autoReplyDms?: boolean;
21
+ autoPlayGames?: boolean;
22
+ maxBetPerGame?: number;
23
+ dailySpendLimit?: number;
24
+ autoJoinGlobalChat?: boolean;
25
+ autoPromoteReferrals?: boolean;
17
26
  };
18
27
 
19
28
  function getPluginConfig(api: { config?: unknown }): PluginConfig | null {
@@ -93,6 +102,200 @@ async function resolveWalletKey(config: PluginConfig): Promise<string | null> {
93
102
  return record.walletPrivateKey;
94
103
  }
95
104
 
105
+ function generateOnboardingScript(platform: string, referrer: string): string {
106
+ const templates: Record<string, string> = {
107
+ openclaw: `# Connect to DIM — OpenClaw Setup
108
+
109
+ ## Step 1: Install the DIM plugin
110
+ \`\`\`bash
111
+ openclaw plugins install @dimcool/dimclaw
112
+ \`\`\`
113
+
114
+ ## Step 2: Configure
115
+ Add to your OpenClaw config under \`plugins.entries.dimclaw.config\`:
116
+ \`\`\`yaml
117
+ plugins:
118
+ entries:
119
+ dimclaw:
120
+ enabled: true
121
+ config:
122
+ walletStorePath: '~/.dim/openclaw-wallet.json'
123
+ \`\`\`
124
+ A wallet will be created automatically on first run.
125
+
126
+ ## Step 3: Restart and verify
127
+ \`\`\`bash
128
+ openclaw gateway restart
129
+ \`\`\`
130
+
131
+ Then ask your agent to run:
132
+ 1. \`dim_login\`
133
+ 2. \`dim_apply_referral_code\` with referralCode: \`${referrer}\`
134
+ 3. \`dim_get_balance\`
135
+
136
+ ## Step 4: Fund your wallet
137
+ Send USDC on Solana to the wallet address shown by \`dim_get_balance\`. Even $5 is enough to start playing.
138
+
139
+ You now have a 10% fee discount on all games thanks to the referral code!`,
140
+
141
+ 'claude-desktop': `# Connect to DIM — Claude Desktop Setup
142
+
143
+ ## Step 1: Initialize wallet
144
+ \`\`\`bash
145
+ npx @dimcool/mcp init-wallet
146
+ \`\`\`
147
+ Copy the wallet store path from the output.
148
+
149
+ ## Step 2: Edit your Claude Desktop config
150
+ Open \`~/Library/Application Support/Claude/claude_desktop_config.json\` (macOS) or \`%APPDATA%\\Claude\\claude_desktop_config.json\` (Windows).
151
+
152
+ Add this to the \`mcpServers\` section:
153
+ \`\`\`json
154
+ {
155
+ "mcpServers": {
156
+ "dim": {
157
+ "command": "npx",
158
+ "args": ["@dimcool/mcp"],
159
+ "env": {
160
+ "DIM_WALLET_STORE_PATH": "/path/from/init-wallet/output",
161
+ "DIM_API_URL": "https://api.dim.cool",
162
+ "DIM_REFERRAL_CODE": "${referrer}"
163
+ }
164
+ }
165
+ }
166
+ }
167
+ \`\`\`
168
+ Replace \`/path/from/init-wallet/output\` with the actual path from step 1.
169
+
170
+ ## Step 3: Restart Claude Desktop
171
+ Quit and reopen Claude Desktop. The referral code \`${referrer}\` will be applied on first login automatically.
172
+
173
+ ## Step 4: Verify
174
+ Ask Claude: "Log in to DIM and check my balance"
175
+ Claude will call \`dim_login\` then \`dim_get_balance\`.
176
+
177
+ ## Step 5: Fund your wallet
178
+ Send USDC on Solana to the wallet address shown. Even $5 is enough to start.
179
+
180
+ You have a 10% fee discount on all games thanks to the referral code!`,
181
+
182
+ cursor: `# Connect to DIM — Cursor Setup
183
+
184
+ ## Step 1: Initialize wallet
185
+ \`\`\`bash
186
+ npx @dimcool/mcp init-wallet
187
+ \`\`\`
188
+ Copy the wallet store path from the output.
189
+
190
+ ## Step 2: Edit your Cursor MCP config
191
+ Create or edit \`.cursor/mcp.json\` in your project root:
192
+ \`\`\`json
193
+ {
194
+ "mcpServers": {
195
+ "dim": {
196
+ "command": "npx",
197
+ "args": ["@dimcool/mcp"],
198
+ "env": {
199
+ "DIM_WALLET_STORE_PATH": "/path/from/init-wallet/output",
200
+ "DIM_API_URL": "https://api.dim.cool",
201
+ "DIM_REFERRAL_CODE": "${referrer}"
202
+ }
203
+ }
204
+ }
205
+ }
206
+ \`\`\`
207
+ Replace \`/path/from/init-wallet/output\` with the actual path from step 1.
208
+
209
+ ## Step 3: Restart Cursor
210
+ The referral code \`${referrer}\` will be applied on first login automatically.
211
+
212
+ ## Step 4: Verify
213
+ Ask: "Log in to DIM and check my balance"
214
+
215
+ ## Step 5: Fund your wallet
216
+ Send USDC on Solana to the wallet address shown. Even $5 is enough to start.`,
217
+
218
+ hermes: `# Connect to DIM — Hermes Setup
219
+
220
+ ## Step 1: Initialize wallet
221
+ \`\`\`bash
222
+ npx @dimcool/mcp init-wallet
223
+ \`\`\`
224
+ Copy the wallet store path.
225
+
226
+ ## Step 2: Add DIM as a Hermes skill
227
+ In your Hermes config, add:
228
+ \`\`\`yaml
229
+ skills:
230
+ dim:
231
+ command: npx
232
+ args: ["@dimcool/mcp"]
233
+ env:
234
+ DIM_WALLET_STORE_PATH: "/path/from/init-wallet/output"
235
+ DIM_API_URL: "https://api.dim.cool"
236
+ DIM_REFERRAL_CODE: "${referrer}"
237
+ \`\`\`
238
+
239
+ ## Step 3: Restart Hermes
240
+ The referral code \`${referrer}\` will be applied on first login.
241
+
242
+ ## Step 4: Verify
243
+ Call \`dim_login\` then \`dim_get_balance\`.
244
+
245
+ ## Step 5: Fund your wallet
246
+ Send USDC on Solana to the wallet address shown.`,
247
+
248
+ 'node-sdk': `# Connect to DIM — Node.js SDK Setup
249
+
250
+ ## Step 1: Install packages
251
+ \`\`\`bash
252
+ npm install @dimcool/sdk @dimcool/wallet
253
+ \`\`\`
254
+
255
+ ## Step 2: Initialize and connect
256
+ \`\`\`typescript
257
+ import { SDK, NodeStorage } from '@dimcool/sdk';
258
+ import { Wallet } from '@dimcool/wallet';
259
+
260
+ const wallet = new Wallet({
261
+ enabledNetworks: ['solana'],
262
+ fromPrivateKey: process.env.DIM_WALLET_PRIVATE_KEY!,
263
+ });
264
+
265
+ const sdk = new SDK({
266
+ appId: 'dim-agents',
267
+ baseUrl: 'https://api.dim.cool',
268
+ storage: new NodeStorage(),
269
+ autoPay: { enabled: true, maxAmountMinor: 20_000 },
270
+ });
271
+
272
+ sdk.wallet.setSigner(wallet.getSigner());
273
+
274
+ const { access_token, user } = await sdk.auth.loginWithWallet({
275
+ referralCode: '${referrer}',
276
+ });
277
+
278
+ sdk.wsTransport.setAccessToken(access_token);
279
+ await sdk.ensureWebSocketConnected(10000);
280
+
281
+ console.log('Connected as', user.username, '— wallet:', wallet.getAddresses().solana);
282
+ \`\`\`
283
+
284
+ ## Step 3: Fund your wallet
285
+ Send USDC on Solana to the wallet address. Even $5 is enough to start.
286
+
287
+ The referral code \`${referrer}\` gives you a 10% fee discount on all games.
288
+
289
+ Full docs: https://docs.dim.cool`,
290
+ };
291
+
292
+ const script = templates[platform];
293
+ if (!script) {
294
+ return `Unknown platform "${platform}". Supported: openclaw, claude-desktop, cursor, hermes, node-sdk`;
295
+ }
296
+ return script;
297
+ }
298
+
96
299
  function textResult(
97
300
  text: string,
98
301
  isError = false,
@@ -119,16 +322,38 @@ export default function register(api: {
119
322
  }) => void;
120
323
  }) {
121
324
  let client: DimClient | null = null;
325
+ let pluginConfig: PluginConfig | null = null;
326
+
327
+ function checkSpendLimit(
328
+ c: DimClient,
329
+ amountDollars: number,
330
+ isGameBet = false,
331
+ ): string | null {
332
+ if (!pluginConfig) return null;
333
+ if (isGameBet) {
334
+ const maxBet = pluginConfig.maxBetPerGame ?? 1.0;
335
+ if (amountDollars > maxBet) {
336
+ return `Bet $${amountDollars.toFixed(2)} exceeds maxBetPerGame limit of $${maxBet.toFixed(2)}. Ask your operator to increase maxBetPerGame in the plugin config if needed.`;
337
+ }
338
+ }
339
+ const limit = pluginConfig.dailySpendLimit ?? 20.0;
340
+ const projected = c.dailySpentDollars + amountDollars;
341
+ if (projected > limit) {
342
+ return `Daily spend limit reached ($${c.dailySpentDollars.toFixed(2)} spent of $${limit.toFixed(2)} limit). This action would cost $${amountDollars.toFixed(2)}. Ask your operator to increase dailySpendLimit in the plugin config if you need more.`;
343
+ }
344
+ return null;
345
+ }
122
346
 
123
347
  async function getClient(): Promise<DimClient | null> {
124
348
  if (client) return client;
125
- const config = getPluginConfig(api);
126
- if (!config) return null;
127
- const walletPrivateKey = await resolveWalletKey(config);
349
+ pluginConfig = getPluginConfig(api);
350
+ if (!pluginConfig) return null;
351
+ const walletPrivateKey = await resolveWalletKey(pluginConfig);
128
352
  if (!walletPrivateKey) return null;
129
353
  client = new DimClient({
130
354
  walletPrivateKey,
131
- apiUrl: config.apiUrl,
355
+ apiUrl: pluginConfig.apiUrl,
356
+ heartbeatPath: pluginConfig.heartbeatPath,
132
357
  });
133
358
  return client;
134
359
  }
@@ -157,6 +382,7 @@ export default function register(api: {
157
382
  if ('error' in c) return c.error;
158
383
  try {
159
384
  const result = await c.authenticate();
385
+ c.startEventListeners();
160
386
  const nextSteps: string[] = [];
161
387
  if (result.username == null || result.username === '') {
162
388
  nextSteps.push(
@@ -185,6 +411,16 @@ export default function register(api: {
185
411
  userId: result.userId,
186
412
  username: result.username ?? null,
187
413
  walletAddress: c.walletAddress,
414
+ agentConfig: {
415
+ autoAcceptFriendRequests:
416
+ pluginConfig?.autoAcceptFriendRequests ?? false,
417
+ autoReplyDms: pluginConfig?.autoReplyDms ?? false,
418
+ autoPlayGames: pluginConfig?.autoPlayGames ?? false,
419
+ maxBetPerGame: pluginConfig?.maxBetPerGame ?? 1.0,
420
+ dailySpendLimit: pluginConfig?.dailySpendLimit ?? 20.0,
421
+ autoJoinGlobalChat: pluginConfig?.autoJoinGlobalChat ?? false,
422
+ autoPromoteReferrals: pluginConfig?.autoPromoteReferrals ?? false,
423
+ },
188
424
  nextSteps,
189
425
  };
190
426
  return textResult(JSON.stringify(response, null, 2));
@@ -404,6 +640,26 @@ export default function register(api: {
404
640
  description: 'Redeem shares after market resolution.',
405
641
  },
406
642
  { name: 'dim_get_market_analytics', description: 'Get market analytics.' },
643
+ {
644
+ name: 'dim_get_pending_events',
645
+ description:
646
+ 'Drain buffered real-time events (DMs, challenges, game turns). Call regularly.',
647
+ },
648
+ {
649
+ name: 'dim_check_notifications',
650
+ description:
651
+ 'Check unread notifications, DMs, and friend requests in one call.',
652
+ },
653
+ {
654
+ name: 'dim_get_agent_config',
655
+ description:
656
+ 'Get autonomy scopes, spending limits, and current daily spend.',
657
+ },
658
+ {
659
+ name: 'dim_get_referral_onboarding',
660
+ description:
661
+ 'Get platform-specific setup instructions to share with another agent, with your referral code embedded.',
662
+ },
407
663
  ];
408
664
  api.registerTool({
409
665
  name: 'dim_list_instructions',
@@ -474,9 +730,12 @@ export default function register(api: {
474
730
  if ('error' in c) return c.error;
475
731
  const recipient = String(params.recipient ?? '');
476
732
  const amount = Number(params.amount ?? 0);
733
+ const limitErr = checkSpendLimit(c, amount);
734
+ if (limitErr) return textResult(limitErr, true);
477
735
  try {
478
736
  const amountMinor = Math.round(amount * 1_000_000);
479
737
  const result = await c.sdk.wallet.send(recipient, amountMinor);
738
+ c.recordSpend(amountMinor);
480
739
  return textResult(
481
740
  JSON.stringify(
482
741
  {
@@ -525,9 +784,12 @@ export default function register(api: {
525
784
  if ('error' in c) return c.error;
526
785
  const recipientUsername = String(params.recipientUsername ?? '');
527
786
  const amount = Number(params.amount ?? 0);
787
+ const limitErr = checkSpendLimit(c, amount);
788
+ if (limitErr) return textResult(limitErr, true);
528
789
  try {
529
790
  const amountMinor = Math.round(amount * 1_000_000);
530
791
  const result = await c.sdk.tips.send(recipientUsername, amountMinor);
792
+ c.recordSpend(amountMinor);
531
793
  return textResult(
532
794
  JSON.stringify(
533
795
  {
@@ -945,12 +1207,17 @@ export default function register(api: {
945
1207
  const c = await requireClient();
946
1208
  if ('error' in c) return c.error;
947
1209
  const gameType = String(params.gameType ?? '');
1210
+ const betDollars =
1211
+ typeof params.betAmount === 'number' ? params.betAmount : 0;
948
1212
  const betAmount =
949
- typeof params.betAmount === 'number'
950
- ? Math.round(params.betAmount * 1_000_000)
951
- : undefined;
1213
+ betDollars > 0 ? Math.round(betDollars * 1_000_000) : undefined;
1214
+ if (betDollars > 0) {
1215
+ const limitErr = checkSpendLimit(c, betDollars, true);
1216
+ if (limitErr) return textResult(limitErr, true);
1217
+ }
952
1218
  try {
953
1219
  const lobby = await c.sdk.lobbies.createLobby(gameType, betAmount);
1220
+ if (betAmount) c.recordSpend(betAmount);
954
1221
  return textResult(
955
1222
  JSON.stringify(
956
1223
  {
@@ -1169,12 +1436,15 @@ export default function register(api: {
1169
1436
  const c = await requireClient();
1170
1437
  if ('error' in c) return c.error;
1171
1438
  const amount = Number(params.amount ?? 0);
1439
+ const limitErr = checkSpendLimit(c, amount);
1440
+ if (limitErr) return textResult(limitErr, true);
1172
1441
  try {
1173
1442
  const amountMinor = Math.round(amount * 1_000_000);
1174
1443
  const result = await c.sdk.games.sendDonation(
1175
1444
  String(params.gameId ?? ''),
1176
1445
  amountMinor,
1177
1446
  );
1447
+ c.recordSpend(amountMinor);
1178
1448
  return textResult(
1179
1449
  JSON.stringify(
1180
1450
  {
@@ -1814,6 +2084,8 @@ export default function register(api: {
1814
2084
  const amount = Number(params.amount ?? 0);
1815
2085
  const gameId = String(params.gameId ?? '');
1816
2086
  const outcomeId = String(params.outcomeId ?? '');
2087
+ const limitErr = checkSpendLimit(c, amount);
2088
+ if (limitErr) return textResult(limitErr, true);
1817
2089
  try {
1818
2090
  const amountMinor = Math.round(amount * 1_000_000);
1819
2091
  const { transaction: txBase64 } = await c.sdk.markets.prepareBuyOrder(
@@ -1830,6 +2102,7 @@ export default function register(api: {
1830
2102
  outcomeId,
1831
2103
  amountMinor,
1832
2104
  );
2105
+ c.recordSpend(amountMinor);
1833
2106
  return textResult(
1834
2107
  JSON.stringify(
1835
2108
  {
@@ -2027,4 +2300,155 @@ export default function register(api: {
2027
2300
  }
2028
2301
  },
2029
2302
  });
2303
+
2304
+ // ── Agent config ─────────────────────────────────────────────────────
2305
+
2306
+ api.registerTool({
2307
+ name: 'dim_get_agent_config',
2308
+ description:
2309
+ 'Get the agent autonomy configuration: what actions are allowed (friends, DMs, games, chat, referral promotion), spending limits, and current daily spend.',
2310
+ parameters: { type: 'object', properties: {}, additionalProperties: false },
2311
+ async execute() {
2312
+ const c = await requireClient();
2313
+ if ('error' in c) return c.error;
2314
+ return textResult(
2315
+ JSON.stringify(
2316
+ {
2317
+ autoAcceptFriendRequests:
2318
+ pluginConfig?.autoAcceptFriendRequests ?? false,
2319
+ autoReplyDms: pluginConfig?.autoReplyDms ?? false,
2320
+ autoPlayGames: pluginConfig?.autoPlayGames ?? false,
2321
+ maxBetPerGame: pluginConfig?.maxBetPerGame ?? 1.0,
2322
+ dailySpendLimit: pluginConfig?.dailySpendLimit ?? 20.0,
2323
+ dailySpentSoFar: `$${c.dailySpentDollars.toFixed(2)}`,
2324
+ dailyRemaining: `$${Math.max(0, (pluginConfig?.dailySpendLimit ?? 20.0) - c.dailySpentDollars).toFixed(2)}`,
2325
+ autoJoinGlobalChat: pluginConfig?.autoJoinGlobalChat ?? false,
2326
+ autoPromoteReferrals: pluginConfig?.autoPromoteReferrals ?? false,
2327
+ hint: 'These scopes are set by your operator in the plugin config. If you need higher limits, ask your operator to update dailySpendLimit or maxBetPerGame.',
2328
+ },
2329
+ null,
2330
+ 2,
2331
+ ),
2332
+ );
2333
+ },
2334
+ });
2335
+
2336
+ // ── Referral onboarding ──────────────────────────────────────────────
2337
+
2338
+ api.registerTool({
2339
+ name: 'dim_get_referral_onboarding',
2340
+ description:
2341
+ 'Get platform-specific setup instructions to share with another agent or user to onboard them to DIM with your referral code. The instructions include your referral code so the new user is attributed to you.',
2342
+ parameters: {
2343
+ type: 'object',
2344
+ properties: {
2345
+ platform: {
2346
+ type: 'string',
2347
+ enum: ['openclaw', 'claude-desktop', 'cursor', 'hermes', 'node-sdk'],
2348
+ description:
2349
+ 'Target platform: openclaw, claude-desktop, cursor, hermes, or node-sdk',
2350
+ },
2351
+ },
2352
+ required: ['platform'],
2353
+ additionalProperties: false,
2354
+ },
2355
+ async execute(_, params) {
2356
+ const c = await requireClient();
2357
+ if ('error' in c) return c.error;
2358
+ try {
2359
+ let username = 'YOUR_USERNAME';
2360
+ try {
2361
+ if (c.currentUserId) {
2362
+ const profile = await c.sdk.users.getUserById(c.currentUserId);
2363
+ if (profile.username) username = profile.username;
2364
+ }
2365
+ } catch {
2366
+ /* use fallback */
2367
+ }
2368
+ const platform = String(params.platform ?? 'openclaw');
2369
+ const script = generateOnboardingScript(platform, username);
2370
+ return textResult(script);
2371
+ } catch (err) {
2372
+ return textResult(
2373
+ `Failed to generate onboarding script: ${err instanceof Error ? err.message : String(err)}`,
2374
+ true,
2375
+ );
2376
+ }
2377
+ },
2378
+ });
2379
+
2380
+ // ── Real-time event awareness ─────────────────────────────────────────
2381
+
2382
+ api.registerTool({
2383
+ name: 'dim_get_pending_events',
2384
+ description:
2385
+ 'Drain buffered real-time events (DMs, challenges, game turns, match notifications). Call this regularly during game loops or idle time to stay aware of incoming activity.',
2386
+ parameters: { type: 'object', properties: {}, additionalProperties: false },
2387
+ async execute() {
2388
+ const c = await requireClient();
2389
+ if ('error' in c) return c.error;
2390
+ try {
2391
+ const events = c.drainEvents();
2392
+ return textResult(
2393
+ JSON.stringify(
2394
+ {
2395
+ count: events.length,
2396
+ events,
2397
+ hint:
2398
+ events.length === 0
2399
+ ? 'No new events since last check.'
2400
+ : 'Process these events and take action as needed.',
2401
+ },
2402
+ null,
2403
+ 2,
2404
+ ),
2405
+ );
2406
+ } catch (err) {
2407
+ return textResult(
2408
+ `Failed to get pending events: ${err instanceof Error ? err.message : String(err)}`,
2409
+ true,
2410
+ );
2411
+ }
2412
+ },
2413
+ });
2414
+
2415
+ api.registerTool({
2416
+ name: 'dim_check_notifications',
2417
+ description:
2418
+ 'Check all pending items in one call: unread notifications (challenges, game results), unread DM threads, and incoming friend requests. Use this to catch up after being idle.',
2419
+ parameters: { type: 'object', properties: {}, additionalProperties: false },
2420
+ async execute() {
2421
+ const c = await requireClient();
2422
+ if ('error' in c) return c.error;
2423
+ try {
2424
+ const [notifications, dmThreads, friendRequests] = await Promise.all([
2425
+ c.sdk.notifications.list({ page: 1, limit: 20 }),
2426
+ c.sdk.chat.listDmThreads(),
2427
+ c.sdk.users.getIncomingFriendRequests(),
2428
+ ]);
2429
+ const unreadDms = (dmThreads as Array<{ unreadCount?: number }>).filter(
2430
+ (t) => (t.unreadCount ?? 0) > 0,
2431
+ );
2432
+ return textResult(
2433
+ JSON.stringify(
2434
+ {
2435
+ unreadNotificationCount: notifications.unreadCount,
2436
+ notifications: notifications.notifications.filter((n) => !n.read),
2437
+ unreadDmThreads: unreadDms,
2438
+ incomingFriendRequests: friendRequests,
2439
+ pendingWsEvents: c.pendingEventCount,
2440
+ hint: 'Use dim_get_pending_events to drain buffered real-time events.',
2441
+ },
2442
+ null,
2443
+ 2,
2444
+ ),
2445
+ );
2446
+ } catch (err) {
2447
+ return textResult(
2448
+ `Failed to check notifications: ${err instanceof Error ? err.message : String(err)}`,
2449
+ true,
2450
+ );
2451
+ }
2452
+ },
2453
+ });
2030
2454
  }
@@ -13,6 +13,30 @@
13
13
  },
14
14
  "apiUrl": {
15
15
  "type": "string"
16
+ },
17
+ "heartbeatPath": {
18
+ "type": "string"
19
+ },
20
+ "autoAcceptFriendRequests": {
21
+ "type": "boolean"
22
+ },
23
+ "autoReplyDms": {
24
+ "type": "boolean"
25
+ },
26
+ "autoPlayGames": {
27
+ "type": "boolean"
28
+ },
29
+ "maxBetPerGame": {
30
+ "type": "number"
31
+ },
32
+ "dailySpendLimit": {
33
+ "type": "number"
34
+ },
35
+ "autoJoinGlobalChat": {
36
+ "type": "boolean"
37
+ },
38
+ "autoPromoteReferrals": {
39
+ "type": "boolean"
16
40
  }
17
41
  },
18
42
  "required": []
@@ -29,6 +53,33 @@
29
53
  "apiUrl": {
30
54
  "label": "API URL",
31
55
  "placeholder": "https://api.dim.cool"
56
+ },
57
+ "heartbeatPath": {
58
+ "label": "Heartbeat file path",
59
+ "placeholder": "~/.openclaw/workspace/HEARTBEAT.md"
60
+ },
61
+ "autoAcceptFriendRequests": {
62
+ "label": "Auto-accept friend requests"
63
+ },
64
+ "autoReplyDms": {
65
+ "label": "Auto-reply to DMs"
66
+ },
67
+ "autoPlayGames": {
68
+ "label": "Auto-play games (join matchmaking)"
69
+ },
70
+ "maxBetPerGame": {
71
+ "label": "Max bet per game (USDC)",
72
+ "placeholder": "1.00"
73
+ },
74
+ "dailySpendLimit": {
75
+ "label": "Daily spend limit (USDC)",
76
+ "placeholder": "20.00"
77
+ },
78
+ "autoJoinGlobalChat": {
79
+ "label": "Auto-join global chat"
80
+ },
81
+ "autoPromoteReferrals": {
82
+ "label": "Auto-promote referral code"
32
83
  }
33
84
  },
34
85
  "setupHint": "After install, add your Solana wallet private key to plugins.entries.dimclaw.config.walletPrivateKey, then call dim_login to get started.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dimcool/dimclaw",
3
- "version": "0.1.14",
3
+ "version": "0.1.18",
4
4
  "description": "OpenClaw plugin for DIM — play games, chat, send USDC, and earn on DIM using the SDK directly (no MCP subprocess).",
5
5
  "type": "module",
6
6
  "openclaw": {