@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/dim-client.ts +112 -0
- package/dist/index.js +542 -65
- package/index.ts +431 -7
- package/openclaw.plugin.json +51 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6513,14 +6513,14 @@ var require_url_state_machine = __commonJS({
|
|
|
6513
6513
|
return url3.replace(/\u0009|\u000A|\u000D/g, "");
|
|
6514
6514
|
}
|
|
6515
6515
|
function shortenPath(url3) {
|
|
6516
|
-
const
|
|
6517
|
-
if (
|
|
6516
|
+
const path3 = url3.path;
|
|
6517
|
+
if (path3.length === 0) {
|
|
6518
6518
|
return;
|
|
6519
6519
|
}
|
|
6520
|
-
if (url3.scheme === "file" &&
|
|
6520
|
+
if (url3.scheme === "file" && path3.length === 1 && isNormalizedWindowsDriveLetter(path3[0])) {
|
|
6521
6521
|
return;
|
|
6522
6522
|
}
|
|
6523
|
-
|
|
6523
|
+
path3.pop();
|
|
6524
6524
|
}
|
|
6525
6525
|
function includesCredentials(url3) {
|
|
6526
6526
|
return url3.username !== "" || url3.password !== "";
|
|
@@ -7577,7 +7577,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
7577
7577
|
"../../node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
|
|
7578
7578
|
"use strict";
|
|
7579
7579
|
var fs = __require("fs");
|
|
7580
|
-
var
|
|
7580
|
+
var path3 = __require("path");
|
|
7581
7581
|
var os = __require("os");
|
|
7582
7582
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
7583
7583
|
var vars = process.config && process.config.variables || {};
|
|
@@ -7594,21 +7594,21 @@ var require_node_gyp_build = __commonJS({
|
|
|
7594
7594
|
return runtimeRequire(load.resolve(dir));
|
|
7595
7595
|
}
|
|
7596
7596
|
load.resolve = load.path = function(dir) {
|
|
7597
|
-
dir =
|
|
7597
|
+
dir = path3.resolve(dir || ".");
|
|
7598
7598
|
try {
|
|
7599
|
-
var name = runtimeRequire(
|
|
7599
|
+
var name = runtimeRequire(path3.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
|
|
7600
7600
|
if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
|
|
7601
7601
|
} catch (err) {
|
|
7602
7602
|
}
|
|
7603
7603
|
if (!prebuildsOnly) {
|
|
7604
|
-
var release = getFirst(
|
|
7604
|
+
var release = getFirst(path3.join(dir, "build/Release"), matchBuild);
|
|
7605
7605
|
if (release) return release;
|
|
7606
|
-
var debug12 = getFirst(
|
|
7606
|
+
var debug12 = getFirst(path3.join(dir, "build/Debug"), matchBuild);
|
|
7607
7607
|
if (debug12) return debug12;
|
|
7608
7608
|
}
|
|
7609
7609
|
var prebuild = resolve(dir);
|
|
7610
7610
|
if (prebuild) return prebuild;
|
|
7611
|
-
var nearby = resolve(
|
|
7611
|
+
var nearby = resolve(path3.dirname(process.execPath));
|
|
7612
7612
|
if (nearby) return nearby;
|
|
7613
7613
|
var target = [
|
|
7614
7614
|
"platform=" + platform,
|
|
@@ -7625,14 +7625,14 @@ var require_node_gyp_build = __commonJS({
|
|
|
7625
7625
|
].filter(Boolean).join(" ");
|
|
7626
7626
|
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
|
|
7627
7627
|
function resolve(dir2) {
|
|
7628
|
-
var tuples = readdirSync(
|
|
7628
|
+
var tuples = readdirSync(path3.join(dir2, "prebuilds")).map(parseTuple);
|
|
7629
7629
|
var tuple3 = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
7630
7630
|
if (!tuple3) return;
|
|
7631
|
-
var prebuilds =
|
|
7631
|
+
var prebuilds = path3.join(dir2, "prebuilds", tuple3.name);
|
|
7632
7632
|
var parsed = readdirSync(prebuilds).map(parseTags);
|
|
7633
7633
|
var candidates = parsed.filter(matchTags(runtime, abi));
|
|
7634
7634
|
var winner = candidates.sort(compareTags(runtime))[0];
|
|
7635
|
-
if (winner) return
|
|
7635
|
+
if (winner) return path3.join(prebuilds, winner.file);
|
|
7636
7636
|
}
|
|
7637
7637
|
};
|
|
7638
7638
|
function readdirSync(dir) {
|
|
@@ -7644,7 +7644,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
7644
7644
|
}
|
|
7645
7645
|
function getFirst(dir, filter) {
|
|
7646
7646
|
var files = readdirSync(dir).filter(filter);
|
|
7647
|
-
return files[0] &&
|
|
7647
|
+
return files[0] && path3.join(dir, files[0]);
|
|
7648
7648
|
}
|
|
7649
7649
|
function matchBuild(name) {
|
|
7650
7650
|
return /\.node$/.test(name);
|
|
@@ -18589,8 +18589,8 @@ var require_nacl_fast = __commonJS({
|
|
|
18589
18589
|
});
|
|
18590
18590
|
|
|
18591
18591
|
// index.ts
|
|
18592
|
-
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
18593
|
-
import
|
|
18592
|
+
import { mkdir as mkdir2, readFile, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
18593
|
+
import path2 from "path";
|
|
18594
18594
|
|
|
18595
18595
|
// ../../node_modules/@solana/web3.js/lib/index.esm.js
|
|
18596
18596
|
import { Buffer as Buffer2 } from "buffer";
|
|
@@ -21589,8 +21589,8 @@ var StructError = class extends TypeError {
|
|
|
21589
21589
|
constructor(failure, failures) {
|
|
21590
21590
|
let cached;
|
|
21591
21591
|
const { message, explanation, ...rest } = failure;
|
|
21592
|
-
const { path:
|
|
21593
|
-
const msg =
|
|
21592
|
+
const { path: path3 } = failure;
|
|
21593
|
+
const msg = path3.length === 0 ? message : `At path: ${path3.join(".")} -- ${message}`;
|
|
21594
21594
|
super(explanation ?? msg);
|
|
21595
21595
|
if (explanation != null)
|
|
21596
21596
|
this.cause = msg;
|
|
@@ -21628,15 +21628,15 @@ function toFailure(result, context, struct2, value2) {
|
|
|
21628
21628
|
} else if (typeof result === "string") {
|
|
21629
21629
|
result = { message: result };
|
|
21630
21630
|
}
|
|
21631
|
-
const { path:
|
|
21631
|
+
const { path: path3, branch } = context;
|
|
21632
21632
|
const { type: type3 } = struct2;
|
|
21633
21633
|
const { refinement, message = `Expected a value of type \`${type3}\`${refinement ? ` with refinement \`${refinement}\`` : ""}, but received: \`${print(value2)}\`` } = result;
|
|
21634
21634
|
return {
|
|
21635
21635
|
value: value2,
|
|
21636
21636
|
type: type3,
|
|
21637
21637
|
refinement,
|
|
21638
|
-
key:
|
|
21639
|
-
path:
|
|
21638
|
+
key: path3[path3.length - 1],
|
|
21639
|
+
path: path3,
|
|
21640
21640
|
branch,
|
|
21641
21641
|
...result,
|
|
21642
21642
|
message
|
|
@@ -21654,8 +21654,8 @@ function* toFailures(result, context, struct2, value2) {
|
|
|
21654
21654
|
}
|
|
21655
21655
|
}
|
|
21656
21656
|
function* run(value2, struct2, options = {}) {
|
|
21657
|
-
const { path:
|
|
21658
|
-
const ctx = { path:
|
|
21657
|
+
const { path: path3 = [], branch = [value2], coerce: coerce3 = false, mask: mask3 = false } = options;
|
|
21658
|
+
const ctx = { path: path3, branch, mask: mask3 };
|
|
21659
21659
|
if (coerce3) {
|
|
21660
21660
|
value2 = struct2.coercer(value2, ctx);
|
|
21661
21661
|
}
|
|
@@ -21667,7 +21667,7 @@ function* run(value2, struct2, options = {}) {
|
|
|
21667
21667
|
}
|
|
21668
21668
|
for (let [k, v, s] of struct2.entries(value2, ctx)) {
|
|
21669
21669
|
const ts = run(v, s, {
|
|
21670
|
-
path: k === void 0 ?
|
|
21670
|
+
path: k === void 0 ? path3 : [...path3, k],
|
|
21671
21671
|
branch: k === void 0 ? branch : [...branch, v],
|
|
21672
21672
|
coerce: coerce3,
|
|
21673
21673
|
mask: mask3,
|
|
@@ -28583,6 +28583,10 @@ var esm_default = base;
|
|
|
28583
28583
|
var ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
28584
28584
|
var esm_default2 = esm_default(ALPHABET);
|
|
28585
28585
|
|
|
28586
|
+
// dim-client.ts
|
|
28587
|
+
import { mkdir, writeFile, rename } from "fs/promises";
|
|
28588
|
+
import path from "path";
|
|
28589
|
+
|
|
28586
28590
|
// ../sdk/dist/index.js
|
|
28587
28591
|
import crypto22 from "crypto";
|
|
28588
28592
|
import crypto32 from "crypto";
|
|
@@ -29836,12 +29840,12 @@ function parse3(str) {
|
|
|
29836
29840
|
uri.queryKey = queryKey(uri, uri["query"]);
|
|
29837
29841
|
return uri;
|
|
29838
29842
|
}
|
|
29839
|
-
function pathNames(obj,
|
|
29840
|
-
const regx = /\/{2,9}/g, names =
|
|
29841
|
-
if (
|
|
29843
|
+
function pathNames(obj, path3) {
|
|
29844
|
+
const regx = /\/{2,9}/g, names = path3.replace(regx, "/").split("/");
|
|
29845
|
+
if (path3.slice(0, 1) == "/" || path3.length === 0) {
|
|
29842
29846
|
names.splice(0, 1);
|
|
29843
29847
|
}
|
|
29844
|
-
if (
|
|
29848
|
+
if (path3.slice(-1) == "/") {
|
|
29845
29849
|
names.splice(names.length - 1, 1);
|
|
29846
29850
|
}
|
|
29847
29851
|
return names;
|
|
@@ -30458,7 +30462,7 @@ var protocol2 = Socket.protocol;
|
|
|
30458
30462
|
// ../../node_modules/socket.io-client/build/esm-debug/url.js
|
|
30459
30463
|
var import_debug7 = __toESM(require_src2(), 1);
|
|
30460
30464
|
var debug7 = (0, import_debug7.default)("socket.io-client:url");
|
|
30461
|
-
function url2(uri,
|
|
30465
|
+
function url2(uri, path3 = "", loc) {
|
|
30462
30466
|
let obj = uri;
|
|
30463
30467
|
loc = loc || typeof location !== "undefined" && location;
|
|
30464
30468
|
if (null == uri)
|
|
@@ -30492,7 +30496,7 @@ function url2(uri, path2 = "", loc) {
|
|
|
30492
30496
|
obj.path = obj.path || "/";
|
|
30493
30497
|
const ipv6 = obj.host.indexOf(":") !== -1;
|
|
30494
30498
|
const host = ipv6 ? "[" + obj.host + "]" : obj.host;
|
|
30495
|
-
obj.id = obj.protocol + "://" + host + ":" + obj.port +
|
|
30499
|
+
obj.id = obj.protocol + "://" + host + ":" + obj.port + path3;
|
|
30496
30500
|
obj.href = obj.protocol + "://" + host + (loc && loc.port === obj.port ? "" : ":" + obj.port);
|
|
30497
30501
|
return obj;
|
|
30498
30502
|
}
|
|
@@ -32116,8 +32120,8 @@ function lookup(uri, opts) {
|
|
|
32116
32120
|
const parsed = url2(uri, opts.path || "/socket.io");
|
|
32117
32121
|
const source = parsed.source;
|
|
32118
32122
|
const id = parsed.id;
|
|
32119
|
-
const
|
|
32120
|
-
const sameNamespace = cache[id] &&
|
|
32123
|
+
const path3 = parsed.path;
|
|
32124
|
+
const sameNamespace = cache[id] && path3 in cache[id]["nsps"];
|
|
32121
32125
|
const newConnection = opts.forceNew || opts["force new connection"] || false === opts.multiplex || sameNamespace;
|
|
32122
32126
|
let io;
|
|
32123
32127
|
if (newConnection) {
|
|
@@ -38664,14 +38668,14 @@ var require_url_state_machine2 = __commonJS2({
|
|
|
38664
38668
|
return url22.replace(/\u0009|\u000A|\u000D/g, "");
|
|
38665
38669
|
}
|
|
38666
38670
|
function shortenPath(url22) {
|
|
38667
|
-
const
|
|
38668
|
-
if (
|
|
38671
|
+
const path3 = url22.path;
|
|
38672
|
+
if (path3.length === 0) {
|
|
38669
38673
|
return;
|
|
38670
38674
|
}
|
|
38671
|
-
if (url22.scheme === "file" &&
|
|
38675
|
+
if (url22.scheme === "file" && path3.length === 1 && isNormalizedWindowsDriveLetter(path3[0])) {
|
|
38672
38676
|
return;
|
|
38673
38677
|
}
|
|
38674
|
-
|
|
38678
|
+
path3.pop();
|
|
38675
38679
|
}
|
|
38676
38680
|
function includesCredentials(url22) {
|
|
38677
38681
|
return url22.username !== "" || url22.password !== "";
|
|
@@ -39718,7 +39722,7 @@ var require_node_gyp_build3 = __commonJS2({
|
|
|
39718
39722
|
"../../node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
|
|
39719
39723
|
"use strict";
|
|
39720
39724
|
var fs = __require2("fs");
|
|
39721
|
-
var
|
|
39725
|
+
var path3 = __require2("path");
|
|
39722
39726
|
var os = __require2("os");
|
|
39723
39727
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require2;
|
|
39724
39728
|
var vars = process.config && process.config.variables || {};
|
|
@@ -39735,21 +39739,21 @@ var require_node_gyp_build3 = __commonJS2({
|
|
|
39735
39739
|
return runtimeRequire(load.resolve(dir));
|
|
39736
39740
|
}
|
|
39737
39741
|
load.resolve = load.path = function(dir) {
|
|
39738
|
-
dir =
|
|
39742
|
+
dir = path3.resolve(dir || ".");
|
|
39739
39743
|
try {
|
|
39740
|
-
var name = runtimeRequire(
|
|
39744
|
+
var name = runtimeRequire(path3.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
|
|
39741
39745
|
if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
|
|
39742
39746
|
} catch (err) {
|
|
39743
39747
|
}
|
|
39744
39748
|
if (!prebuildsOnly) {
|
|
39745
|
-
var release = getFirst(
|
|
39749
|
+
var release = getFirst(path3.join(dir, "build/Release"), matchBuild);
|
|
39746
39750
|
if (release) return release;
|
|
39747
|
-
var debug12 = getFirst(
|
|
39751
|
+
var debug12 = getFirst(path3.join(dir, "build/Debug"), matchBuild);
|
|
39748
39752
|
if (debug12) return debug12;
|
|
39749
39753
|
}
|
|
39750
39754
|
var prebuild = resolve(dir);
|
|
39751
39755
|
if (prebuild) return prebuild;
|
|
39752
|
-
var nearby = resolve(
|
|
39756
|
+
var nearby = resolve(path3.dirname(process.execPath));
|
|
39753
39757
|
if (nearby) return nearby;
|
|
39754
39758
|
var target = [
|
|
39755
39759
|
"platform=" + platform,
|
|
@@ -39766,14 +39770,14 @@ var require_node_gyp_build3 = __commonJS2({
|
|
|
39766
39770
|
].filter(Boolean).join(" ");
|
|
39767
39771
|
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
|
|
39768
39772
|
function resolve(dir2) {
|
|
39769
|
-
var tuples = readdirSync(
|
|
39773
|
+
var tuples = readdirSync(path3.join(dir2, "prebuilds")).map(parseTuple);
|
|
39770
39774
|
var tuple22 = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
39771
39775
|
if (!tuple22) return;
|
|
39772
|
-
var prebuilds =
|
|
39776
|
+
var prebuilds = path3.join(dir2, "prebuilds", tuple22.name);
|
|
39773
39777
|
var parsed = readdirSync(prebuilds).map(parseTags);
|
|
39774
39778
|
var candidates = parsed.filter(matchTags(runtime, abi));
|
|
39775
39779
|
var winner = candidates.sort(compareTags(runtime))[0];
|
|
39776
|
-
if (winner) return
|
|
39780
|
+
if (winner) return path3.join(prebuilds, winner.file);
|
|
39777
39781
|
}
|
|
39778
39782
|
};
|
|
39779
39783
|
function readdirSync(dir) {
|
|
@@ -39785,7 +39789,7 @@ var require_node_gyp_build3 = __commonJS2({
|
|
|
39785
39789
|
}
|
|
39786
39790
|
function getFirst(dir, filter) {
|
|
39787
39791
|
var files = readdirSync(dir).filter(filter);
|
|
39788
|
-
return files[0] &&
|
|
39792
|
+
return files[0] && path3.join(dir, files[0]);
|
|
39789
39793
|
}
|
|
39790
39794
|
function matchBuild(name) {
|
|
39791
39795
|
return /\.node$/.test(name);
|
|
@@ -46870,8 +46874,8 @@ var StructError2 = class extends TypeError {
|
|
|
46870
46874
|
constructor(failure, failures) {
|
|
46871
46875
|
let cached;
|
|
46872
46876
|
const { message, explanation, ...rest } = failure;
|
|
46873
|
-
const { path:
|
|
46874
|
-
const msg =
|
|
46877
|
+
const { path: path3 } = failure;
|
|
46878
|
+
const msg = path3.length === 0 ? message : `At path: ${path3.join(".")} -- ${message}`;
|
|
46875
46879
|
super(explanation ?? msg);
|
|
46876
46880
|
if (explanation != null)
|
|
46877
46881
|
this.cause = msg;
|
|
@@ -46909,15 +46913,15 @@ function toFailure2(result, context, struct2, value2) {
|
|
|
46909
46913
|
} else if (typeof result === "string") {
|
|
46910
46914
|
result = { message: result };
|
|
46911
46915
|
}
|
|
46912
|
-
const { path:
|
|
46916
|
+
const { path: path3, branch } = context;
|
|
46913
46917
|
const { type: type22 } = struct2;
|
|
46914
46918
|
const { refinement, message = `Expected a value of type \`${type22}\`${refinement ? ` with refinement \`${refinement}\`` : ""}, but received: \`${print2(value2)}\`` } = result;
|
|
46915
46919
|
return {
|
|
46916
46920
|
value: value2,
|
|
46917
46921
|
type: type22,
|
|
46918
46922
|
refinement,
|
|
46919
|
-
key:
|
|
46920
|
-
path:
|
|
46923
|
+
key: path3[path3.length - 1],
|
|
46924
|
+
path: path3,
|
|
46921
46925
|
branch,
|
|
46922
46926
|
...result,
|
|
46923
46927
|
message
|
|
@@ -46935,8 +46939,8 @@ function* toFailures2(result, context, struct2, value2) {
|
|
|
46935
46939
|
}
|
|
46936
46940
|
}
|
|
46937
46941
|
function* run2(value2, struct2, options = {}) {
|
|
46938
|
-
const { path:
|
|
46939
|
-
const ctx = { path:
|
|
46942
|
+
const { path: path3 = [], branch = [value2], coerce: coerce22 = false, mask: mask22 = false } = options;
|
|
46943
|
+
const ctx = { path: path3, branch, mask: mask22 };
|
|
46940
46944
|
if (coerce22) {
|
|
46941
46945
|
value2 = struct2.coercer(value2, ctx);
|
|
46942
46946
|
}
|
|
@@ -46948,7 +46952,7 @@ function* run2(value2, struct2, options = {}) {
|
|
|
46948
46952
|
}
|
|
46949
46953
|
for (let [k, v, s] of struct2.entries(value2, ctx)) {
|
|
46950
46954
|
const ts = run2(v, s, {
|
|
46951
|
-
path: k === void 0 ?
|
|
46955
|
+
path: k === void 0 ? path3 : [...path3, k],
|
|
46952
46956
|
branch: k === void 0 ? branch : [...branch, v],
|
|
46953
46957
|
coerce: coerce22,
|
|
46954
46958
|
mask: mask22,
|
|
@@ -57305,6 +57309,8 @@ var DimClient = class {
|
|
|
57305
57309
|
config;
|
|
57306
57310
|
authenticated = false;
|
|
57307
57311
|
userId = null;
|
|
57312
|
+
eventQueue = [];
|
|
57313
|
+
unsubscribers = [];
|
|
57308
57314
|
constructor(config) {
|
|
57309
57315
|
this.config = config;
|
|
57310
57316
|
const secretKeyBytes = esm_default2.decode(config.walletPrivateKey);
|
|
@@ -57360,6 +57366,97 @@ var DimClient = class {
|
|
|
57360
57366
|
async ensureConnected(timeoutMs = 1e4) {
|
|
57361
57367
|
await this.sdk.ensureWebSocketConnected(timeoutMs);
|
|
57362
57368
|
}
|
|
57369
|
+
/**
|
|
57370
|
+
* Subscribe to key WS events and buffer them for agent consumption.
|
|
57371
|
+
* Call after authenticate() when the WS transport is connected.
|
|
57372
|
+
*/
|
|
57373
|
+
startEventListeners() {
|
|
57374
|
+
const events = [
|
|
57375
|
+
"chat:message",
|
|
57376
|
+
"notification",
|
|
57377
|
+
"lobby:matched",
|
|
57378
|
+
"lobby:invitation",
|
|
57379
|
+
"game:turn",
|
|
57380
|
+
"game:completed"
|
|
57381
|
+
];
|
|
57382
|
+
for (const event of events) {
|
|
57383
|
+
this.unsubscribers.push(
|
|
57384
|
+
this.sdk.events.subscribe(event, (payload) => {
|
|
57385
|
+
this.eventQueue.push({
|
|
57386
|
+
event,
|
|
57387
|
+
payload,
|
|
57388
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
57389
|
+
});
|
|
57390
|
+
this.writeHeartbeat().catch(() => {
|
|
57391
|
+
});
|
|
57392
|
+
})
|
|
57393
|
+
);
|
|
57394
|
+
}
|
|
57395
|
+
}
|
|
57396
|
+
/** Write HEARTBEAT.md with pending event summary for OpenClaw's heartbeat cycle. */
|
|
57397
|
+
async writeHeartbeat() {
|
|
57398
|
+
if (!this.config.heartbeatPath) return;
|
|
57399
|
+
const filePath = this.resolveHeartbeatPath();
|
|
57400
|
+
const count = this.eventQueue.length;
|
|
57401
|
+
if (count === 0) return;
|
|
57402
|
+
const lines = ["# DIM Heartbeat", ""];
|
|
57403
|
+
const eventTypes = new Set(this.eventQueue.map((e) => e.event));
|
|
57404
|
+
if (eventTypes.has("chat:message")) {
|
|
57405
|
+
lines.push("- You have new DMs \u2014 call dim_check_notifications");
|
|
57406
|
+
}
|
|
57407
|
+
if (eventTypes.has("notification")) {
|
|
57408
|
+
lines.push(
|
|
57409
|
+
"- New notifications (challenges, friend requests, game results) \u2014 call dim_check_notifications"
|
|
57410
|
+
);
|
|
57411
|
+
}
|
|
57412
|
+
if (eventTypes.has("lobby:matched") || eventTypes.has("lobby:invitation")) {
|
|
57413
|
+
lines.push("- A game match is ready \u2014 call dim_get_pending_events");
|
|
57414
|
+
}
|
|
57415
|
+
if (eventTypes.has("game:turn")) {
|
|
57416
|
+
lines.push("- It's your turn in a game \u2014 call dim_get_pending_events");
|
|
57417
|
+
}
|
|
57418
|
+
if (eventTypes.has("game:completed")) {
|
|
57419
|
+
lines.push("- A game has completed \u2014 call dim_get_pending_events");
|
|
57420
|
+
}
|
|
57421
|
+
lines.push("");
|
|
57422
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
57423
|
+
const tmp = `${filePath}.tmp`;
|
|
57424
|
+
await writeFile(tmp, lines.join("\n"), "utf8");
|
|
57425
|
+
await rename(tmp, filePath);
|
|
57426
|
+
}
|
|
57427
|
+
resolveHeartbeatPath() {
|
|
57428
|
+
const p = this.config.heartbeatPath;
|
|
57429
|
+
if (p.startsWith("~/") && process.env.HOME) {
|
|
57430
|
+
return path.join(process.env.HOME, p.slice(2));
|
|
57431
|
+
}
|
|
57432
|
+
return path.resolve(p);
|
|
57433
|
+
}
|
|
57434
|
+
/** Drain all buffered events since last call. */
|
|
57435
|
+
drainEvents() {
|
|
57436
|
+
return this.eventQueue.splice(0);
|
|
57437
|
+
}
|
|
57438
|
+
/** Peek at buffered event count without draining. */
|
|
57439
|
+
get pendingEventCount() {
|
|
57440
|
+
return this.eventQueue.length;
|
|
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
|
+
}
|
|
57363
57460
|
getKeypair() {
|
|
57364
57461
|
return this.keypair;
|
|
57365
57462
|
}
|
|
@@ -57373,8 +57470,8 @@ function getPluginConfig(api) {
|
|
|
57373
57470
|
return dimclawEntry?.config ?? null;
|
|
57374
57471
|
}
|
|
57375
57472
|
function resolveStorePath(storePath) {
|
|
57376
|
-
const expanded = storePath.startsWith("~/") && process.env.HOME ?
|
|
57377
|
-
return
|
|
57473
|
+
const expanded = storePath.startsWith("~/") && process.env.HOME ? path2.join(process.env.HOME, storePath.slice(2)) : storePath;
|
|
57474
|
+
return path2.resolve(expanded);
|
|
57378
57475
|
}
|
|
57379
57476
|
async function readWalletFile(storePath) {
|
|
57380
57477
|
try {
|
|
@@ -57394,14 +57491,14 @@ async function readWalletFile(storePath) {
|
|
|
57394
57491
|
}
|
|
57395
57492
|
}
|
|
57396
57493
|
async function writeWalletFile(storePath, record3) {
|
|
57397
|
-
await
|
|
57494
|
+
await mkdir2(path2.dirname(storePath), { recursive: true });
|
|
57398
57495
|
const tmp = `${storePath}.tmp`;
|
|
57399
|
-
await
|
|
57496
|
+
await writeFile2(tmp, `${JSON.stringify(record3, null, 2)}
|
|
57400
57497
|
`, {
|
|
57401
57498
|
encoding: "utf8",
|
|
57402
57499
|
mode: 384
|
|
57403
57500
|
});
|
|
57404
|
-
await
|
|
57501
|
+
await rename2(tmp, storePath);
|
|
57405
57502
|
}
|
|
57406
57503
|
function createWalletRecord() {
|
|
57407
57504
|
const keypair = Keypair.generate();
|
|
@@ -57422,6 +57519,194 @@ async function resolveWalletKey(config) {
|
|
|
57422
57519
|
await writeWalletFile(storePath, record3);
|
|
57423
57520
|
return record3.walletPrivateKey;
|
|
57424
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
|
+
}
|
|
57425
57710
|
function textResult(text, isError = false) {
|
|
57426
57711
|
return {
|
|
57427
57712
|
content: [{ type: "text", text }],
|
|
@@ -57430,15 +57715,32 @@ function textResult(text, isError = false) {
|
|
|
57430
57715
|
}
|
|
57431
57716
|
function register(api) {
|
|
57432
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
|
+
}
|
|
57433
57734
|
async function getClient() {
|
|
57434
57735
|
if (client) return client;
|
|
57435
|
-
|
|
57436
|
-
if (!
|
|
57437
|
-
const walletPrivateKey = await resolveWalletKey(
|
|
57736
|
+
pluginConfig = getPluginConfig(api);
|
|
57737
|
+
if (!pluginConfig) return null;
|
|
57738
|
+
const walletPrivateKey = await resolveWalletKey(pluginConfig);
|
|
57438
57739
|
if (!walletPrivateKey) return null;
|
|
57439
57740
|
client = new DimClient({
|
|
57440
57741
|
walletPrivateKey,
|
|
57441
|
-
apiUrl:
|
|
57742
|
+
apiUrl: pluginConfig.apiUrl,
|
|
57743
|
+
heartbeatPath: pluginConfig.heartbeatPath
|
|
57442
57744
|
});
|
|
57443
57745
|
return client;
|
|
57444
57746
|
}
|
|
@@ -57461,6 +57763,7 @@ function register(api) {
|
|
|
57461
57763
|
if ("error" in c) return c.error;
|
|
57462
57764
|
try {
|
|
57463
57765
|
const result = await c.authenticate();
|
|
57766
|
+
c.startEventListeners();
|
|
57464
57767
|
const nextSteps = [];
|
|
57465
57768
|
if (result.username == null || result.username === "") {
|
|
57466
57769
|
nextSteps.push(
|
|
@@ -57488,6 +57791,15 @@ function register(api) {
|
|
|
57488
57791
|
userId: result.userId,
|
|
57489
57792
|
username: result.username ?? null,
|
|
57490
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
|
+
},
|
|
57491
57803
|
nextSteps
|
|
57492
57804
|
};
|
|
57493
57805
|
return textResult(JSON.stringify(response, null, 2));
|
|
@@ -57692,7 +58004,23 @@ function register(api) {
|
|
|
57692
58004
|
name: "dim_redeem_shares",
|
|
57693
58005
|
description: "Redeem shares after market resolution."
|
|
57694
58006
|
},
|
|
57695
|
-
{ name: "dim_get_market_analytics", description: "Get market analytics." }
|
|
58007
|
+
{ name: "dim_get_market_analytics", description: "Get market analytics." },
|
|
58008
|
+
{
|
|
58009
|
+
name: "dim_get_pending_events",
|
|
58010
|
+
description: "Drain buffered real-time events (DMs, challenges, game turns). Call regularly."
|
|
58011
|
+
},
|
|
58012
|
+
{
|
|
58013
|
+
name: "dim_check_notifications",
|
|
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."
|
|
58023
|
+
}
|
|
57696
58024
|
];
|
|
57697
58025
|
api.registerTool({
|
|
57698
58026
|
name: "dim_list_instructions",
|
|
@@ -57757,9 +58085,12 @@ function register(api) {
|
|
|
57757
58085
|
if ("error" in c) return c.error;
|
|
57758
58086
|
const recipient = String(params.recipient ?? "");
|
|
57759
58087
|
const amount = Number(params.amount ?? 0);
|
|
58088
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58089
|
+
if (limitErr) return textResult(limitErr, true);
|
|
57760
58090
|
try {
|
|
57761
58091
|
const amountMinor = Math.round(amount * 1e6);
|
|
57762
58092
|
const result = await c.sdk.wallet.send(recipient, amountMinor);
|
|
58093
|
+
c.recordSpend(amountMinor);
|
|
57763
58094
|
return textResult(
|
|
57764
58095
|
JSON.stringify(
|
|
57765
58096
|
{
|
|
@@ -57806,9 +58137,12 @@ function register(api) {
|
|
|
57806
58137
|
if ("error" in c) return c.error;
|
|
57807
58138
|
const recipientUsername = String(params.recipientUsername ?? "");
|
|
57808
58139
|
const amount = Number(params.amount ?? 0);
|
|
58140
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58141
|
+
if (limitErr) return textResult(limitErr, true);
|
|
57809
58142
|
try {
|
|
57810
58143
|
const amountMinor = Math.round(amount * 1e6);
|
|
57811
58144
|
const result = await c.sdk.tips.send(recipientUsername, amountMinor);
|
|
58145
|
+
c.recordSpend(amountMinor);
|
|
57812
58146
|
return textResult(
|
|
57813
58147
|
JSON.stringify(
|
|
57814
58148
|
{
|
|
@@ -58197,9 +58531,15 @@ function register(api) {
|
|
|
58197
58531
|
const c = await requireClient();
|
|
58198
58532
|
if ("error" in c) return c.error;
|
|
58199
58533
|
const gameType = String(params.gameType ?? "");
|
|
58200
|
-
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
|
+
}
|
|
58201
58540
|
try {
|
|
58202
58541
|
const lobby = await c.sdk.lobbies.createLobby(gameType, betAmount);
|
|
58542
|
+
if (betAmount) c.recordSpend(betAmount);
|
|
58203
58543
|
return textResult(
|
|
58204
58544
|
JSON.stringify(
|
|
58205
58545
|
{
|
|
@@ -58397,12 +58737,15 @@ function register(api) {
|
|
|
58397
58737
|
const c = await requireClient();
|
|
58398
58738
|
if ("error" in c) return c.error;
|
|
58399
58739
|
const amount = Number(params.amount ?? 0);
|
|
58740
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
58741
|
+
if (limitErr) return textResult(limitErr, true);
|
|
58400
58742
|
try {
|
|
58401
58743
|
const amountMinor = Math.round(amount * 1e6);
|
|
58402
58744
|
const result = await c.sdk.games.sendDonation(
|
|
58403
58745
|
String(params.gameId ?? ""),
|
|
58404
58746
|
amountMinor
|
|
58405
58747
|
);
|
|
58748
|
+
c.recordSpend(amountMinor);
|
|
58406
58749
|
return textResult(
|
|
58407
58750
|
JSON.stringify(
|
|
58408
58751
|
{
|
|
@@ -58983,6 +59326,8 @@ function register(api) {
|
|
|
58983
59326
|
const amount = Number(params.amount ?? 0);
|
|
58984
59327
|
const gameId = String(params.gameId ?? "");
|
|
58985
59328
|
const outcomeId = String(params.outcomeId ?? "");
|
|
59329
|
+
const limitErr = checkSpendLimit(c, amount);
|
|
59330
|
+
if (limitErr) return textResult(limitErr, true);
|
|
58986
59331
|
try {
|
|
58987
59332
|
const amountMinor = Math.round(amount * 1e6);
|
|
58988
59333
|
const { transaction: txBase64 } = await c.sdk.markets.prepareBuyOrder(
|
|
@@ -58999,6 +59344,7 @@ function register(api) {
|
|
|
58999
59344
|
outcomeId,
|
|
59000
59345
|
amountMinor
|
|
59001
59346
|
);
|
|
59347
|
+
c.recordSpend(amountMinor);
|
|
59002
59348
|
return textResult(
|
|
59003
59349
|
JSON.stringify(
|
|
59004
59350
|
{
|
|
@@ -59186,6 +59532,137 @@ function register(api) {
|
|
|
59186
59532
|
}
|
|
59187
59533
|
}
|
|
59188
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
|
+
});
|
|
59600
|
+
api.registerTool({
|
|
59601
|
+
name: "dim_get_pending_events",
|
|
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.",
|
|
59603
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
59604
|
+
async execute() {
|
|
59605
|
+
const c = await requireClient();
|
|
59606
|
+
if ("error" in c) return c.error;
|
|
59607
|
+
try {
|
|
59608
|
+
const events = c.drainEvents();
|
|
59609
|
+
return textResult(
|
|
59610
|
+
JSON.stringify(
|
|
59611
|
+
{
|
|
59612
|
+
count: events.length,
|
|
59613
|
+
events,
|
|
59614
|
+
hint: events.length === 0 ? "No new events since last check." : "Process these events and take action as needed."
|
|
59615
|
+
},
|
|
59616
|
+
null,
|
|
59617
|
+
2
|
|
59618
|
+
)
|
|
59619
|
+
);
|
|
59620
|
+
} catch (err) {
|
|
59621
|
+
return textResult(
|
|
59622
|
+
`Failed to get pending events: ${err instanceof Error ? err.message : String(err)}`,
|
|
59623
|
+
true
|
|
59624
|
+
);
|
|
59625
|
+
}
|
|
59626
|
+
}
|
|
59627
|
+
});
|
|
59628
|
+
api.registerTool({
|
|
59629
|
+
name: "dim_check_notifications",
|
|
59630
|
+
description: "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.",
|
|
59631
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
59632
|
+
async execute() {
|
|
59633
|
+
const c = await requireClient();
|
|
59634
|
+
if ("error" in c) return c.error;
|
|
59635
|
+
try {
|
|
59636
|
+
const [notifications, dmThreads, friendRequests] = await Promise.all([
|
|
59637
|
+
c.sdk.notifications.list({ page: 1, limit: 20 }),
|
|
59638
|
+
c.sdk.chat.listDmThreads(),
|
|
59639
|
+
c.sdk.users.getIncomingFriendRequests()
|
|
59640
|
+
]);
|
|
59641
|
+
const unreadDms = dmThreads.filter(
|
|
59642
|
+
(t) => (t.unreadCount ?? 0) > 0
|
|
59643
|
+
);
|
|
59644
|
+
return textResult(
|
|
59645
|
+
JSON.stringify(
|
|
59646
|
+
{
|
|
59647
|
+
unreadNotificationCount: notifications.unreadCount,
|
|
59648
|
+
notifications: notifications.notifications.filter((n) => !n.read),
|
|
59649
|
+
unreadDmThreads: unreadDms,
|
|
59650
|
+
incomingFriendRequests: friendRequests,
|
|
59651
|
+
pendingWsEvents: c.pendingEventCount,
|
|
59652
|
+
hint: "Use dim_get_pending_events to drain buffered real-time events."
|
|
59653
|
+
},
|
|
59654
|
+
null,
|
|
59655
|
+
2
|
|
59656
|
+
)
|
|
59657
|
+
);
|
|
59658
|
+
} catch (err) {
|
|
59659
|
+
return textResult(
|
|
59660
|
+
`Failed to check notifications: ${err instanceof Error ? err.message : String(err)}`,
|
|
59661
|
+
true
|
|
59662
|
+
);
|
|
59663
|
+
}
|
|
59664
|
+
}
|
|
59665
|
+
});
|
|
59189
59666
|
}
|
|
59190
59667
|
export {
|
|
59191
59668
|
register as default
|