@dimcool/mcp 0.1.30 → 0.1.32
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/README.md +166 -125
- package/dist/index.js +314 -154
- package/dist/server.d.ts +31 -0
- package/dist/server.js +19371 -0
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -10964,7 +10964,7 @@ var require_money = __commonJS2({
|
|
|
10964
10964
|
"../utils/dist/money.js"(exports) {
|
|
10965
10965
|
"use strict";
|
|
10966
10966
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10967
|
-
exports.SOL_LAMPORTS = exports.MICRO_UNITS = void 0;
|
|
10967
|
+
exports.SOL_MINT = exports.SOL_LAMPORTS = exports.MICRO_UNITS = void 0;
|
|
10968
10968
|
exports.isSolMint = isSolMint;
|
|
10969
10969
|
exports.formatMoneyMinor = formatMoneyMinor2;
|
|
10970
10970
|
exports.toMajor = toMajor2;
|
|
@@ -10977,12 +10977,12 @@ var require_money = __commonJS2({
|
|
|
10977
10977
|
exports.formatMoneyMinorCompact = formatMoneyMinorCompact;
|
|
10978
10978
|
exports.MICRO_UNITS = 1e6;
|
|
10979
10979
|
exports.SOL_LAMPORTS = 1e9;
|
|
10980
|
-
|
|
10980
|
+
exports.SOL_MINT = "SOL";
|
|
10981
10981
|
var SOL_SYSTEM_PROGRAM = "11111111111111111111111111111111";
|
|
10982
10982
|
function isSolMint(mint) {
|
|
10983
10983
|
if (!mint)
|
|
10984
10984
|
return false;
|
|
10985
|
-
return mint ===
|
|
10985
|
+
return mint === exports.SOL_MINT || mint === SOL_SYSTEM_PROGRAM;
|
|
10986
10986
|
}
|
|
10987
10987
|
function formatMoneyMinor2(amountMinor, fractionDigits = 2) {
|
|
10988
10988
|
return (amountMinor / exports.MICRO_UNITS).toFixed(fractionDigits);
|
|
@@ -11086,7 +11086,7 @@ var require_dist = __commonJS2({
|
|
|
11086
11086
|
"../utils/dist/index.js"(exports) {
|
|
11087
11087
|
"use strict";
|
|
11088
11088
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11089
|
-
exports.formatMoneyMinorCompact = exports.formatCurrencyPartsForToken = exports.formatCurrencyParts = exports.kformatMoney = exports.kformat = exports.formatSolMinor = exports.toSolMajor = exports.toMajor = exports.formatMoneyMinor = exports.isSolMint = exports.SOL_LAMPORTS = exports.MICRO_UNITS = void 0;
|
|
11089
|
+
exports.formatMoneyMinorCompact = exports.formatCurrencyPartsForToken = exports.formatCurrencyParts = exports.kformatMoney = exports.kformat = exports.formatSolMinor = exports.toSolMajor = exports.toMajor = exports.formatMoneyMinor = exports.isSolMint = exports.SOL_MINT = exports.SOL_LAMPORTS = exports.MICRO_UNITS = void 0;
|
|
11090
11090
|
var money_1 = require_money();
|
|
11091
11091
|
Object.defineProperty(exports, "MICRO_UNITS", { enumerable: true, get: function() {
|
|
11092
11092
|
return money_1.MICRO_UNITS;
|
|
@@ -11094,6 +11094,9 @@ var require_dist = __commonJS2({
|
|
|
11094
11094
|
Object.defineProperty(exports, "SOL_LAMPORTS", { enumerable: true, get: function() {
|
|
11095
11095
|
return money_1.SOL_LAMPORTS;
|
|
11096
11096
|
} });
|
|
11097
|
+
Object.defineProperty(exports, "SOL_MINT", { enumerable: true, get: function() {
|
|
11098
|
+
return money_1.SOL_MINT;
|
|
11099
|
+
} });
|
|
11097
11100
|
Object.defineProperty(exports, "isSolMint", { enumerable: true, get: function() {
|
|
11098
11101
|
return money_1.isSolMint;
|
|
11099
11102
|
} });
|
|
@@ -11630,6 +11633,9 @@ var Admin = class {
|
|
|
11630
11633
|
this.http = http;
|
|
11631
11634
|
this.logger = logger2;
|
|
11632
11635
|
}
|
|
11636
|
+
async getInternalBots() {
|
|
11637
|
+
return this.http.get("/admin/internal-bots");
|
|
11638
|
+
}
|
|
11633
11639
|
async getUserById(id) {
|
|
11634
11640
|
return this.http.get(`/admin/users/${id}`);
|
|
11635
11641
|
}
|
|
@@ -11981,6 +11987,13 @@ var Lobbies = class {
|
|
|
11981
11987
|
setLobbyStore(store) {
|
|
11982
11988
|
this.lobbyStore = store;
|
|
11983
11989
|
}
|
|
11990
|
+
/**
|
|
11991
|
+
* Create a new game lobby.
|
|
11992
|
+
*
|
|
11993
|
+
* **Important:** Creating a lobby automatically closes and refunds any
|
|
11994
|
+
* existing open or queued lobby for this user. You do not need to manually
|
|
11995
|
+
* leave or cancel a previous lobby before calling this.
|
|
11996
|
+
*/
|
|
11984
11997
|
async createLobby(gameType, betAmount) {
|
|
11985
11998
|
return this.http.post("/lobbies", { gameType, betAmount });
|
|
11986
11999
|
}
|
|
@@ -12044,21 +12057,6 @@ var Lobbies = class {
|
|
|
12044
12057
|
async deleteLobby(lobbyId) {
|
|
12045
12058
|
return this.http.delete(`/lobbies/admin/${lobbyId}`);
|
|
12046
12059
|
}
|
|
12047
|
-
/**
|
|
12048
|
-
* Play again: Create a new lobby and prepare deposit in one flow.
|
|
12049
|
-
* Returns the lobby and unsigned transaction that needs to be signed.
|
|
12050
|
-
* @param gameType - The game type to play again
|
|
12051
|
-
* @param betAmount - The bet amount (same as previous game)
|
|
12052
|
-
* @param escrow - The escrow service instance (from sdk.escrow)
|
|
12053
|
-
*/
|
|
12054
|
-
async playAgain(gameType, betAmount, escrow) {
|
|
12055
|
-
const lobby = await this.createLobby(gameType, betAmount);
|
|
12056
|
-
const { transaction } = await escrow.prepareAndStartDeposit(lobby.id);
|
|
12057
|
-
return {
|
|
12058
|
-
lobby,
|
|
12059
|
-
unsignedTransaction: transaction
|
|
12060
|
-
};
|
|
12061
|
-
}
|
|
12062
12060
|
};
|
|
12063
12061
|
var Games = class {
|
|
12064
12062
|
constructor(http, wallet, logger2) {
|
|
@@ -12578,6 +12576,7 @@ var Achievements = class {
|
|
|
12578
12576
|
return this.http.get(`/achievements/users/${userId}`);
|
|
12579
12577
|
}
|
|
12580
12578
|
};
|
|
12579
|
+
var import_utils = __toESM2(require_dist(), 1);
|
|
12581
12580
|
var MIN_TRANSFER_AMOUNT = 5e4;
|
|
12582
12581
|
var MIN_SOL_TRANSFER_AMOUNT = 1e6;
|
|
12583
12582
|
var Wallet = class {
|
|
@@ -14253,8 +14252,21 @@ function createGameActionsStore(transport2) {
|
|
|
14253
14252
|
});
|
|
14254
14253
|
};
|
|
14255
14254
|
const isNonRpsState = (state) => Boolean(state && !isRpsState(state));
|
|
14255
|
+
const pendingEvents = /* @__PURE__ */ new Map();
|
|
14256
|
+
function enqueue(gameId, event) {
|
|
14257
|
+
const q = pendingEvents.get(gameId) ?? [];
|
|
14258
|
+
q.push(event);
|
|
14259
|
+
pendingEvents.set(gameId, q);
|
|
14260
|
+
}
|
|
14261
|
+
function drainQueue(gameId) {
|
|
14262
|
+
const q = pendingEvents.get(gameId);
|
|
14263
|
+
if (!q?.length) return;
|
|
14264
|
+
pendingEvents.delete(gameId);
|
|
14265
|
+
for (const ev of q) applyWsEvent(ev);
|
|
14266
|
+
}
|
|
14256
14267
|
const setBaseState = (gameId, state) => {
|
|
14257
14268
|
updateState(gameId, state);
|
|
14269
|
+
drainQueue(gameId);
|
|
14258
14270
|
};
|
|
14259
14271
|
const clearState = (gameId) => {
|
|
14260
14272
|
store.updateState((state) => {
|
|
@@ -14264,6 +14276,7 @@ function createGameActionsStore(transport2) {
|
|
|
14264
14276
|
const { [gameId]: _, ...rest } = state.statesByGameId;
|
|
14265
14277
|
return { ...state, statesByGameId: rest };
|
|
14266
14278
|
});
|
|
14279
|
+
pendingEvents.delete(gameId);
|
|
14267
14280
|
};
|
|
14268
14281
|
const applyWsEvent = (event) => {
|
|
14269
14282
|
switch (event.event) {
|
|
@@ -14282,7 +14295,10 @@ function createGameActionsStore(transport2) {
|
|
|
14282
14295
|
}
|
|
14283
14296
|
case "game:rps:starting": {
|
|
14284
14297
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14285
|
-
if (!current || !isRpsState(current))
|
|
14298
|
+
if (!current || !isRpsState(current)) {
|
|
14299
|
+
enqueue(event.payload.gameId, event);
|
|
14300
|
+
return;
|
|
14301
|
+
}
|
|
14286
14302
|
const betAmount = typeof event.payload.betAmount === "number" ? event.payload.betAmount : void 0;
|
|
14287
14303
|
const startedAt = typeof event.payload.startedAt === "string" ? event.payload.startedAt : current.roundState.startedAt;
|
|
14288
14304
|
const bufferEndsAt = typeof event.payload.bufferEndsAt === "string" ? event.payload.bufferEndsAt : current.roundState.selectionEndsAt;
|
|
@@ -14303,7 +14319,10 @@ function createGameActionsStore(transport2) {
|
|
|
14303
14319
|
}
|
|
14304
14320
|
case "game:rps:round:started": {
|
|
14305
14321
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14306
|
-
if (!current || !isRpsState(current))
|
|
14322
|
+
if (!current || !isRpsState(current)) {
|
|
14323
|
+
enqueue(event.payload.gameId, event);
|
|
14324
|
+
return;
|
|
14325
|
+
}
|
|
14307
14326
|
const actions = {};
|
|
14308
14327
|
const baseUsers = /* @__PURE__ */ new Set();
|
|
14309
14328
|
Object.keys(current.roundState.actions).forEach(
|
|
@@ -14337,7 +14356,10 @@ function createGameActionsStore(transport2) {
|
|
|
14337
14356
|
}
|
|
14338
14357
|
case "game:rps:action:received": {
|
|
14339
14358
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14340
|
-
if (!current || !isRpsState(current))
|
|
14359
|
+
if (!current || !isRpsState(current)) {
|
|
14360
|
+
enqueue(event.payload.gameId, event);
|
|
14361
|
+
return;
|
|
14362
|
+
}
|
|
14341
14363
|
const updated = {
|
|
14342
14364
|
...current,
|
|
14343
14365
|
roundState: {
|
|
@@ -14356,7 +14378,10 @@ function createGameActionsStore(transport2) {
|
|
|
14356
14378
|
}
|
|
14357
14379
|
case "game:rps:timer:cutoff": {
|
|
14358
14380
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14359
|
-
if (!current || !isRpsState(current))
|
|
14381
|
+
if (!current || !isRpsState(current)) {
|
|
14382
|
+
enqueue(event.payload.gameId, event);
|
|
14383
|
+
return;
|
|
14384
|
+
}
|
|
14360
14385
|
const updated = {
|
|
14361
14386
|
...current,
|
|
14362
14387
|
roundState: {
|
|
@@ -14370,7 +14395,10 @@ function createGameActionsStore(transport2) {
|
|
|
14370
14395
|
}
|
|
14371
14396
|
case "game:rps:round:reveal": {
|
|
14372
14397
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14373
|
-
if (!current || !isRpsState(current))
|
|
14398
|
+
if (!current || !isRpsState(current)) {
|
|
14399
|
+
enqueue(event.payload.gameId, event);
|
|
14400
|
+
return;
|
|
14401
|
+
}
|
|
14374
14402
|
const actions = {};
|
|
14375
14403
|
const payloadActions = event.payload.actions;
|
|
14376
14404
|
Object.keys(payloadActions || {}).forEach((userId) => {
|
|
@@ -14394,7 +14422,10 @@ function createGameActionsStore(transport2) {
|
|
|
14394
14422
|
}
|
|
14395
14423
|
case "game:rps:round:completed": {
|
|
14396
14424
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14397
|
-
if (!current || !isRpsState(current))
|
|
14425
|
+
if (!current || !isRpsState(current)) {
|
|
14426
|
+
enqueue(event.payload.gameId, event);
|
|
14427
|
+
return;
|
|
14428
|
+
}
|
|
14398
14429
|
const roundHistory = [
|
|
14399
14430
|
...current.roundHistory || [],
|
|
14400
14431
|
{
|
|
@@ -14419,7 +14450,10 @@ function createGameActionsStore(transport2) {
|
|
|
14419
14450
|
}
|
|
14420
14451
|
case "game:rps:timeout": {
|
|
14421
14452
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14422
|
-
if (!current || !isRpsState(current))
|
|
14453
|
+
if (!current || !isRpsState(current)) {
|
|
14454
|
+
enqueue(event.payload.gameId, event);
|
|
14455
|
+
return;
|
|
14456
|
+
}
|
|
14423
14457
|
const timedOutUser = event.payload.playerId;
|
|
14424
14458
|
const action = event.payload.action;
|
|
14425
14459
|
const updated = {
|
|
@@ -14444,7 +14478,10 @@ function createGameActionsStore(transport2) {
|
|
|
14444
14478
|
const payload = event.payload;
|
|
14445
14479
|
const { gameId } = payload;
|
|
14446
14480
|
const current = store.getState().statesByGameId[gameId];
|
|
14447
|
-
if (!current)
|
|
14481
|
+
if (!current) {
|
|
14482
|
+
enqueue(gameId, event);
|
|
14483
|
+
return;
|
|
14484
|
+
}
|
|
14448
14485
|
const updated = isRpsCompletionPayload(payload) && isRpsState(current) ? {
|
|
14449
14486
|
...current,
|
|
14450
14487
|
status: "completed",
|
|
@@ -14493,11 +14530,15 @@ function createGameActionsStore(transport2) {
|
|
|
14493
14530
|
const current = store.getState().statesByGameId[gameId];
|
|
14494
14531
|
const updated = current ? { ...current, ...incoming } : incoming;
|
|
14495
14532
|
updateState(gameId, updated);
|
|
14533
|
+
drainQueue(gameId);
|
|
14496
14534
|
break;
|
|
14497
14535
|
}
|
|
14498
14536
|
case "game:rematch:requested": {
|
|
14499
14537
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14500
|
-
if (!current)
|
|
14538
|
+
if (!current) {
|
|
14539
|
+
enqueue(event.payload.gameId, event);
|
|
14540
|
+
return;
|
|
14541
|
+
}
|
|
14501
14542
|
const requestedBy = event.payload.requestedBy;
|
|
14502
14543
|
const userId = event.payload.userId;
|
|
14503
14544
|
const requested = new Set(
|
|
@@ -14513,7 +14554,10 @@ function createGameActionsStore(transport2) {
|
|
|
14513
14554
|
}
|
|
14514
14555
|
case "game:rematch:cancelled": {
|
|
14515
14556
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14516
|
-
if (!current)
|
|
14557
|
+
if (!current) {
|
|
14558
|
+
enqueue(event.payload.gameId, event);
|
|
14559
|
+
return;
|
|
14560
|
+
}
|
|
14517
14561
|
const requestedBy = event.payload.requestedBy ?? [];
|
|
14518
14562
|
const updated = {
|
|
14519
14563
|
...current,
|
|
@@ -14524,7 +14568,10 @@ function createGameActionsStore(transport2) {
|
|
|
14524
14568
|
}
|
|
14525
14569
|
case "game:rematch:started": {
|
|
14526
14570
|
const current = store.getState().statesByGameId[event.payload.gameId];
|
|
14527
|
-
if (!current)
|
|
14571
|
+
if (!current) {
|
|
14572
|
+
enqueue(event.payload.gameId, event);
|
|
14573
|
+
return;
|
|
14574
|
+
}
|
|
14528
14575
|
const updated = {
|
|
14529
14576
|
...current,
|
|
14530
14577
|
rematchRequestedBy: event.payload.playerIds ?? []
|
|
@@ -14535,7 +14582,10 @@ function createGameActionsStore(transport2) {
|
|
|
14535
14582
|
case "game:pot:updated": {
|
|
14536
14583
|
const { gameId, totalPotMinor } = event.payload;
|
|
14537
14584
|
const current = store.getState().statesByGameId[gameId];
|
|
14538
|
-
if (!current)
|
|
14585
|
+
if (!current) {
|
|
14586
|
+
enqueue(gameId, event);
|
|
14587
|
+
return;
|
|
14588
|
+
}
|
|
14539
14589
|
const updated = {
|
|
14540
14590
|
...current,
|
|
14541
14591
|
totalPotMinor
|
|
@@ -14548,12 +14598,123 @@ function createGameActionsStore(transport2) {
|
|
|
14548
14598
|
}
|
|
14549
14599
|
};
|
|
14550
14600
|
const joinGame = (gameId) => transport2.joinRoom(`game:${gameId}`);
|
|
14601
|
+
const getCountdownDigit = (gameId, nowMs) => {
|
|
14602
|
+
const state = store.getState().statesByGameId[gameId];
|
|
14603
|
+
if (!state) return null;
|
|
14604
|
+
if (isRpsState(state)) {
|
|
14605
|
+
if (state.roundState.phase !== "starting") return null;
|
|
14606
|
+
const remaining = new Date(state.roundState.selectionEndsAt).getTime() - nowMs;
|
|
14607
|
+
if (remaining <= 0) return null;
|
|
14608
|
+
return Math.ceil(remaining / 1e3);
|
|
14609
|
+
}
|
|
14610
|
+
const bufferEndsAt = state.bufferEndsAt;
|
|
14611
|
+
if (bufferEndsAt) {
|
|
14612
|
+
const remaining = new Date(bufferEndsAt).getTime() - nowMs;
|
|
14613
|
+
if (remaining <= 0) return null;
|
|
14614
|
+
return Math.ceil(remaining / 1e3);
|
|
14615
|
+
}
|
|
14616
|
+
return null;
|
|
14617
|
+
};
|
|
14618
|
+
const getChessClockTimes = (gameId, nowMs) => {
|
|
14619
|
+
const state = store.getState().statesByGameId[gameId];
|
|
14620
|
+
if (!state || state.gameType !== "chess") return null;
|
|
14621
|
+
const s = state;
|
|
14622
|
+
let whiteMs = s.whiteTimeMs ?? 0;
|
|
14623
|
+
let blackMs = s.blackTimeMs ?? 0;
|
|
14624
|
+
if (s.status === "active" && s.currentPlayerId) {
|
|
14625
|
+
const startedAt = Date.parse(s.turnStartedAt);
|
|
14626
|
+
if (!Number.isNaN(startedAt)) {
|
|
14627
|
+
const elapsed = Math.max(0, nowMs - startedAt);
|
|
14628
|
+
if (s.currentPlayerId === s.whitePlayerId) {
|
|
14629
|
+
whiteMs = Math.max(0, whiteMs - elapsed);
|
|
14630
|
+
} else if (s.currentPlayerId === s.blackPlayerId) {
|
|
14631
|
+
blackMs = Math.max(0, blackMs - elapsed);
|
|
14632
|
+
}
|
|
14633
|
+
}
|
|
14634
|
+
}
|
|
14635
|
+
return { whiteTimeMs: whiteMs, blackTimeMs: blackMs };
|
|
14636
|
+
};
|
|
14637
|
+
const getChessCapturedPieces = (gameId) => {
|
|
14638
|
+
const state = store.getState().statesByGameId[gameId];
|
|
14639
|
+
if (!state || state.gameType !== "chess") return null;
|
|
14640
|
+
const fen = state.fen;
|
|
14641
|
+
if (!fen) return { capturedByWhite: [], capturedByBlack: [] };
|
|
14642
|
+
const placement = fen.split(" ")[0];
|
|
14643
|
+
const white = {};
|
|
14644
|
+
const black = {};
|
|
14645
|
+
for (const char of placement) {
|
|
14646
|
+
if (char === "/" || char >= "1" && char <= "8") continue;
|
|
14647
|
+
const lower = char.toLowerCase();
|
|
14648
|
+
if (char === lower) {
|
|
14649
|
+
black[lower] = (black[lower] ?? 0) + 1;
|
|
14650
|
+
} else {
|
|
14651
|
+
white[lower] = (white[lower] ?? 0) + 1;
|
|
14652
|
+
}
|
|
14653
|
+
}
|
|
14654
|
+
const INITIAL = {
|
|
14655
|
+
p: 8,
|
|
14656
|
+
r: 2,
|
|
14657
|
+
n: 2,
|
|
14658
|
+
b: 2,
|
|
14659
|
+
q: 1,
|
|
14660
|
+
k: 1
|
|
14661
|
+
};
|
|
14662
|
+
const capturedByWhite = [];
|
|
14663
|
+
const capturedByBlack = [];
|
|
14664
|
+
for (const [type, initial] of Object.entries(INITIAL)) {
|
|
14665
|
+
const missingBlack = initial - (black[type] ?? 0);
|
|
14666
|
+
for (let i = 0; i < missingBlack; i++) capturedByWhite.push(`b${type}`);
|
|
14667
|
+
const missingWhite = initial - (white[type] ?? 0);
|
|
14668
|
+
for (let i = 0; i < missingWhite; i++) capturedByBlack.push(`w${type}`);
|
|
14669
|
+
}
|
|
14670
|
+
return { capturedByWhite, capturedByBlack };
|
|
14671
|
+
};
|
|
14672
|
+
const getTicTacToeClockTimes = (gameId, nowMs) => {
|
|
14673
|
+
const state = store.getState().statesByGameId[gameId];
|
|
14674
|
+
if (!state || state.gameType !== "tic-tac-toe") return null;
|
|
14675
|
+
const s = state;
|
|
14676
|
+
let xMs = s.xTimeMs ?? 0;
|
|
14677
|
+
let oMs = s.oTimeMs ?? 0;
|
|
14678
|
+
if (s.status === "active" && s.currentPlayerId) {
|
|
14679
|
+
const currentMark = s.playerMarks[s.currentPlayerId];
|
|
14680
|
+
const startedAt = Date.parse(s.turnStartedAt);
|
|
14681
|
+
if (!Number.isNaN(startedAt)) {
|
|
14682
|
+
const elapsed = Math.max(0, nowMs - startedAt);
|
|
14683
|
+
if (currentMark === "X") xMs = Math.max(0, xMs - elapsed);
|
|
14684
|
+
else if (currentMark === "O") oMs = Math.max(0, oMs - elapsed);
|
|
14685
|
+
}
|
|
14686
|
+
}
|
|
14687
|
+
return { xTimeMs: xMs, oTimeMs: oMs };
|
|
14688
|
+
};
|
|
14689
|
+
const getConnect4ClockTimes = (gameId, nowMs) => {
|
|
14690
|
+
const state = store.getState().statesByGameId[gameId];
|
|
14691
|
+
if (!state || state.gameType !== "connect-four") return null;
|
|
14692
|
+
const s = state;
|
|
14693
|
+
let redMs = s.redTimeMs ?? 0;
|
|
14694
|
+
let yellowMs = s.yellowTimeMs ?? 0;
|
|
14695
|
+
if (s.status === "active" && s.currentPlayerId) {
|
|
14696
|
+
const currentColor = s.playerColors[s.currentPlayerId];
|
|
14697
|
+
const startedAt = Date.parse(s.turnStartedAt);
|
|
14698
|
+
if (!Number.isNaN(startedAt)) {
|
|
14699
|
+
const elapsed = Math.max(0, nowMs - startedAt);
|
|
14700
|
+
if (currentColor === "RED") redMs = Math.max(0, redMs - elapsed);
|
|
14701
|
+
else if (currentColor === "YELLOW")
|
|
14702
|
+
yellowMs = Math.max(0, yellowMs - elapsed);
|
|
14703
|
+
}
|
|
14704
|
+
}
|
|
14705
|
+
return { redTimeMs: redMs, yellowTimeMs: yellowMs };
|
|
14706
|
+
};
|
|
14551
14707
|
return {
|
|
14552
14708
|
store,
|
|
14553
14709
|
setBaseState,
|
|
14554
14710
|
clearState,
|
|
14555
14711
|
applyWsEvent,
|
|
14556
|
-
joinGame
|
|
14712
|
+
joinGame,
|
|
14713
|
+
getCountdownDigit,
|
|
14714
|
+
getChessClockTimes,
|
|
14715
|
+
getChessCapturedPieces,
|
|
14716
|
+
getTicTacToeClockTimes,
|
|
14717
|
+
getConnect4ClockTimes
|
|
14557
14718
|
};
|
|
14558
14719
|
}
|
|
14559
14720
|
function isRpsState(state) {
|
|
@@ -15211,12 +15372,14 @@ var WsRouter = class {
|
|
|
15211
15372
|
}
|
|
15212
15373
|
const decoded = decodeWsEvent(eventName, payload);
|
|
15213
15374
|
if (!decoded) return;
|
|
15214
|
-
|
|
15215
|
-
|
|
15216
|
-
this.deps.
|
|
15217
|
-
this.deps.
|
|
15218
|
-
this.deps.
|
|
15219
|
-
this.deps.
|
|
15375
|
+
const serverTs = payload !== null && typeof payload === "object" ? payload._serverTs : void 0;
|
|
15376
|
+
const event = serverTs !== void 0 ? { ...decoded, _serverTs: serverTs } : decoded;
|
|
15377
|
+
this.deps.lobbyStore.applyWsEvent(event);
|
|
15378
|
+
this.deps.gameStore.applyWsEvent(event);
|
|
15379
|
+
this.deps.gameActionsStore.applyWsEvent(event);
|
|
15380
|
+
this.deps.chatStore.applyWsEvent(event);
|
|
15381
|
+
this.deps.dmThreadsStore.applyWsEvent(event);
|
|
15382
|
+
this.deps.notificationsStore.applyWsEvent(event);
|
|
15220
15383
|
});
|
|
15221
15384
|
}
|
|
15222
15385
|
stop() {
|
|
@@ -15228,12 +15391,14 @@ var WsRouter = class {
|
|
|
15228
15391
|
this.transport.subscribeEvent(eventName, (payload) => {
|
|
15229
15392
|
const decoded = decodeWsEvent(eventName, payload);
|
|
15230
15393
|
if (!decoded) return;
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
this.deps.
|
|
15234
|
-
this.deps.
|
|
15235
|
-
this.deps.
|
|
15236
|
-
this.deps.
|
|
15394
|
+
const serverTs = payload !== null && typeof payload === "object" ? payload._serverTs : void 0;
|
|
15395
|
+
const event = serverTs !== void 0 ? { ...decoded, _serverTs: serverTs } : decoded;
|
|
15396
|
+
this.deps.lobbyStore.applyWsEvent(event);
|
|
15397
|
+
this.deps.gameStore.applyWsEvent(event);
|
|
15398
|
+
this.deps.gameActionsStore.applyWsEvent(event);
|
|
15399
|
+
this.deps.chatStore.applyWsEvent(event);
|
|
15400
|
+
this.deps.dmThreadsStore.applyWsEvent(event);
|
|
15401
|
+
this.deps.notificationsStore.applyWsEvent(event);
|
|
15237
15402
|
});
|
|
15238
15403
|
}
|
|
15239
15404
|
}
|
|
@@ -15371,15 +15536,38 @@ var SDK = class {
|
|
|
15371
15536
|
return { ...result, lobby };
|
|
15372
15537
|
}
|
|
15373
15538
|
};
|
|
15374
|
-
var
|
|
15375
|
-
var export_MICRO_UNITS =
|
|
15376
|
-
var
|
|
15377
|
-
var
|
|
15539
|
+
var import_utils2 = __toESM2(require_dist(), 1);
|
|
15540
|
+
var export_MICRO_UNITS = import_utils2.MICRO_UNITS;
|
|
15541
|
+
var export_SOL_MINT = import_utils.SOL_MINT;
|
|
15542
|
+
var export_formatMoneyMinor = import_utils2.formatMoneyMinor;
|
|
15543
|
+
var export_toMajor = import_utils2.toMajor;
|
|
15378
15544
|
|
|
15379
15545
|
// ../dim-agent-core/src/client.ts
|
|
15380
15546
|
var import_tweetnacl = __toESM(require_nacl_fast(), 1);
|
|
15381
15547
|
import { Keypair } from "@solana/web3.js";
|
|
15382
15548
|
import bs58 from "bs58";
|
|
15549
|
+
function decodeJwtSub(token) {
|
|
15550
|
+
try {
|
|
15551
|
+
const parts2 = token.split(".");
|
|
15552
|
+
if (parts2.length < 2) return null;
|
|
15553
|
+
const base64 = parts2[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
15554
|
+
const json = Buffer.from(base64, "base64").toString("utf-8");
|
|
15555
|
+
const parsed = JSON.parse(json);
|
|
15556
|
+
return typeof parsed.sub === "string" ? parsed.sub : null;
|
|
15557
|
+
} catch {
|
|
15558
|
+
return null;
|
|
15559
|
+
}
|
|
15560
|
+
}
|
|
15561
|
+
function signatureToBytes(sig) {
|
|
15562
|
+
if (sig.includes("-") || sig.includes("_")) {
|
|
15563
|
+
const padded = sig.replace(/-/g, "+").replace(/_/g, "/") + "==".slice(sig.length % 4 === 0 ? 4 : sig.length % 4);
|
|
15564
|
+
return new Uint8Array(Buffer.from(padded, "base64"));
|
|
15565
|
+
}
|
|
15566
|
+
if (/[+/=]/.test(sig)) {
|
|
15567
|
+
return new Uint8Array(Buffer.from(sig, "base64"));
|
|
15568
|
+
}
|
|
15569
|
+
return bs58.decode(sig);
|
|
15570
|
+
}
|
|
15383
15571
|
var DimAgentClient = class {
|
|
15384
15572
|
sdk;
|
|
15385
15573
|
agentConfig;
|
|
@@ -15406,10 +15594,19 @@ var DimAgentClient = class {
|
|
|
15406
15594
|
} else {
|
|
15407
15595
|
this.keypair = null;
|
|
15408
15596
|
}
|
|
15597
|
+
const storage = new NodeStorage();
|
|
15598
|
+
if (config.accessToken) {
|
|
15599
|
+
storage.set(TOKEN_KEY, config.accessToken);
|
|
15600
|
+
const sub = decodeJwtSub(config.accessToken);
|
|
15601
|
+
if (sub) {
|
|
15602
|
+
this.authenticated = true;
|
|
15603
|
+
this.userId = sub;
|
|
15604
|
+
}
|
|
15605
|
+
}
|
|
15409
15606
|
this.sdk = new SDK({
|
|
15410
15607
|
appId: "dim-agents",
|
|
15411
15608
|
baseUrl: config.apiUrl || "https://api.dim.cool",
|
|
15412
|
-
storage
|
|
15609
|
+
storage,
|
|
15413
15610
|
autoPay: {
|
|
15414
15611
|
enabled: !this.externalSignerMode,
|
|
15415
15612
|
maxAmountMinor: 25e3,
|
|
@@ -15513,10 +15710,10 @@ var DimAgentClient = class {
|
|
|
15513
15710
|
/**
|
|
15514
15711
|
* Complete authentication using an externally provided signature (external signer mode).
|
|
15515
15712
|
* @param address - Solana wallet address (base58)
|
|
15516
|
-
* @param
|
|
15713
|
+
* @param signature - Detached ed25519 signature in base58, base64, or base64url (from sign_solana_message)
|
|
15517
15714
|
*/
|
|
15518
|
-
async completeAuth(address,
|
|
15519
|
-
const signatureBytes =
|
|
15715
|
+
async completeAuth(address, signature) {
|
|
15716
|
+
const signatureBytes = signatureToBytes(signature);
|
|
15520
15717
|
const signedMessage = Buffer.from(signatureBytes).toString("base64");
|
|
15521
15718
|
const response = await this.sdk.auth.loginWithExternalSignature(
|
|
15522
15719
|
address,
|
|
@@ -15670,7 +15867,7 @@ async function requestAuthMessage(client, args) {
|
|
|
15670
15867
|
data: {
|
|
15671
15868
|
message,
|
|
15672
15869
|
address: args.address,
|
|
15673
|
-
nextStep: 'Sign this message with sign_solana_message (networkId: "solana:mainnet"), then call dim_complete_login with the address and the base58
|
|
15870
|
+
nextStep: 'Sign this message with sign_solana_message (networkId: "solana:mainnet"), then call dim_complete_login with the address and the signature. Accepted formats: base58, base64, or base64url (all formats returned by wallet MCPs are accepted).'
|
|
15674
15871
|
}
|
|
15675
15872
|
};
|
|
15676
15873
|
} catch (error) {
|
|
@@ -16916,58 +17113,6 @@ function raceTimeout(promise, ms) {
|
|
|
16916
17113
|
});
|
|
16917
17114
|
}
|
|
16918
17115
|
|
|
16919
|
-
// ../dim-agent-core/src/tools/challenges.ts
|
|
16920
|
-
async function challengeUser(client, args) {
|
|
16921
|
-
try {
|
|
16922
|
-
if (!args.targetUsername && !args.targetUserId) {
|
|
16923
|
-
return {
|
|
16924
|
-
error: "Must provide either targetUsername or targetUserId.",
|
|
16925
|
-
isError: true
|
|
16926
|
-
};
|
|
16927
|
-
}
|
|
16928
|
-
const spendErr = client.checkSpendLimit(args.amount, true);
|
|
16929
|
-
if (spendErr) return { error: spendErr, isError: true };
|
|
16930
|
-
const amountMinor = Math.round(args.amount * 1e6);
|
|
16931
|
-
const result = await client.sdk.challenges.create({
|
|
16932
|
-
gameType: args.gameType,
|
|
16933
|
-
amount: amountMinor,
|
|
16934
|
-
targetUsername: args.targetUsername,
|
|
16935
|
-
targetUserId: args.targetUserId
|
|
16936
|
-
});
|
|
16937
|
-
client.recordSpend(amountMinor);
|
|
16938
|
-
return {
|
|
16939
|
-
data: {
|
|
16940
|
-
...result,
|
|
16941
|
-
amountFormatted: `$${args.amount.toFixed(2)}`,
|
|
16942
|
-
hint: "The challenged user will receive a notification. When they accept, a lobby is created automatically."
|
|
16943
|
-
}
|
|
16944
|
-
};
|
|
16945
|
-
} catch (error) {
|
|
16946
|
-
return {
|
|
16947
|
-
error: `Failed to create challenge: ${error instanceof Error ? error.message : String(error)}`,
|
|
16948
|
-
isError: true
|
|
16949
|
-
};
|
|
16950
|
-
}
|
|
16951
|
-
}
|
|
16952
|
-
async function acceptChallenge(client, args) {
|
|
16953
|
-
try {
|
|
16954
|
-
const result = await client.sdk.challenges.accept(args.challengeId);
|
|
16955
|
-
const spectateUrl = result.gameId ? await getSpectateUrl(client) : null;
|
|
16956
|
-
return {
|
|
16957
|
-
data: {
|
|
16958
|
-
...result,
|
|
16959
|
-
...spectateUrl && { spectateUrl },
|
|
16960
|
-
hint: result.gameId ? `Game started! Call dim_game_loop with gameId "${result.gameId}".${spectateUrl ? ` Tell the user they can spectate at ${spectateUrl}` : ""}` : `Lobby created: ${result.lobbyId}. Use dim_join_queue to start matchmaking.`
|
|
16961
|
-
}
|
|
16962
|
-
};
|
|
16963
|
-
} catch (error) {
|
|
16964
|
-
return {
|
|
16965
|
-
error: `Failed to accept challenge: ${error instanceof Error ? error.message : String(error)}`,
|
|
16966
|
-
isError: true
|
|
16967
|
-
};
|
|
16968
|
-
}
|
|
16969
|
-
}
|
|
16970
|
-
|
|
16971
17116
|
// ../dim-agent-core/src/tools/referrals.ts
|
|
16972
17117
|
async function getReferralSummary(client) {
|
|
16973
17118
|
try {
|
|
@@ -17844,6 +17989,22 @@ async function getGameHistory(client, args) {
|
|
|
17844
17989
|
};
|
|
17845
17990
|
}
|
|
17846
17991
|
}
|
|
17992
|
+
async function reportUser(client, args) {
|
|
17993
|
+
try {
|
|
17994
|
+
await client.sdk.reports.create(args.userId, args.reason);
|
|
17995
|
+
return {
|
|
17996
|
+
data: {
|
|
17997
|
+
success: true,
|
|
17998
|
+
hint: "Report submitted. The DIM moderation team will review it."
|
|
17999
|
+
}
|
|
18000
|
+
};
|
|
18001
|
+
} catch (error) {
|
|
18002
|
+
return {
|
|
18003
|
+
error: `Failed to report user: ${error instanceof Error ? error.message : String(error)}`,
|
|
18004
|
+
isError: true
|
|
18005
|
+
};
|
|
18006
|
+
}
|
|
18007
|
+
}
|
|
17847
18008
|
async function getMyStats(client) {
|
|
17848
18009
|
try {
|
|
17849
18010
|
if (!client.currentUserId) {
|
|
@@ -17889,7 +18050,7 @@ var TOOL_DEFINITIONS = [
|
|
|
17889
18050
|
},
|
|
17890
18051
|
{
|
|
17891
18052
|
name: "dim_complete_login",
|
|
17892
|
-
description: "External wallet login step 2: provide the wallet address and
|
|
18053
|
+
description: "External wallet login step 2: provide the wallet address and signature from sign_solana_message to complete authentication with DIM.",
|
|
17893
18054
|
params: {
|
|
17894
18055
|
address: {
|
|
17895
18056
|
type: "string",
|
|
@@ -17898,7 +18059,7 @@ var TOOL_DEFINITIONS = [
|
|
|
17898
18059
|
},
|
|
17899
18060
|
signature: {
|
|
17900
18061
|
type: "string",
|
|
17901
|
-
description: "
|
|
18062
|
+
description: "Signature from sign_solana_message \u2014 base58, base64, or base64url accepted",
|
|
17902
18063
|
required: true
|
|
17903
18064
|
}
|
|
17904
18065
|
},
|
|
@@ -18342,9 +18503,26 @@ var TOOL_DEFINITIONS = [
|
|
|
18342
18503
|
params: {},
|
|
18343
18504
|
execute: (c) => getMyStats(c)
|
|
18344
18505
|
},
|
|
18506
|
+
{
|
|
18507
|
+
name: "dim_report_user",
|
|
18508
|
+
description: "Report a user for cheating, harassment, or other violations. Rate limited to 5 reports per hour.",
|
|
18509
|
+
params: {
|
|
18510
|
+
userId: {
|
|
18511
|
+
type: "string",
|
|
18512
|
+
description: "The ID of the user to report",
|
|
18513
|
+
required: true
|
|
18514
|
+
},
|
|
18515
|
+
reason: {
|
|
18516
|
+
type: "string",
|
|
18517
|
+
description: "Reason for the report (max 300 characters)",
|
|
18518
|
+
required: true
|
|
18519
|
+
}
|
|
18520
|
+
},
|
|
18521
|
+
execute: (c, a) => reportUser(c, a)
|
|
18522
|
+
},
|
|
18345
18523
|
{
|
|
18346
18524
|
name: "dim_create_lobby",
|
|
18347
|
-
description: "Create a new game lobby. Bet amount is in USDC dollars (e.g., 1.00 for $1.00). A 1% fee (min 1 cent) is charged per player.",
|
|
18525
|
+
description: "Create a new game lobby. Bet amount is in USDC dollars (e.g., 1.00 for $1.00). A 1% fee (min 1 cent) is charged per player. NOTE: Creating a lobby automatically closes and refunds any previous open or queued lobby for this user \u2014 you do not need to clean up manually.",
|
|
18348
18526
|
params: {
|
|
18349
18527
|
gameType: {
|
|
18350
18528
|
type: "string",
|
|
@@ -18558,45 +18736,6 @@ var TOOL_DEFINITIONS = [
|
|
|
18558
18736
|
},
|
|
18559
18737
|
execute: (c, a) => inviteToLobby(c, a)
|
|
18560
18738
|
},
|
|
18561
|
-
// ── Challenges ───────────────────────────────────────────────────────
|
|
18562
|
-
{
|
|
18563
|
-
name: "dim_challenge_user",
|
|
18564
|
-
description: "Challenge a specific user to a game. This is the best way to invite someone you are chatting with \u2014 they get a notification and can accept directly. Prefer this over creating a lobby when you know who you want to play. Amount must be between $1 and $1000.",
|
|
18565
|
-
params: {
|
|
18566
|
-
gameType: { type: "string", description: "Game type", required: true },
|
|
18567
|
-
amount: {
|
|
18568
|
-
type: "number",
|
|
18569
|
-
description: "Challenge amount in USDC dollars",
|
|
18570
|
-
required: true,
|
|
18571
|
-
min: 1,
|
|
18572
|
-
max: 1e3
|
|
18573
|
-
},
|
|
18574
|
-
targetUsername: {
|
|
18575
|
-
type: "string",
|
|
18576
|
-
description: "Username of the user to challenge"
|
|
18577
|
-
},
|
|
18578
|
-
targetUserId: {
|
|
18579
|
-
type: "string",
|
|
18580
|
-
description: "User ID of the user to challenge"
|
|
18581
|
-
}
|
|
18582
|
-
},
|
|
18583
|
-
execute: (c, a) => challengeUser(
|
|
18584
|
-
c,
|
|
18585
|
-
a
|
|
18586
|
-
)
|
|
18587
|
-
},
|
|
18588
|
-
{
|
|
18589
|
-
name: "dim_accept_challenge",
|
|
18590
|
-
description: "Accept a challenge that was sent to you.",
|
|
18591
|
-
params: {
|
|
18592
|
-
challengeId: {
|
|
18593
|
-
type: "string",
|
|
18594
|
-
description: "The challenge ID to accept",
|
|
18595
|
-
required: true
|
|
18596
|
-
}
|
|
18597
|
-
},
|
|
18598
|
-
execute: (c, a) => acceptChallenge(c, a)
|
|
18599
|
-
},
|
|
18600
18739
|
// ── Referrals ────────────────────────────────────────────────────────
|
|
18601
18740
|
{
|
|
18602
18741
|
name: "dim_get_referral_summary",
|
|
@@ -18869,7 +19008,7 @@ var TOOL_DEFINITIONS = [
|
|
|
18869
19008
|
// ── Notifications & Events ───────────────────────────────────────────
|
|
18870
19009
|
{
|
|
18871
19010
|
name: "dim_get_pending_events",
|
|
18872
|
-
description: "Drain buffered real-time events (DMs,
|
|
19011
|
+
description: "Drain buffered real-time events (DMs, game turns, match notifications). Call regularly to stay aware.",
|
|
18873
19012
|
params: {},
|
|
18874
19013
|
execute: (c) => getPendingEvents(c)
|
|
18875
19014
|
},
|
|
@@ -18906,11 +19045,18 @@ async function executeWithAuthRetry(client, tool, params) {
|
|
|
18906
19045
|
if (tool.name === "dim_login") {
|
|
18907
19046
|
return tool.execute(client, params);
|
|
18908
19047
|
}
|
|
19048
|
+
if (client.externalSignerMode) {
|
|
19049
|
+
return tool.execute(client, params);
|
|
19050
|
+
}
|
|
18909
19051
|
try {
|
|
18910
19052
|
const result = await tool.execute(client, params);
|
|
18911
19053
|
if (!result.error && !result.isError) return result;
|
|
18912
19054
|
if (!isUnauthorizedResult(result)) return result;
|
|
18913
|
-
|
|
19055
|
+
try {
|
|
19056
|
+
await client.authenticate();
|
|
19057
|
+
} catch {
|
|
19058
|
+
return { error: UNAUTHORIZED_MESSAGE, isError: true };
|
|
19059
|
+
}
|
|
18914
19060
|
const retryResult = await tool.execute(client, params);
|
|
18915
19061
|
if (retryResult.isError || retryResult.error) {
|
|
18916
19062
|
if (isUnauthorizedResult(retryResult)) {
|
|
@@ -19113,6 +19259,10 @@ function registerResources(server2, client) {
|
|
|
19113
19259
|
}
|
|
19114
19260
|
|
|
19115
19261
|
// src/server.ts
|
|
19262
|
+
var HOSTED_EXCLUDED_TOOLS = /* @__PURE__ */ new Set([
|
|
19263
|
+
"dim_game_loop",
|
|
19264
|
+
"dim_get_pending_events"
|
|
19265
|
+
]);
|
|
19116
19266
|
function paramToZod(p) {
|
|
19117
19267
|
let schema;
|
|
19118
19268
|
if (p.enum) {
|
|
@@ -19133,14 +19283,14 @@ function paramToZod(p) {
|
|
|
19133
19283
|
if (!p.required) schema = schema.optional();
|
|
19134
19284
|
return schema.describe(p.description);
|
|
19135
19285
|
}
|
|
19136
|
-
function
|
|
19286
|
+
function buildMcpServer(client, mode) {
|
|
19137
19287
|
const server2 = new McpServer({
|
|
19138
19288
|
name: "dim",
|
|
19139
19289
|
version: "1.0.0",
|
|
19140
|
-
description: "DIM Gaming Platform \u2014 Play games, chat, send USDC,
|
|
19290
|
+
description: "DIM Gaming Platform \u2014 Play games, chat, send USDC, and earn referral income. DIM is noncustodial; your Solana address is returned by dim_get_profile and dim_get_balance. Start by calling dim_login. After login: set a username with dim_set_username, check balance with dim_get_balance, list games with dim_list_games, or apply a referral code with dim_apply_referral_code for a 10% fee discount."
|
|
19141
19291
|
});
|
|
19142
|
-
const client = new DimAgentClient(config);
|
|
19143
19292
|
for (const tool of TOOL_DEFINITIONS) {
|
|
19293
|
+
if (mode === "hosted" && HOSTED_EXCLUDED_TOOLS.has(tool.name)) continue;
|
|
19144
19294
|
const zodParams = {};
|
|
19145
19295
|
for (const [key, param] of Object.entries(tool.params)) {
|
|
19146
19296
|
zodParams[key] = paramToZod(param);
|
|
@@ -19170,6 +19320,7 @@ function createDimMcpServer(config) {
|
|
|
19170
19320
|
}
|
|
19171
19321
|
);
|
|
19172
19322
|
}
|
|
19323
|
+
const gameHint = mode === "hosted" ? "Game flow: dim_create_lobby \u2192 dim_deposit_for_lobby (returns unsignedTx \u2014 sign with Phantom MCP) \u2192 dim_join_queue \u2192 poll dim_get_lobby until matched \u2192 dim_get_game_state \u2192 dim_submit_action \u2192 repeat. For real-time game_loop, use the DIM CLI (npx @dimcool/cli)." : "Game flow: For paid lobbies, dim_create_lobby \u2192 dim_deposit_for_lobby \u2192 dim_join_queue. For free lobbies, dim_create_lobby \u2192 dim_join_queue. Then dim_game_loop (blocks until your turn) \u2192 dim_submit_action \u2192 dim_game_loop \u2192 repeat. Use dim_leave_lobby to exit a lobby.";
|
|
19173
19324
|
server2.tool(
|
|
19174
19325
|
"dim_list_instructions",
|
|
19175
19326
|
"List all available DIM tools with short descriptions.",
|
|
@@ -19183,8 +19334,8 @@ function createDimMcpServer(config) {
|
|
|
19183
19334
|
wallet_linkage: WALLET_LINKAGE_NOTE,
|
|
19184
19335
|
wallet_address: "Your DIM Solana address is returned by dim_get_profile, dim_get_balance, dim_get_wallet_activity, and dim_get_wallet_address. Use it to confirm which address is tied to DIM.",
|
|
19185
19336
|
wallet_activity: "For deposits, transfers, payouts, and claimable items use dim_get_wallet_activity.",
|
|
19186
|
-
hint:
|
|
19187
|
-
spectate_on_game_start: "When a game starts (dim_join_queue
|
|
19337
|
+
hint: gameHint,
|
|
19338
|
+
spectate_on_game_start: "When a game starts (dim_join_queue returns matched/gameId), tell the user they can spectate at the spectateUrl in the tool response, or at https://dim.cool/spectate/[your DIM username].",
|
|
19188
19339
|
daily_summary: "At least once per day, report to the operator your DIM progress: call dim_get_game_history (and optionally dim_get_my_stats and dim_get_referral_summary), then summarize games played and referral earnings.",
|
|
19189
19340
|
move_formats: {
|
|
19190
19341
|
"rock-paper-scissors": 'action: "play", payload: { action: "rock"|"paper"|"scissors" }',
|
|
@@ -19204,6 +19355,15 @@ function createDimMcpServer(config) {
|
|
|
19204
19355
|
})
|
|
19205
19356
|
);
|
|
19206
19357
|
registerResources(server2, client);
|
|
19358
|
+
return server2;
|
|
19359
|
+
}
|
|
19360
|
+
function createDimMcpServer(clientOrConfig, options) {
|
|
19361
|
+
const mode = options?.mode ?? "local";
|
|
19362
|
+
if (clientOrConfig instanceof DimAgentClient) {
|
|
19363
|
+
return buildMcpServer(clientOrConfig, mode);
|
|
19364
|
+
}
|
|
19365
|
+
const client = new DimAgentClient(clientOrConfig);
|
|
19366
|
+
const server2 = buildMcpServer(client, mode);
|
|
19207
19367
|
return { server: server2, client };
|
|
19208
19368
|
}
|
|
19209
19369
|
|