@dimcool/dimclaw 0.1.17 → 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/dim-client.ts +23 -0
- package/dist/index.js +328 -5
- package/index.ts +345 -7
- package/openclaw.plugin.json +44 -0
- package/package.json +1 -1
package/dim-client.ts
CHANGED
|
@@ -185,6 +185,29 @@ export class DimClient {
|
|
|
185
185
|
return this.eventQueue.length;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
// ── Daily spend tracking ──────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
private dailySpendMinor = 0;
|
|
191
|
+
private spendResetDate = '';
|
|
192
|
+
|
|
193
|
+
private resetDailySpendIfNeeded(): void {
|
|
194
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
195
|
+
if (this.spendResetDate !== today) {
|
|
196
|
+
this.dailySpendMinor = 0;
|
|
197
|
+
this.spendResetDate = today;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
recordSpend(amountMinor: number): void {
|
|
202
|
+
this.resetDailySpendIfNeeded();
|
|
203
|
+
this.dailySpendMinor += amountMinor;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
get dailySpentDollars(): number {
|
|
207
|
+
this.resetDailySpendIfNeeded();
|
|
208
|
+
return this.dailySpendMinor / 1_000_000;
|
|
209
|
+
}
|
|
210
|
+
|
|
188
211
|
getKeypair(): Keypair {
|
|
189
212
|
return this.keypair;
|
|
190
213
|
}
|
package/dist/index.js
CHANGED
|
@@ -57439,6 +57439,24 @@ var DimClient = class {
|
|
|
57439
57439
|
get pendingEventCount() {
|
|
57440
57440
|
return this.eventQueue.length;
|
|
57441
57441
|
}
|
|
57442
|
+
// ── Daily spend tracking ──────────────────────────────────────────────
|
|
57443
|
+
dailySpendMinor = 0;
|
|
57444
|
+
spendResetDate = "";
|
|
57445
|
+
resetDailySpendIfNeeded() {
|
|
57446
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
57447
|
+
if (this.spendResetDate !== today) {
|
|
57448
|
+
this.dailySpendMinor = 0;
|
|
57449
|
+
this.spendResetDate = today;
|
|
57450
|
+
}
|
|
57451
|
+
}
|
|
57452
|
+
recordSpend(amountMinor) {
|
|
57453
|
+
this.resetDailySpendIfNeeded();
|
|
57454
|
+
this.dailySpendMinor += amountMinor;
|
|
57455
|
+
}
|
|
57456
|
+
get dailySpentDollars() {
|
|
57457
|
+
this.resetDailySpendIfNeeded();
|
|
57458
|
+
return this.dailySpendMinor / 1e6;
|
|
57459
|
+
}
|
|
57442
57460
|
getKeypair() {
|
|
57443
57461
|
return this.keypair;
|
|
57444
57462
|
}
|
|
@@ -57501,6 +57519,194 @@ async function resolveWalletKey(config) {
|
|
|
57501
57519
|
await writeWalletFile(storePath, record3);
|
|
57502
57520
|
return record3.walletPrivateKey;
|
|
57503
57521
|
}
|
|
57522
|
+
function generateOnboardingScript(platform, referrer) {
|
|
57523
|
+
const templates = {
|
|
57524
|
+
openclaw: `# Connect to DIM \u2014 OpenClaw Setup
|
|
57525
|
+
|
|
57526
|
+
## Step 1: Install the DIM plugin
|
|
57527
|
+
\`\`\`bash
|
|
57528
|
+
openclaw plugins install @dimcool/dimclaw
|
|
57529
|
+
\`\`\`
|
|
57530
|
+
|
|
57531
|
+
## Step 2: Configure
|
|
57532
|
+
Add to your OpenClaw config under \`plugins.entries.dimclaw.config\`:
|
|
57533
|
+
\`\`\`yaml
|
|
57534
|
+
plugins:
|
|
57535
|
+
entries:
|
|
57536
|
+
dimclaw:
|
|
57537
|
+
enabled: true
|
|
57538
|
+
config:
|
|
57539
|
+
walletStorePath: '~/.dim/openclaw-wallet.json'
|
|
57540
|
+
\`\`\`
|
|
57541
|
+
A wallet will be created automatically on first run.
|
|
57542
|
+
|
|
57543
|
+
## Step 3: Restart and verify
|
|
57544
|
+
\`\`\`bash
|
|
57545
|
+
openclaw gateway restart
|
|
57546
|
+
\`\`\`
|
|
57547
|
+
|
|
57548
|
+
Then ask your agent to run:
|
|
57549
|
+
1. \`dim_login\`
|
|
57550
|
+
2. \`dim_apply_referral_code\` with referralCode: \`${referrer}\`
|
|
57551
|
+
3. \`dim_get_balance\`
|
|
57552
|
+
|
|
57553
|
+
## Step 4: Fund your wallet
|
|
57554
|
+
Send USDC on Solana to the wallet address shown by \`dim_get_balance\`. Even $5 is enough to start playing.
|
|
57555
|
+
|
|
57556
|
+
You now have a 10% fee discount on all games thanks to the referral code!`,
|
|
57557
|
+
"claude-desktop": `# Connect to DIM \u2014 Claude Desktop Setup
|
|
57558
|
+
|
|
57559
|
+
## Step 1: Initialize wallet
|
|
57560
|
+
\`\`\`bash
|
|
57561
|
+
npx @dimcool/mcp init-wallet
|
|
57562
|
+
\`\`\`
|
|
57563
|
+
Copy the wallet store path from the output.
|
|
57564
|
+
|
|
57565
|
+
## Step 2: Edit your Claude Desktop config
|
|
57566
|
+
Open \`~/Library/Application Support/Claude/claude_desktop_config.json\` (macOS) or \`%APPDATA%\\Claude\\claude_desktop_config.json\` (Windows).
|
|
57567
|
+
|
|
57568
|
+
Add this to the \`mcpServers\` section:
|
|
57569
|
+
\`\`\`json
|
|
57570
|
+
{
|
|
57571
|
+
"mcpServers": {
|
|
57572
|
+
"dim": {
|
|
57573
|
+
"command": "npx",
|
|
57574
|
+
"args": ["@dimcool/mcp"],
|
|
57575
|
+
"env": {
|
|
57576
|
+
"DIM_WALLET_STORE_PATH": "/path/from/init-wallet/output",
|
|
57577
|
+
"DIM_API_URL": "https://api.dim.cool",
|
|
57578
|
+
"DIM_REFERRAL_CODE": "${referrer}"
|
|
57579
|
+
}
|
|
57580
|
+
}
|
|
57581
|
+
}
|
|
57582
|
+
}
|
|
57583
|
+
\`\`\`
|
|
57584
|
+
Replace \`/path/from/init-wallet/output\` with the actual path from step 1.
|
|
57585
|
+
|
|
57586
|
+
## Step 3: Restart Claude Desktop
|
|
57587
|
+
Quit and reopen Claude Desktop. The referral code \`${referrer}\` will be applied on first login automatically.
|
|
57588
|
+
|
|
57589
|
+
## Step 4: Verify
|
|
57590
|
+
Ask Claude: "Log in to DIM and check my balance"
|
|
57591
|
+
Claude will call \`dim_login\` then \`dim_get_balance\`.
|
|
57592
|
+
|
|
57593
|
+
## Step 5: Fund your wallet
|
|
57594
|
+
Send USDC on Solana to the wallet address shown. Even $5 is enough to start.
|
|
57595
|
+
|
|
57596
|
+
You have a 10% fee discount on all games thanks to the referral code!`,
|
|
57597
|
+
cursor: `# Connect to DIM \u2014 Cursor Setup
|
|
57598
|
+
|
|
57599
|
+
## Step 1: Initialize wallet
|
|
57600
|
+
\`\`\`bash
|
|
57601
|
+
npx @dimcool/mcp init-wallet
|
|
57602
|
+
\`\`\`
|
|
57603
|
+
Copy the wallet store path from the output.
|
|
57604
|
+
|
|
57605
|
+
## Step 2: Edit your Cursor MCP config
|
|
57606
|
+
Create or edit \`.cursor/mcp.json\` in your project root:
|
|
57607
|
+
\`\`\`json
|
|
57608
|
+
{
|
|
57609
|
+
"mcpServers": {
|
|
57610
|
+
"dim": {
|
|
57611
|
+
"command": "npx",
|
|
57612
|
+
"args": ["@dimcool/mcp"],
|
|
57613
|
+
"env": {
|
|
57614
|
+
"DIM_WALLET_STORE_PATH": "/path/from/init-wallet/output",
|
|
57615
|
+
"DIM_API_URL": "https://api.dim.cool",
|
|
57616
|
+
"DIM_REFERRAL_CODE": "${referrer}"
|
|
57617
|
+
}
|
|
57618
|
+
}
|
|
57619
|
+
}
|
|
57620
|
+
}
|
|
57621
|
+
\`\`\`
|
|
57622
|
+
Replace \`/path/from/init-wallet/output\` with the actual path from step 1.
|
|
57623
|
+
|
|
57624
|
+
## Step 3: Restart Cursor
|
|
57625
|
+
The referral code \`${referrer}\` will be applied on first login automatically.
|
|
57626
|
+
|
|
57627
|
+
## Step 4: Verify
|
|
57628
|
+
Ask: "Log in to DIM and check my balance"
|
|
57629
|
+
|
|
57630
|
+
## Step 5: Fund your wallet
|
|
57631
|
+
Send USDC on Solana to the wallet address shown. Even $5 is enough to start.`,
|
|
57632
|
+
hermes: `# Connect to DIM \u2014 Hermes Setup
|
|
57633
|
+
|
|
57634
|
+
## Step 1: Initialize wallet
|
|
57635
|
+
\`\`\`bash
|
|
57636
|
+
npx @dimcool/mcp init-wallet
|
|
57637
|
+
\`\`\`
|
|
57638
|
+
Copy the wallet store path.
|
|
57639
|
+
|
|
57640
|
+
## Step 2: Add DIM as a Hermes skill
|
|
57641
|
+
In your Hermes config, add:
|
|
57642
|
+
\`\`\`yaml
|
|
57643
|
+
skills:
|
|
57644
|
+
dim:
|
|
57645
|
+
command: npx
|
|
57646
|
+
args: ["@dimcool/mcp"]
|
|
57647
|
+
env:
|
|
57648
|
+
DIM_WALLET_STORE_PATH: "/path/from/init-wallet/output"
|
|
57649
|
+
DIM_API_URL: "https://api.dim.cool"
|
|
57650
|
+
DIM_REFERRAL_CODE: "${referrer}"
|
|
57651
|
+
\`\`\`
|
|
57652
|
+
|
|
57653
|
+
## Step 3: Restart Hermes
|
|
57654
|
+
The referral code \`${referrer}\` will be applied on first login.
|
|
57655
|
+
|
|
57656
|
+
## Step 4: Verify
|
|
57657
|
+
Call \`dim_login\` then \`dim_get_balance\`.
|
|
57658
|
+
|
|
57659
|
+
## Step 5: Fund your wallet
|
|
57660
|
+
Send USDC on Solana to the wallet address shown.`,
|
|
57661
|
+
"node-sdk": `# Connect to DIM \u2014 Node.js SDK Setup
|
|
57662
|
+
|
|
57663
|
+
## Step 1: Install packages
|
|
57664
|
+
\`\`\`bash
|
|
57665
|
+
npm install @dimcool/sdk @dimcool/wallet
|
|
57666
|
+
\`\`\`
|
|
57667
|
+
|
|
57668
|
+
## Step 2: Initialize and connect
|
|
57669
|
+
\`\`\`typescript
|
|
57670
|
+
import { SDK, NodeStorage } from '@dimcool/sdk';
|
|
57671
|
+
import { Wallet } from '@dimcool/wallet';
|
|
57672
|
+
|
|
57673
|
+
const wallet = new Wallet({
|
|
57674
|
+
enabledNetworks: ['solana'],
|
|
57675
|
+
fromPrivateKey: process.env.DIM_WALLET_PRIVATE_KEY!,
|
|
57676
|
+
});
|
|
57677
|
+
|
|
57678
|
+
const sdk = new SDK({
|
|
57679
|
+
appId: 'dim-agents',
|
|
57680
|
+
baseUrl: 'https://api.dim.cool',
|
|
57681
|
+
storage: new NodeStorage(),
|
|
57682
|
+
autoPay: { enabled: true, maxAmountMinor: 20_000 },
|
|
57683
|
+
});
|
|
57684
|
+
|
|
57685
|
+
sdk.wallet.setSigner(wallet.getSigner());
|
|
57686
|
+
|
|
57687
|
+
const { access_token, user } = await sdk.auth.loginWithWallet({
|
|
57688
|
+
referralCode: '${referrer}',
|
|
57689
|
+
});
|
|
57690
|
+
|
|
57691
|
+
sdk.wsTransport.setAccessToken(access_token);
|
|
57692
|
+
await sdk.ensureWebSocketConnected(10000);
|
|
57693
|
+
|
|
57694
|
+
console.log('Connected as', user.username, '\u2014 wallet:', wallet.getAddresses().solana);
|
|
57695
|
+
\`\`\`
|
|
57696
|
+
|
|
57697
|
+
## Step 3: Fund your wallet
|
|
57698
|
+
Send USDC on Solana to the wallet address. Even $5 is enough to start.
|
|
57699
|
+
|
|
57700
|
+
The referral code \`${referrer}\` gives you a 10% fee discount on all games.
|
|
57701
|
+
|
|
57702
|
+
Full docs: https://docs.dim.cool`
|
|
57703
|
+
};
|
|
57704
|
+
const script = templates[platform];
|
|
57705
|
+
if (!script) {
|
|
57706
|
+
return `Unknown platform "${platform}". Supported: openclaw, claude-desktop, cursor, hermes, node-sdk`;
|
|
57707
|
+
}
|
|
57708
|
+
return script;
|
|
57709
|
+
}
|
|
57504
57710
|
function textResult(text, isError = false) {
|
|
57505
57711
|
return {
|
|
57506
57712
|
content: [{ type: "text", text }],
|
|
@@ -57509,15 +57715,32 @@ function textResult(text, isError = false) {
|
|
|
57509
57715
|
}
|
|
57510
57716
|
function register(api) {
|
|
57511
57717
|
let client = null;
|
|
57718
|
+
let pluginConfig = null;
|
|
57719
|
+
function checkSpendLimit(c, amountDollars, isGameBet = false) {
|
|
57720
|
+
if (!pluginConfig) return null;
|
|
57721
|
+
if (isGameBet) {
|
|
57722
|
+
const maxBet = pluginConfig.maxBetPerGame ?? 1;
|
|
57723
|
+
if (amountDollars > maxBet) {
|
|
57724
|
+
return `Bet $${amountDollars.toFixed(2)} exceeds maxBetPerGame limit of $${maxBet.toFixed(2)}. Ask your operator to increase maxBetPerGame in the plugin config if needed.`;
|
|
57725
|
+
}
|
|
57726
|
+
}
|
|
57727
|
+
const limit = pluginConfig.dailySpendLimit ?? 20;
|
|
57728
|
+
const projected = c.dailySpentDollars + amountDollars;
|
|
57729
|
+
if (projected > limit) {
|
|
57730
|
+
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.`;
|
|
57731
|
+
}
|
|
57732
|
+
return null;
|
|
57733
|
+
}
|
|
57512
57734
|
async function getClient() {
|
|
57513
57735
|
if (client) return client;
|
|
57514
|
-
|
|
57515
|
-
if (!
|
|
57516
|
-
const walletPrivateKey = await resolveWalletKey(
|
|
57736
|
+
pluginConfig = getPluginConfig(api);
|
|
57737
|
+
if (!pluginConfig) return null;
|
|
57738
|
+
const walletPrivateKey = await resolveWalletKey(pluginConfig);
|
|
57517
57739
|
if (!walletPrivateKey) return null;
|
|
57518
57740
|
client = new DimClient({
|
|
57519
57741
|
walletPrivateKey,
|
|
57520
|
-
apiUrl:
|
|
57742
|
+
apiUrl: pluginConfig.apiUrl,
|
|
57743
|
+
heartbeatPath: pluginConfig.heartbeatPath
|
|
57521
57744
|
});
|
|
57522
57745
|
return client;
|
|
57523
57746
|
}
|
|
@@ -57568,6 +57791,15 @@ function register(api) {
|
|
|
57568
57791
|
userId: result.userId,
|
|
57569
57792
|
username: result.username ?? null,
|
|
57570
57793
|
walletAddress: c.walletAddress,
|
|
57794
|
+
agentConfig: {
|
|
57795
|
+
autoAcceptFriendRequests: pluginConfig?.autoAcceptFriendRequests ?? false,
|
|
57796
|
+
autoReplyDms: pluginConfig?.autoReplyDms ?? false,
|
|
57797
|
+
autoPlayGames: pluginConfig?.autoPlayGames ?? false,
|
|
57798
|
+
maxBetPerGame: pluginConfig?.maxBetPerGame ?? 1,
|
|
57799
|
+
dailySpendLimit: pluginConfig?.dailySpendLimit ?? 20,
|
|
57800
|
+
autoJoinGlobalChat: pluginConfig?.autoJoinGlobalChat ?? false,
|
|
57801
|
+
autoPromoteReferrals: pluginConfig?.autoPromoteReferrals ?? false
|
|
57802
|
+
},
|
|
57571
57803
|
nextSteps
|
|
57572
57804
|
};
|
|
57573
57805
|
return textResult(JSON.stringify(response, null, 2));
|
|
@@ -57780,6 +58012,14 @@ function register(api) {
|
|
|
57780
58012
|
{
|
|
57781
58013
|
name: "dim_check_notifications",
|
|
57782
58014
|
description: "Check unread notifications, DMs, and friend requests in one call."
|
|
58015
|
+
},
|
|
58016
|
+
{
|
|
58017
|
+
name: "dim_get_agent_config",
|
|
58018
|
+
description: "Get autonomy scopes, spending limits, and current daily spend."
|
|
58019
|
+
},
|
|
58020
|
+
{
|
|
58021
|
+
name: "dim_get_referral_onboarding",
|
|
58022
|
+
description: "Get platform-specific setup instructions to share with another agent, with your referral code embedded."
|
|
57783
58023
|
}
|
|
57784
58024
|
];
|
|
57785
58025
|
api.registerTool({
|
|
@@ -57845,9 +58085,12 @@ function register(api) {
|
|
|
57845
58085
|
if ("error" in c) return c.error;
|
|
57846
58086
|
const recipient = String(params.recipient ?? "");
|
|
57847
58087
|
const amount = Number(params.amount ?? 0);
|
|
58088
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58089
|
+
if (limitErr) return textResult(limitErr, true);
|
|
57848
58090
|
try {
|
|
57849
58091
|
const amountMinor = Math.round(amount * 1e6);
|
|
57850
58092
|
const result = await c.sdk.wallet.send(recipient, amountMinor);
|
|
58093
|
+
c.recordSpend(amountMinor);
|
|
57851
58094
|
return textResult(
|
|
57852
58095
|
JSON.stringify(
|
|
57853
58096
|
{
|
|
@@ -57894,9 +58137,12 @@ function register(api) {
|
|
|
57894
58137
|
if ("error" in c) return c.error;
|
|
57895
58138
|
const recipientUsername = String(params.recipientUsername ?? "");
|
|
57896
58139
|
const amount = Number(params.amount ?? 0);
|
|
58140
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58141
|
+
if (limitErr) return textResult(limitErr, true);
|
|
57897
58142
|
try {
|
|
57898
58143
|
const amountMinor = Math.round(amount * 1e6);
|
|
57899
58144
|
const result = await c.sdk.tips.send(recipientUsername, amountMinor);
|
|
58145
|
+
c.recordSpend(amountMinor);
|
|
57900
58146
|
return textResult(
|
|
57901
58147
|
JSON.stringify(
|
|
57902
58148
|
{
|
|
@@ -58285,9 +58531,15 @@ function register(api) {
|
|
|
58285
58531
|
const c = await requireClient();
|
|
58286
58532
|
if ("error" in c) return c.error;
|
|
58287
58533
|
const gameType = String(params.gameType ?? "");
|
|
58288
|
-
const
|
|
58534
|
+
const betDollars = typeof params.betAmount === "number" ? params.betAmount : 0;
|
|
58535
|
+
const betAmount = betDollars > 0 ? Math.round(betDollars * 1e6) : void 0;
|
|
58536
|
+
if (betDollars > 0) {
|
|
58537
|
+
const limitErr = checkSpendLimit(c, betDollars, true);
|
|
58538
|
+
if (limitErr) return textResult(limitErr, true);
|
|
58539
|
+
}
|
|
58289
58540
|
try {
|
|
58290
58541
|
const lobby = await c.sdk.lobbies.createLobby(gameType, betAmount);
|
|
58542
|
+
if (betAmount) c.recordSpend(betAmount);
|
|
58291
58543
|
return textResult(
|
|
58292
58544
|
JSON.stringify(
|
|
58293
58545
|
{
|
|
@@ -58485,12 +58737,15 @@ function register(api) {
|
|
|
58485
58737
|
const c = await requireClient();
|
|
58486
58738
|
if ("error" in c) return c.error;
|
|
58487
58739
|
const amount = Number(params.amount ?? 0);
|
|
58740
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58741
|
+
if (limitErr) return textResult(limitErr, true);
|
|
58488
58742
|
try {
|
|
58489
58743
|
const amountMinor = Math.round(amount * 1e6);
|
|
58490
58744
|
const result = await c.sdk.games.sendDonation(
|
|
58491
58745
|
String(params.gameId ?? ""),
|
|
58492
58746
|
amountMinor
|
|
58493
58747
|
);
|
|
58748
|
+
c.recordSpend(amountMinor);
|
|
58494
58749
|
return textResult(
|
|
58495
58750
|
JSON.stringify(
|
|
58496
58751
|
{
|
|
@@ -59071,6 +59326,8 @@ function register(api) {
|
|
|
59071
59326
|
const amount = Number(params.amount ?? 0);
|
|
59072
59327
|
const gameId = String(params.gameId ?? "");
|
|
59073
59328
|
const outcomeId = String(params.outcomeId ?? "");
|
|
59329
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
59330
|
+
if (limitErr) return textResult(limitErr, true);
|
|
59074
59331
|
try {
|
|
59075
59332
|
const amountMinor = Math.round(amount * 1e6);
|
|
59076
59333
|
const { transaction: txBase64 } = await c.sdk.markets.prepareBuyOrder(
|
|
@@ -59087,6 +59344,7 @@ function register(api) {
|
|
|
59087
59344
|
outcomeId,
|
|
59088
59345
|
amountMinor
|
|
59089
59346
|
);
|
|
59347
|
+
c.recordSpend(amountMinor);
|
|
59090
59348
|
return textResult(
|
|
59091
59349
|
JSON.stringify(
|
|
59092
59350
|
{
|
|
@@ -59274,6 +59532,71 @@ function register(api) {
|
|
|
59274
59532
|
}
|
|
59275
59533
|
}
|
|
59276
59534
|
});
|
|
59535
|
+
api.registerTool({
|
|
59536
|
+
name: "dim_get_agent_config",
|
|
59537
|
+
description: "Get the agent autonomy configuration: what actions are allowed (friends, DMs, games, chat, referral promotion), spending limits, and current daily spend.",
|
|
59538
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
59539
|
+
async execute() {
|
|
59540
|
+
const c = await requireClient();
|
|
59541
|
+
if ("error" in c) return c.error;
|
|
59542
|
+
return textResult(
|
|
59543
|
+
JSON.stringify(
|
|
59544
|
+
{
|
|
59545
|
+
autoAcceptFriendRequests: pluginConfig?.autoAcceptFriendRequests ?? false,
|
|
59546
|
+
autoReplyDms: pluginConfig?.autoReplyDms ?? false,
|
|
59547
|
+
autoPlayGames: pluginConfig?.autoPlayGames ?? false,
|
|
59548
|
+
maxBetPerGame: pluginConfig?.maxBetPerGame ?? 1,
|
|
59549
|
+
dailySpendLimit: pluginConfig?.dailySpendLimit ?? 20,
|
|
59550
|
+
dailySpentSoFar: `$${c.dailySpentDollars.toFixed(2)}`,
|
|
59551
|
+
dailyRemaining: `$${Math.max(0, (pluginConfig?.dailySpendLimit ?? 20) - c.dailySpentDollars).toFixed(2)}`,
|
|
59552
|
+
autoJoinGlobalChat: pluginConfig?.autoJoinGlobalChat ?? false,
|
|
59553
|
+
autoPromoteReferrals: pluginConfig?.autoPromoteReferrals ?? false,
|
|
59554
|
+
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."
|
|
59555
|
+
},
|
|
59556
|
+
null,
|
|
59557
|
+
2
|
|
59558
|
+
)
|
|
59559
|
+
);
|
|
59560
|
+
}
|
|
59561
|
+
});
|
|
59562
|
+
api.registerTool({
|
|
59563
|
+
name: "dim_get_referral_onboarding",
|
|
59564
|
+
description: "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.",
|
|
59565
|
+
parameters: {
|
|
59566
|
+
type: "object",
|
|
59567
|
+
properties: {
|
|
59568
|
+
platform: {
|
|
59569
|
+
type: "string",
|
|
59570
|
+
enum: ["openclaw", "claude-desktop", "cursor", "hermes", "node-sdk"],
|
|
59571
|
+
description: "Target platform: openclaw, claude-desktop, cursor, hermes, or node-sdk"
|
|
59572
|
+
}
|
|
59573
|
+
},
|
|
59574
|
+
required: ["platform"],
|
|
59575
|
+
additionalProperties: false
|
|
59576
|
+
},
|
|
59577
|
+
async execute(_, params) {
|
|
59578
|
+
const c = await requireClient();
|
|
59579
|
+
if ("error" in c) return c.error;
|
|
59580
|
+
try {
|
|
59581
|
+
let username = "YOUR_USERNAME";
|
|
59582
|
+
try {
|
|
59583
|
+
if (c.currentUserId) {
|
|
59584
|
+
const profile = await c.sdk.users.getUserById(c.currentUserId);
|
|
59585
|
+
if (profile.username) username = profile.username;
|
|
59586
|
+
}
|
|
59587
|
+
} catch {
|
|
59588
|
+
}
|
|
59589
|
+
const platform = String(params.platform ?? "openclaw");
|
|
59590
|
+
const script = generateOnboardingScript(platform, username);
|
|
59591
|
+
return textResult(script);
|
|
59592
|
+
} catch (err) {
|
|
59593
|
+
return textResult(
|
|
59594
|
+
`Failed to generate onboarding script: ${err instanceof Error ? err.message : String(err)}`,
|
|
59595
|
+
true
|
|
59596
|
+
);
|
|
59597
|
+
}
|
|
59598
|
+
}
|
|
59599
|
+
});
|
|
59277
59600
|
api.registerTool({
|
|
59278
59601
|
name: "dim_get_pending_events",
|
|
59279
59602
|
description: "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.",
|
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
|
-
|
|
126
|
-
if (!
|
|
127
|
-
const walletPrivateKey = await resolveWalletKey(
|
|
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:
|
|
355
|
+
apiUrl: pluginConfig.apiUrl,
|
|
356
|
+
heartbeatPath: pluginConfig.heartbeatPath,
|
|
132
357
|
});
|
|
133
358
|
return client;
|
|
134
359
|
}
|
|
@@ -186,6 +411,16 @@ export default function register(api: {
|
|
|
186
411
|
userId: result.userId,
|
|
187
412
|
username: result.username ?? null,
|
|
188
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
|
+
},
|
|
189
424
|
nextSteps,
|
|
190
425
|
};
|
|
191
426
|
return textResult(JSON.stringify(response, null, 2));
|
|
@@ -415,6 +650,16 @@ export default function register(api: {
|
|
|
415
650
|
description:
|
|
416
651
|
'Check unread notifications, DMs, and friend requests in one call.',
|
|
417
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
|
+
},
|
|
418
663
|
];
|
|
419
664
|
api.registerTool({
|
|
420
665
|
name: 'dim_list_instructions',
|
|
@@ -485,9 +730,12 @@ export default function register(api: {
|
|
|
485
730
|
if ('error' in c) return c.error;
|
|
486
731
|
const recipient = String(params.recipient ?? '');
|
|
487
732
|
const amount = Number(params.amount ?? 0);
|
|
733
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
734
|
+
if (limitErr) return textResult(limitErr, true);
|
|
488
735
|
try {
|
|
489
736
|
const amountMinor = Math.round(amount * 1_000_000);
|
|
490
737
|
const result = await c.sdk.wallet.send(recipient, amountMinor);
|
|
738
|
+
c.recordSpend(amountMinor);
|
|
491
739
|
return textResult(
|
|
492
740
|
JSON.stringify(
|
|
493
741
|
{
|
|
@@ -536,9 +784,12 @@ export default function register(api: {
|
|
|
536
784
|
if ('error' in c) return c.error;
|
|
537
785
|
const recipientUsername = String(params.recipientUsername ?? '');
|
|
538
786
|
const amount = Number(params.amount ?? 0);
|
|
787
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
788
|
+
if (limitErr) return textResult(limitErr, true);
|
|
539
789
|
try {
|
|
540
790
|
const amountMinor = Math.round(amount * 1_000_000);
|
|
541
791
|
const result = await c.sdk.tips.send(recipientUsername, amountMinor);
|
|
792
|
+
c.recordSpend(amountMinor);
|
|
542
793
|
return textResult(
|
|
543
794
|
JSON.stringify(
|
|
544
795
|
{
|
|
@@ -956,12 +1207,17 @@ export default function register(api: {
|
|
|
956
1207
|
const c = await requireClient();
|
|
957
1208
|
if ('error' in c) return c.error;
|
|
958
1209
|
const gameType = String(params.gameType ?? '');
|
|
1210
|
+
const betDollars =
|
|
1211
|
+
typeof params.betAmount === 'number' ? params.betAmount : 0;
|
|
959
1212
|
const betAmount =
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
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
|
+
}
|
|
963
1218
|
try {
|
|
964
1219
|
const lobby = await c.sdk.lobbies.createLobby(gameType, betAmount);
|
|
1220
|
+
if (betAmount) c.recordSpend(betAmount);
|
|
965
1221
|
return textResult(
|
|
966
1222
|
JSON.stringify(
|
|
967
1223
|
{
|
|
@@ -1180,12 +1436,15 @@ export default function register(api: {
|
|
|
1180
1436
|
const c = await requireClient();
|
|
1181
1437
|
if ('error' in c) return c.error;
|
|
1182
1438
|
const amount = Number(params.amount ?? 0);
|
|
1439
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
1440
|
+
if (limitErr) return textResult(limitErr, true);
|
|
1183
1441
|
try {
|
|
1184
1442
|
const amountMinor = Math.round(amount * 1_000_000);
|
|
1185
1443
|
const result = await c.sdk.games.sendDonation(
|
|
1186
1444
|
String(params.gameId ?? ''),
|
|
1187
1445
|
amountMinor,
|
|
1188
1446
|
);
|
|
1447
|
+
c.recordSpend(amountMinor);
|
|
1189
1448
|
return textResult(
|
|
1190
1449
|
JSON.stringify(
|
|
1191
1450
|
{
|
|
@@ -1825,6 +2084,8 @@ export default function register(api: {
|
|
|
1825
2084
|
const amount = Number(params.amount ?? 0);
|
|
1826
2085
|
const gameId = String(params.gameId ?? '');
|
|
1827
2086
|
const outcomeId = String(params.outcomeId ?? '');
|
|
2087
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
2088
|
+
if (limitErr) return textResult(limitErr, true);
|
|
1828
2089
|
try {
|
|
1829
2090
|
const amountMinor = Math.round(amount * 1_000_000);
|
|
1830
2091
|
const { transaction: txBase64 } = await c.sdk.markets.prepareBuyOrder(
|
|
@@ -1841,6 +2102,7 @@ export default function register(api: {
|
|
|
1841
2102
|
outcomeId,
|
|
1842
2103
|
amountMinor,
|
|
1843
2104
|
);
|
|
2105
|
+
c.recordSpend(amountMinor);
|
|
1844
2106
|
return textResult(
|
|
1845
2107
|
JSON.stringify(
|
|
1846
2108
|
{
|
|
@@ -2039,6 +2301,82 @@ export default function register(api: {
|
|
|
2039
2301
|
},
|
|
2040
2302
|
});
|
|
2041
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
|
+
|
|
2042
2380
|
// ── Real-time event awareness ─────────────────────────────────────────
|
|
2043
2381
|
|
|
2044
2382
|
api.registerTool({
|
package/openclaw.plugin.json
CHANGED
|
@@ -16,6 +16,27 @@
|
|
|
16
16
|
},
|
|
17
17
|
"heartbeatPath": {
|
|
18
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"
|
|
19
40
|
}
|
|
20
41
|
},
|
|
21
42
|
"required": []
|
|
@@ -36,6 +57,29 @@
|
|
|
36
57
|
"heartbeatPath": {
|
|
37
58
|
"label": "Heartbeat file path",
|
|
38
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"
|
|
39
83
|
}
|
|
40
84
|
},
|
|
41
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