Skill: zhzai30/clawquest-agent-mine-openclaw (version 1.0.11)

--- slug: clawquest-agent-mine-openclaw name: ClawQuest: Agent Mine - OpenClaw Managed Mining owner: "@zhzai30 - zhzai30" version: 1.0.10 description: Managed mining over public game APIs using X-Api-Code authentication. metadata: openclaw: requires: env: - REQUEST_TIMEOUT_MS emoji: "⛏️" homepage: "" --- # ClawQuest: Agent Mine - OpenClaw Managed Mining This Skill exposes managed mining tools for OpenClaw session workflows. ## Agent rules OpenClaw Automated agents (including OpenClaw workflows) must follow these constraints: - **Tools only**: Interact with the game **only** through this Skill’s **tool** HTTP API — `POST /tool/:name` on the skill-openclaw service, using the tool names documented below (`set_api_code`, `check_mining_state`, `start_managed_mining_loop`, etc.). Do **not** call the upstream game **`/api/*`** endpoints directly from the agent, custom scripts, or curl unless this Skill explicitly documents that path as a supported tool (it does not for raw `/api/*`). - **Do not modify source**: Do **not** edit, patch, or fork the `skill-openclaw` source tree, `package.json`, or runtime code to “fix” behaviour. Use documented environment variables and this `SKILL.md` only. - **Report errors; do not self-heal in code**: If a tool fails or behaviour is unexpected, **report** the failure (HTTP status, response body, tool name, `cacheKey`, timestamps, logs). Do **not** rewrite Skill code, inject alternate HTTP clients, or bypass the tool layer as a workaround. ## API Contract All mining and stamina APIs require `X-Api-Code`. - `POST /api/startMining` - `POST /api/checkMiningState` - `POST /api/endMining` - `POST /api/setAutoMining` - `POST /api/buyStamina` - `POST /api/getStamina` (Internal round flow still uses `POST /api/setAutoMining`, `POST /api/startMining` and `POST /api/endMining` via the managed loop implementation; they are not exposed as Skill tools.) Authentication: - Header: `X-Api-Code: <apiCode>` The Skill does not perform game client login. Users must provide `apiCode` generated in-game. ## State Codes `check_mining_state` returns `apiState` and `miningState`. Numeric values map as follows. **apiState** | Value | Name | | ----- | ----------- | | 0 | ApiInactive | | 1 | ApiInUse | | 2 | ApiClosing | | 3 | ApiActive | **miningState** | Value | Name | | ----- | ------------------- | | 0 | MiningIdle | | 1 | MiningInProgress | | 2 | MiningRewardPending | ## Tools ### set_api_code Persist an `apiCode` for later calls. Inputs: - `apiCode` (required) - `cacheKey` (optional, default: `default`) ### get_api_code Read the cached `apiCode`. Inputs: - `cacheKey` (optional, default: `default`) ### clear_api_code Delete the cached `apiCode`. Inputs: - `cacheKey` (optional, default: `default`) ### check_mining_state Query API activation status and mining state. Returns `apiState` and `miningState` (see [State Codes](#state-codes)). Inputs: - `apiCode` (optional, falls back to cache) - `cacheKey` (optional, default: `default`) ### buy_stamina Buy stamina using diamonds. Inputs: - `apiCode` (optional, falls back to cache) - `cacheKey` (optional, default: `default`) ### get_stamina Get stamina and diamonds. Inputs: - `apiCode` (optional, falls back to cache) - `cacheKey` (optional, default: `default`) ### start_managed_mining_loop Start managed loop execution. Flow: 1. `start_mining` — abort on error 2. wait for `estimatedEndAt` 3. loop `end_mining` — retry on error, round complete on success 4. record reward 5. wait round interval and continue Inputs: - `apiCode` (optional, falls back to cache) - `cacheKey` (optional, default: `default`) - `lang` (optional) - `pollingIntervalMilliseconds` (optional) - `roundIntervalMilliseconds` (optional) - `maxConsecutiveErrorCount` (optional) - `autoBuyStamina` (optional) - `autoBuyStaminaMaxFailures` (optional) - `forceRestart` (optional) ### start_mining_session Same as `start_managed_mining_loop` with OpenClaw session binding and event stream. ### get_mining_session_events Read incremental session events. Inputs: - `sinceEventId` (optional, default: `0`) ### get_mining_quick_status Read lightweight managed loop status. ### get_managed_mining_status Read full managed loop status. ### stop_managed_mining_loop Request safe stop for running managed loop. ## Deprecated Tools - `start_auto_mining` (deprecated) - `stop_auto_mining` (deprecated) ## Suggested Call Order 1. `set_api_code` (one-time setup) 2. `start_mining_session` 3. (optional) call `get_mining_quick_status` or `get_mining_session_events` on demand — do **not** set up automatic periodic polling by default 4. call `stop_managed_mining_loop` when needed ## Error Codes All API responses include a `code` field. `0` means success; non-zero values indicate an error. ### Common Errors | Code | Name | Description | | ---- | ------------------- | ----------------------------------------------------------------- | | 400 | InvalidParams | Invalid or missing parameters (e.g. empty `X-Api-Code` header) | | 401 | AuthFailed | Authentication failed (invalid `apiCode`) | | 500 | InternalServerError | Server internal error | | 1010 | NotEnoughResources | Insufficient resources (diamonds not enough for stamina purchase) | ### Mining Errors | Code | Name | Description | | ---- | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | 2003 | InsufficientResources | Insufficient stamina to start mining | | 2008 | DiamondNotEnought | Insufficient diamonds | | 2009 | MiningStateConflict | Mining state conflict (e.g. calling `startMining` while already in progress, or `endMining` when not mining via API) | | 2014 | MiningApiNotActive | API mining feature not activated for this player | | 2018 | MiningNotFinished | Mining not finished yet (current time has not reached `estimatedEndAt`) | ## Environment Variables | Variable | Description | | -------------------------------------------- | -------------------------------------------------------------------------- | | `GAME_API_BASE_URL` | Optional API base URL override (default: `https://api.km.cocweb3.com`) | | `REQUEST_TIMEOUT_MS` | Request timeout in milliseconds (default: `8000`) | | `MANAGED_MINING_POLL_INTERVAL_MS` | Default polling interval in milliseconds (default: `1000`) | | [REDACTED_SECRET] | Default round interval in milliseconds (default: `2000`) | | [REDACTED_SECRET] | Consecutive error stop threshold (default: `10`) | | `MANAGED_MINING_AUTO_BUY_STAMINA` | Enable auto-buy on stamina insufficient: `1` or `true` | | [REDACTED_SECRET] | Consecutive auto-buy failures stop threshold (default: `3`) | | `MINING_SESSION_MAX_EVENTS` | Ring buffer size for events (default: `200`) | | `API_CODE_STORE_PATH` | Path for cached apiCode store (default: `./data/api-code-store.json`) | | `ORE_TYPE_NAME_MAP_PATH` | Path for ore type display name map (default: `./config/ore-type-map.json`) |

path: config/ore-type-map.json
content: {
  "oreTypeNameMap": {
    "1": {
      "resourceId": 10003,
      "zh_CN": "金矿石",
      "zh_TW": "金礦石",
      "en_US": "Gold Ore",
      "ja_JP": "金鉱石",
      "ko_KR": "금 광석",
      "ru_RU": "Золотая руда"
    },
    "2": {
      "resourceId": 10004,
      "zh_CN": "铜矿石",
      "zh_TW": "銅礦石",
      "en_US": "Copper Ore",
      "ja_JP": "銅鉱石",
      "ko_KR": "구리 광석",
      "ru_RU": "Медная руда"
    },
    "3": {
      "resourceId": 10005,
      "zh_CN": "铁矿石",
      "zh_TW": "鐵礦石",
      "en_US": "Iron Ore",
      "ja_JP": "鉄鉱石",
      "ko_KR": "철 광석",
      "ru_RU": "Железная руда"
    },
    "4": {
      "resourceId": 10006,
      "zh_CN": "钴矿石",
      "zh_TW": "鈷礦石",
      "en_US": "Cobalt Ore",
      "ja_JP": "コバルト鉱石",
      "ko_KR": "코발트 광석",
      "ru_RU": "Кобальтовая руда"
    },
    "5": {
      "resourceId": 10007,
      "zh_CN": "铀矿石",
      "zh_TW": "鈾礦石",
      "en_US": "Uranium Ore",
      "ja_JP": "ウラン鉱石",
      "ko_KR": "우라늄 광석",
      "ru_RU": "Урановая руда"
    },
    "6": {
      "resourceId": 10008,
      "zh_CN": "伊斯密矿石",
      "zh_TW": "伊斯密礦石",
      "en_US": "Ismium Ore",
      "ja_JP": "イズミウム鉱石",
      "ko_KR": "이즈미움 광석",
      "ru_RU": "Измиевая руда"
    },
    "7": {
      "resourceId": 10009,
      "zh_CN": "铱矿石",
      "zh_TW": "銥礦石",
      "en_US": "Iridium Ore",
      "ja_JP": "イリジウム鉱石",
      "ko_KR": "이리듐 광석",
      "ru_RU": "Иридиевая руда"
    },
    "8": {
      "resourceId": 10010,
      "zh_CN": "电气石矿石",
      "zh_TW": "電氣石礦石",
      "en_US": "Tourmaline Ore",
      "ja_JP": "電気石鉱石",
      "ko_KR": "전기석 광석",
      "ru_RU": "Турмалиновая руда"
    }
  }
}


path: index.js
content: import express from "express";
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
import { GameApiHttpError, fetchGameApiWithApiCodePost, runManagedMiningLoop, setApiAutoMining, } from "./tools.js";
const app = express();
app.use(express.json());
const requestSchema = z.object({
    apiCode: z.string().trim().min(1).optional(),
    cacheKey: z.string().trim().min(1).optional(),
    lang: z
        .enum(["zh_CN", "zh_TW", "en_US", "ja_JP", "ko_KR", "ru_RU"])
        .optional(),
    pollingIntervalMilliseconds: z.number().int().positive().optional(),
    roundIntervalMilliseconds: z.number().int().positive().optional(),
    maxConsecutiveErrorCount: z.number().int().positive().optional(),
    sinceEventId: z.number().int().nonnegative().optional(),
    openclawSessionKey: z.string().trim().min(1).optional(),
    sessionKey: z.string().trim().min(1).optional(),
    forceRestart: z.boolean().optional(),
    autoBuyStamina: z.boolean().optional(),
    autoBuyStaminaMaxFailures: z.number().int().positive().optional(),
});
const apiCodeCache = new Map();
const defaultCacheKey = "default";
const apiCodeStorePath = process.env.API_CODE_STORE_PATH ??
    path.join(process.cwd(), "data", "api-code-store.json");
const defaultManagedMaxConsecutiveErrorCount = Number(process.env.MANAGED_MINING_MAX_CONSECUTIVE_ERROR_COUNT ?? "10");
const maxMiningSessionEventCount = Number(process.env.MINING_SESSION_MAX_EVENTS ?? "200");
const defaultAutoBuyStaminaEnabledFromEnv = process.env.MANAGED_MINING_AUTO_BUY_STAMINA === "1" ||
    process.env.MANAGED_MINING_AUTO_BUY_STAMINA === "true";
let managedMiningTask;
let managedMiningStatus = buildIdleManagedMiningStatus();
let miningSessionEventIdCounter = 0;
let managedMiningTaskGeneration = 0;
app.post("/tool/:name", async (req, res) => {
    const parsed = requestSchema.safeParse(req.body ?? {});
    if (!parsed.success) {
        return res.status(400).json({ ok: false, error: "invalid_payload" });
    }
    const toolName = req.params.name;
    const payload = parsed.data;
    const cacheKey = payload.cacheKey ?? defaultCacheKey;
    try {
        if (toolName === "set_api_code") {
            if (!payload.apiCode) {
                return res.status(400).json({ ok: false, error: "api_code_required" });
            }
            apiCodeCache.set(cacheKey, payload.apiCode);
            await persistApiCodeStore();
            return res.json({ ok: true, data: { cacheKey, hasApiCode: true } });
        }
        if (toolName === "get_api_code") {
            const cachedApiCode = apiCodeCache.get(cacheKey);
            if (!cachedApiCode) {
                return res.status(404).json({ ok: false, error: "api_code_not_found" });
            }
            return res.json({ ok: true, data: { cacheKey, apiCode: cachedApiCode } });
        }
        if (toolName === "clear_api_code") {
            const deleted = apiCodeCache.delete(cacheKey);
            if (deleted) {
                await persistApiCodeStore();
            }
            return res.json({ ok: true, data: { cacheKey, deleted } });
        }
        if (toolName === "check_mining_state") {
            if (payload.apiCode) {
                await upsertApiCode(cacheKey, payload.apiCode);
            }
            const apiCode = resolveApiCodeOrBadRequest(res, payload, cacheKey);
            if (apiCode === undefined) {
                return;
            }
            const upstream = await fetchGameApiWithApiCodePost("/api/checkMiningState", apiCode, {});
            return res.status(upstream.httpStatus).json(upstream.body);
        }
        if (toolName === "buy_stamina") {
            if (payload.apiCode) {
                await upsertApiCode(cacheKey, payload.apiCode);
            }
            const apiCode = resolveApiCodeOrBadRequest(res, payload, cacheKey);
            if (apiCode === undefined) {
                return;
            }
            const upstream = await fetchGameApiWithApiCodePost("/api/buyStamina", apiCode, {});
            return res.status(upstream.httpStatus).json(upstream.body);
        }
        if (toolName === "get_stamina") {
            if (payload.apiCode) {
                await upsertApiCode(cacheKey, payload.apiCode);
            }
            const apiCode = resolveApiCodeOrBadRequest(res, payload, cacheKey);
            if (apiCode === undefined) {
                return;
            }
            const upstream = await fetchGameApiWithApiCodePost("/api/getStamina", apiCode, {});
            return res.status(upstream.httpStatus).json(upstream.body);
        }
        if (toolName === "start_auto_mining") {
            return res.status(410).json({
                ok: false,
                error: "tool_deprecated_use_start_managed_mining_loop",
                message: "start_auto_mining is deprecated. Use start_managed_mining_loop.",
            });
        }
        if (toolName === "start_managed_mining_loop" ||
            toolName === "start_mining_session") {
            if (payload.apiCode) {
                await upsertApiCode(cacheKey, payload.apiCode);
            }
            const apiCode = resolveApiCode(payload, cacheKey);
            if (managedMiningTask) {
                if (payload.forceRestart) {
                    managedMiningTask.stopRequested = true;
                    managedMiningTask = undefined;
                    managedMiningTaskGeneration += 1;
                    managedMiningStatus = buildIdleManagedMiningStatus();
                }
                else {
                    return res.status(409).json({
                        ok: false,
                        error: "managed_mining_loop_already_running",
                        message: "Managed mining loop is already running. Call stop_managed_mining_loop first or use forceRestart: true.",
                        data: managedMiningStatus,
                    });
                }
            }
            const maxConsecutiveErrorCount = normalizePositiveInteger(payload.maxConsecutiveErrorCount, defaultManagedMaxConsecutiveErrorCount);
            const openclawSessionKey = extractOpenClawSessionKey(req, payload);
            miningSessionEventIdCounter = 0;
            const loopGeneration = managedMiningTaskGeneration;
            managedMiningTask = {
                stopRequested: false,
                apiCode,
                cacheKey,
            };
            managedMiningStatus = {
                running: true,
                phase: "starting_round",
                message: "Managed mining loop started. Starting current round.",
                openclawSessionKey,
                startedAt: Date.now(),
                updatedAt: Date.now(),
                cacheKey,
                roundsCompleted: 0,
                consecutiveErrorCount: 0,
                maxConsecutiveErrorCount,
                lastRewardDetails: [],
                events: [],
                lastEventId: 0,
            };
            appendMiningSessionEvent("session_started", {
                openclawSessionKey: openclawSessionKey ?? null,
                cacheKey,
            });
            try {
                await setApiAutoMining(apiCode, true);
            }
            catch (error) {
                console.warn("[skill-openclaw] setApiAutoMining(true) failed:", error);
            }
            void runManagedMiningLoop(apiCode, () => managedMiningTaskGeneration === loopGeneration &&
                managedMiningTask !== undefined &&
                !managedMiningTask.stopRequested, {
                onPhaseChanged: (phase, details) => {
                    if (managedMiningTaskGeneration !== loopGeneration)
                        return;
                    managedMiningStatus.phase = phase;
                    managedMiningStatus.updatedAt = Date.now();
                    managedMiningStatus.message = mapManagedMiningPhaseToMessage(phase);
                    if (phase !== "waiting_estimated_end_at") {
                        managedMiningStatus.estimatedEndAt = undefined;
                    }
                    if (phase === "waiting_estimated_end_at" &&
                        details?.estimatedEndAt) {
                        managedMiningStatus.estimatedEndAt = Number(details.estimatedEndAt);
                    }
                    if (phase === "starting_round") {
                        managedMiningStatus.consecutiveErrorCount = 0;
                        managedMiningStatus.lastError = undefined;
                    }
                },
                onError: (errorMessage, consecutiveErrorCount) => {
                    if (managedMiningTaskGeneration !== loopGeneration)
                        return;
                    managedMiningStatus.updatedAt = Date.now();
                    managedMiningStatus.lastError = errorMessage;
                    managedMiningStatus.consecutiveErrorCount = consecutiveErrorCount;
                    managedMiningStatus.message =
                        "Loop execution error recorded. Continuing according to retry policy.";
                    appendMiningSessionEvent("error", {
                        message: errorMessage,
                        consecutiveErrorCount,
                    });
                },
                onRoundCompleted: (roundResult) => {
                    if (managedMiningTaskGeneration !== loopGeneration)
                        return;
                    managedMiningStatus.updatedAt = Date.now();
                    managedMiningStatus.roundsCompleted += 1;
                    managedMiningStatus.lastRewardDetails = roundResult.rewardDetails;
                    managedMiningStatus.lastCheckState = roundResult.checkState;
                    managedMiningStatus.lastPlayerStatus = extractPlayerStatus(roundResult.checkState);
                    appendMiningSessionEvent("round_completed", {
                        roundsCompleted: managedMiningStatus.roundsCompleted,
                        rewardDetails: roundResult.rewardDetails,
                        playerStatus: managedMiningStatus.lastPlayerStatus,
                    });
                },
            }, {
                lang: payload.lang,
                pollingIntervalMilliseconds: payload.pollingIntervalMilliseconds,
                roundIntervalMilliseconds: payload.roundIntervalMilliseconds,
                maxConsecutiveErrorCount,
                autoBuyStaminaEnabled: payload.autoBuyStamina !== undefined
                    ? payload.autoBuyStamina
                    : defaultAutoBuyStaminaEnabledFromEnv,
                autoBuyStaminaMaxFailures: payload.autoBuyStaminaMaxFailures,
            })
                .then((summary) => {
                if (managedMiningTaskGeneration !== loopGeneration)
                    return;
                managedMiningStatus.running = false;
                managedMiningStatus.phase = "idle";
                managedMiningStatus.updatedAt = Date.now();
                managedMiningStatus.estimatedEndAt = undefined;
                managedMiningStatus.stopReason = summary.stopReason;
                managedMiningStatus.criticalErrorCode = summary.criticalErrorCode;
                if (summary.stopReason === "critical_error") {
                    managedMiningStatus.message = `Managed mining loop stopped by critical server error (code=${summary.criticalErrorCode}).`;
                }
                else if (summary.stopReason === "error_limit_reached") {
                    managedMiningStatus.message =
                        "Managed mining loop stopped after reaching the consecutive error limit.";
                }
                else if (summary.stopReason === "auto_buy_stamina_exhausted") {
                    managedMiningStatus.message = `Managed mining loop stopped because auto-buy stamina failed ${summary.autoBuyStaminaFailureCount ?? 0} consecutive times. Refill resources and restart.`;
                }
                else {
                    managedMiningStatus.message =
                        "Managed mining loop stopped by request.";
                }
                managedMiningStatus.roundsCompleted = summary.roundsCompleted;
                managedMiningStatus.consecutiveErrorCount =
                    summary.consecutiveErrorCount;
                if (summary.lastError) {
                    managedMiningStatus.lastError = summary.lastError;
                }
                if (summary.lastRewardDetails) {
                    managedMiningStatus.lastRewardDetails = summary.lastRewardDetails;
                }
                if (summary.lastCheckState) {
                    managedMiningStatus.lastCheckState = summary.lastCheckState;
                    managedMiningStatus.lastPlayerStatus = extractPlayerStatus(summary.lastCheckState);
                }
                appendMiningSessionEvent("stopped", {
                    stopReason: summary.stopReason,
                    criticalErrorCode: summary.criticalErrorCode,
                    autoBuyStaminaFailureCount: summary.autoBuyStaminaFailureCount,
                    roundsCompleted: summary.roundsCompleted,
                    consecutiveErrorCount: summary.consecutiveErrorCount,
                    lastError: summary.lastError,
                });
            })
                .catch((error) => {
                if (managedMiningTaskGeneration !== loopGeneration)
                    return;
                const message = error instanceof Error ? error.message : String(error);
                managedMiningStatus.running = false;
                managedMiningStatus.phase = "idle";
                managedMiningStatus.updatedAt = Date.now();
                managedMiningStatus.lastError = message;
                managedMiningStatus.message = `Managed mining loop crashed: ${message}`;
                appendMiningSessionEvent("stopped", {
                    stopReason: "critical_error",
                    lastError: message,
                });
            })
                .finally(async () => {
                try {
                    await setApiAutoMining(apiCode, false);
                }
                catch (error) {
                    console.warn("[skill-openclaw] setApiAutoMining(false) failed:", error);
                }
                if (managedMiningTaskGeneration === loopGeneration) {
                    managedMiningTask = undefined;
                }
            });
            return res.json({
                ok: true,
                data: {
                    created: true,
                    openclawSessionKey,
                    status: managedMiningStatus,
                },
            });
        }
        if (toolName === "stop_managed_mining_loop") {
            if (!managedMiningTask) {
                return res.status(404).json({
                    ok: false,
                    error: "managed_mining_loop_not_running",
                    data: managedMiningStatus,
                });
            }
            managedMiningTask.stopRequested = true;
            managedMiningStatus.phase = "stopping";
            managedMiningStatus.updatedAt = Date.now();
            managedMiningStatus.message =
                "Stop request received. Exiting safely at the next checkpoint.";
            return res.json({
                ok: true,
                data: { stopRequested: true, status: managedMiningStatus },
            });
        }
        if (toolName === "get_managed_mining_status") {
            const statusMessage = generateStatusMessage(managedMiningStatus);
            return res.json({
                ok: true,
                data: {
                    ...managedMiningStatus,
                    friendlyMessage: statusMessage,
                },
            });
        }
        if (toolName === "get_mining_quick_status") {
            const quickStatus = {
                running: managedMiningStatus.running,
                phase: managedMiningStatus.phase,
                message: managedMiningStatus.message,
                roundsCompleted: managedMiningStatus.roundsCompleted,
                consecutiveErrorCount: managedMiningStatus.consecutiveErrorCount,
                lastEventId: managedMiningStatus.lastEventId,
                updatedAt: managedMiningStatus.updatedAt,
            };
            return res.json({ ok: true, data: quickStatus });
        }
        if (toolName === "get_mining_session_events") {
            const sinceEventId = payload.sinceEventId ?? 0;
            const newEvents = managedMiningStatus.events.filter((event) => event.id > sinceEventId);
            return res.json({
                ok: true,
                data: {
                    openclawSessionKey: managedMiningStatus.openclawSessionKey,
                    sinceEventId,
                    lastEventId: managedMiningStatus.lastEventId,
                    events: newEvents,
                },
            });
        }
        if (toolName === "stop_auto_mining") {
            return res.status(410).json({
                ok: false,
                error: "tool_deprecated_use_stop_managed_mining_loop",
                message: "stop_auto_mining is deprecated. Use stop_managed_mining_loop.",
            });
        }
    }
    catch (error) {
        if (error instanceof GameApiHttpError) {
            const responseBody = error.responseBody;
            if (responseBody !== undefined &&
                typeof responseBody === "object" &&
                responseBody !== null) {
                return res.status(error.statusCode).json(responseBody);
            }
            return res.status(error.statusCode).json({ message: error.message });
        }
        if (error instanceof Error &&
            error.message.startsWith("game_api_timeout")) {
            return res.status(504).json({ error: error.message });
        }
        const errorMessage = error instanceof Error ? error.message : "tool_execution_failed";
        return res.status(502).json({ ok: false, error: errorMessage });
    }
    return res.status(404).json({ ok: false, error: "tool_not_found" });
});
app.get("/health", (_req, res) => {
    res.json({ ok: true, service: "skill-openclaw" });
});
const port = Number(process.env.PORT ?? "4021");
void bootstrap();
function resolveApiCode(payload, cacheKey) {
    if (payload.apiCode) {
        return payload.apiCode;
    }
    const cachedApiCode = apiCodeCache.get(cacheKey);
    if (!cachedApiCode) {
        throw new Error("api_code_required_or_cache_miss");
    }
    return cachedApiCode;
}
function resolveApiCodeOrBadRequest(res, payload, cacheKey) {
    try {
        return resolveApiCode(payload, cacheKey);
    }
    catch {
        res.status(400).json({ error: "api_code_required_or_cache_miss" });
        return undefined;
    }
}
async function bootstrap() {
    await loadApiCodeStore();
    app.listen(port, () => {
        console.log(`skill-openclaw listening on :${port}`);
    });
}
async function loadApiCodeStore() {
    try {
        const fileContent = await readFile(apiCodeStorePath, "utf-8");
        const parsedStore = JSON.parse(fileContent);
        const apiCodeEntries = Object.entries(parsedStore.apiCodes ?? {});
        for (const [cacheKey, apiCode] of apiCodeEntries) {
            const normalizedCacheKey = cacheKey.trim();
            const normalizedApiCode = String(apiCode).trim();
            if (!normalizedCacheKey || !normalizedApiCode) {
                continue;
            }
            apiCodeCache.set(normalizedCacheKey, normalizedApiCode);
        }
    }
    catch (error) {
        if (error.code === "ENOENT") {
            return;
        }
        throw error;
    }
}
async function persistApiCodeStore() {
    const apiCodeRecord = Object.fromEntries(apiCodeCache.entries());
    const serializedStore = JSON.stringify({ apiCodes: apiCodeRecord }, null, 2);
    await mkdir(path.dirname(apiCodeStorePath), { recursive: true });
    const tmpPath = `${apiCodeStorePath}.tmp.${process.pid}`;
    await writeFile(tmpPath, serializedStore, "utf-8");
    await rename(tmpPath, apiCodeStorePath);
}
async function upsertApiCode(cacheKey, apiCode) {
    apiCodeCache.set(cacheKey, apiCode.trim());
    await persistApiCodeStore();
}
function buildIdleManagedMiningStatus() {
    return {
        running: false,
        phase: "idle",
        message: "Managed mining loop is not running.",
        updatedAt: Date.now(),
        roundsCompleted: 0,
        consecutiveErrorCount: 0,
        maxConsecutiveErrorCount: defaultManagedMaxConsecutiveErrorCount,
        lastRewardDetails: [],
        events: [],
        lastEventId: 0,
    };
}
function extractOpenClawSessionKey(req, payload) {
    const headerValue = req.get("x-openclaw-session-key");
    const fromHeader = normalizeOpenClawSessionKey(headerValue);
    if (fromHeader) {
        return fromHeader;
    }
    const fromBodyExplicit = normalizeOpenClawSessionKey(payload.openclawSessionKey);
    if (fromBodyExplicit) {
        return fromBodyExplicit;
    }
    return normalizeOpenClawSessionKey(payload.sessionKey);
}
function normalizeOpenClawSessionKey(value) {
    if (value === undefined) {
        return undefined;
    }
    const trimmed = value.trim();
    return trimmed.length > 0 ? trimmed : undefined;
}
function appendMiningSessionEvent(eventType, eventPayload) {
    miningSessionEventIdCounter += 1;
    const miningSessionEvent = {
        id: miningSessionEventIdCounter,
        ts: Date.now(),
        type: eventType,
        payload: eventPayload,
    };
    managedMiningStatus.events.push(miningSessionEvent);
    managedMiningStatus.lastEventId = miningSessionEventIdCounter;
    const maxEventCount = Math.max(1, Math.floor(maxMiningSessionEventCount));
    while (managedMiningStatus.events.length > maxEventCount) {
        managedMiningStatus.events.shift();
    }
}
function generateStatusMessage(status) {
    if (!status.running) {
        return "Managed mining loop is not running";
    }
    if (status.roundsCompleted === 0) {
        return `Status: ${status.message}`;
    }
    const playerStatus = status.lastPlayerStatus;
    const goldCount = playerStatus?.Gold || 0;
    const rewardSummary = formatRewardSummary(status.lastRewardDetails);
    return `Round ${status.roundsCompleted} | ${rewardSummary} | Total Gold Bars ${goldCount} | Status: ${getRunningStatusText(status.phase)}`;
}
function getRunningStatusText(phase) {
    switch (phase) {
        case "starting_round":
            return "starting";
        case "waiting_estimated_end_at":
            return "waiting";
        case "polling_reward":
            return "claiming_reward";
        case "reward_collected":
        case "sleeping_between_rounds":
            return "mining";
        case "stopping":
            return "stopping";
        default:
            return "mining";
    }
}
function formatRewardSummary(rewardDetails) {
    if (!Array.isArray(rewardDetails) || rewardDetails.length === 0) {
        return "no_reward";
    }
    const oreCountMap = new Map();
    for (const reward of rewardDetails) {
        const name = String(reward.oreTypeName || reward.name || "unknown");
        const count = Number(reward.count || reward.amount || 0);
        if (count > 0) {
            oreCountMap.set(name, (oreCountMap.get(name) ?? 0) + count);
        }
    }
    if (oreCountMap.size === 0) {
        return "no_reward";
    }
    const parts = [];
    for (const [name, count] of oreCountMap) {
        parts.push(`${name}×${count}`);
    }
    return parts.join(", ");
}
function mapManagedMiningPhaseToMessage(phase) {
    const messageByPhase = {
        idle: "Managed mining loop is not running.",
        starting_round: "Starting current mining round.",
        waiting_estimated_end_at: "Estimated end time received. Waiting before polling reward.",
        polling_reward: "Polling reward status.",
        reward_collected: "Reward collected for current round.",
        sleeping_between_rounds: "Current round completed. Waiting 2 seconds before next round.",
        stopping: "Managed mining loop is stopping.",
    };
    return messageByPhase[phase];
}
function extractPlayerStatus(state) {
    if (!state || typeof state !== "object") {
        return undefined;
    }
    const stateObject = state;
    return stateObject.data?.commonInfo ?? stateObject.data?.playerStatus;
}
function normalizePositiveInteger(value, fallbackValue) {
    const normalizedValue = Math.floor(Number(value));
    if (!Number.isFinite(normalizedValue) || normalizedValue <= 0) {
        return fallbackValue;
    }
    return normalizedValue;
}


path: package-lock.json
content: {
  "name": "clawquest-agent-mine-openclaw",
  "version": "1.0.4",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "clawquest-agent-mine-openclaw",
      "version": "1.0.4",
      "dependencies": {
        "express": "^4.21.2",
        "zod": "^3.23.8"
      },
      "devDependencies": {
        "@types/express": "^4.17.21",
        "@types/node": "^25.5.2",
        "tsx": "^4.19.2",
        "typescript": "^5.6.3"
      },
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/@esbuild/aix-ppc64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "aix"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ia32": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-loong64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-mips64el": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "mips64el"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ppc64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-riscv64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-s390x": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "s390x"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openharmony-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openharmony"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/sunos-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "sunos"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-arm64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-ia32": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-x64": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@types/body-parser": {
      "version": "1.19.6",
      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/connect": "*",
        "@types/node": "*"
      }
    },
    "node_modules/@types/connect": {
      "version": "3.4.38",
      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/@types/express": {
      "version": "4.17.25",
      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/body-parser": "*",
        "@types/express-serve-static-core": "^4.17.33",
        "@types/qs": "*",
        "@types/serve-static": "^1"
      }
    },
    "node_modules/@types/express-serve-static-core": {
      "version": "4.19.8",
      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*",
        "@types/qs": "*",
        "@types/range-parser": "*",
        "@types/send": "*"
      }
    },
    "node_modules/@types/http-errors": {
      "version": "2.0.5",
      "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/mime": {
      "version": "1.3.5",
      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/node": {
      "version": "25.6.0",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "undici-types": "~7.19.0"
      }
    },
    "node_modules/@types/qs": {
      "version": "6.15.0",
      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/range-parser": {
      "version": "1.2.7",
      "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/send": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/@types/serve-static": {
      "version": "1.15.10",
      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/http-errors": "*",
        "@types/node": "*",
        "@types/send": "<1"
      }
    },
    "node_modules/@types/serve-static/node_modules/@types/send": {
      "version": "0.17.6",
      "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/mime": "^1",
        "@types/node": "*"
      }
    },
    "node_modules/accepts": {
      "version": "1.3.8",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-types": "~2.1.34",
        "negotiator": "0.6.3"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/array-flatten": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/body-parser": {
      "version": "1.20.4",
      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "content-type": "~1.0.5",
        "debug": "2.6.9",
        "depd": "2.0.0",
        "destroy": "~1.2.0",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.4.24",
        "on-finished": "~2.4.1",
        "qs": "~6.14.0",
        "raw-body": "~2.5.3",
        "type-is": "~1.6.18",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8",
        "npm": "1.2.8000 || >= 1.4.16"
      }
    },
    "node_modules/bytes": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/call-bound": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "get-intrinsic": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/content-disposition": {
      "version": "0.5.4",
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safe-buffer": "5.2.1"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/content-type": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie-signature": {
      "version": "1.0.7",
      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/debug": {
      "version": "2.6.9",
      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ms": "2.0.0"
      }
    },
    "node_modules/depd": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/destroy": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8",
        "npm": "1.2.8000 || >= 1.4.16"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/ee-first": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/encodeurl": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/esbuild": {
      "version": "0.27.7",
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "bin": {
        "esbuild": "bin/esbuild"
      },
      "engines": {
        "node": ">=18"
      },
      "optionalDependencies": {
        "@esbuild/aix-ppc64": "0.27.7",
        "@esbuild/android-arm": "0.27.7",
        "@esbuild/android-arm64": "0.27.7",
        "@esbuild/android-x64": "0.27.7",
        "@esbuild/darwin-arm64": "0.27.7",
        "@esbuild/darwin-x64": "0.27.7",
        "@esbuild/freebsd-arm64": "0.27.7",
        "@esbuild/freebsd-x64": "0.27.7",
        "@esbuild/linux-arm": "0.27.7",
        "@esbuild/linux-arm64": "0.27.7",
        "@esbuild/linux-ia32": "0.27.7",
        "@esbuild/linux-loong64": "0.27.7",
        "@esbuild/linux-mips64el": "0.27.7",
        "@esbuild/linux-ppc64": "0.27.7",
        "@esbuild/linux-riscv64": "0.27.7",
        "@esbuild/linux-s390x": "0.27.7",
        "@esbuild/linux-x64": "0.27.7",
        "@esbuild/netbsd-arm64": "0.27.7",
        "@esbuild/netbsd-x64": "0.27.7",
        "@esbuild/openbsd-arm64": "0.27.7",
        "@esbuild/openbsd-x64": "0.27.7",
        "@esbuild/openharmony-arm64": "0.27.7",
        "@esbuild/sunos-x64": "0.27.7",
        "@esbuild/win32-arm64": "0.27.7",
        "@esbuild/win32-ia32": "0.27.7",
        "@esbuild/win32-x64": "0.27.7"
      }
    },
    "node_modules/escape-html": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/etag": {
      "version": "1.8.1",
      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/express": {
      "version": "4.22.1",
      "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "accepts": "~1.3.8",
        "array-flatten": "1.1.1",
        "body-parser": "~1.20.3",
        "content-disposition": "~0.5.4",
        "content-type": "~1.0.4",
        "cookie": "~0.7.1",
        "cookie-signature": "~1.0.6",
        "debug": "2.6.9",
        "depd": "2.0.0",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "etag": "~1.8.1",
        "finalhandler": "~1.3.1",
        "fresh": "~0.5.2",
        "http-errors": "~2.0.0",
        "merge-descriptors": "1.0.3",
        "methods": "~1.1.2",
        "on-finished": "~2.4.1",
        "parseurl": "~1.3.3",
        "path-to-regexp": "~0.1.12",
        "proxy-addr": "~2.0.7",
        "qs": "~6.14.0",
        "range-parser": "~1.2.1",
        "safe-buffer": "5.2.1",
        "send": "~0.19.0",
        "serve-static": "~1.16.2",
        "setprototypeof": "1.2.0",
        "statuses": "~2.0.1",
        "type-is": "~1.6.18",
        "utils-merge": "1.0.1",
        "vary": "~1.1.2"
      },
      "engines": {
        "node": ">= 0.10.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/finalhandler": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "2.6.9",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "on-finished": "~2.4.1",
        "parseurl": "~1.3.3",
        "statuses": "~2.0.2",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/forwarded": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/fresh": {
      "version": "0.5.2",
      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/get-tsconfig": {
      "version": "4.14.0",
      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "resolve-pkg-maps": "^1.0.0"
      },
      "funding": {
        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/http-errors": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "depd": "~2.0.0",
        "inherits": "~2.0.4",
        "setprototypeof": "~1.2.0",
        "statuses": "~2.0.2",
        "toidentifier": "~1.0.1"
      },
      "engines": {
        "node": ">= 0.8"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/iconv-lite": {
      "version": "0.4.24",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safer-buffer": ">= 2.1.2 < 3"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/ipaddr.js": {
      "version": "1.9.1",
      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/media-typer": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/merge-descriptors": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/methods": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "bin": {
        "mime": "cli.js"
      },
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/mime-db": {
      "version": "1.52.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "2.1.35",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-db": "1.52.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/ms": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/negotiator": {
      "version": "0.6.3",
      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/object-inspect": {
      "version": "1.13.4",
      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/on-finished": {
      "version": "2.4.1",
      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ee-first": "1.1.1"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/parseurl": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/path-to-regexp": {
      "version": "0.1.13",
      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/proxy-addr": {
      "version": "2.0.7",
      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "forwarded": "0.2.0",
        "ipaddr.js": "1.9.1"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/qs": {
      "version": "6.14.2",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "side-channel": "^1.1.0"
      },
      "engines": {
        "node": ">=0.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/range-parser": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/raw-body": {
      "version": "2.5.3",
      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.4.24",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/resolve-pkg-maps": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "funding": {
        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
      }
    },
    "node_modules/safe-buffer": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/send": {
      "version": "0.19.2",
      "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "2.6.9",
        "depd": "2.0.0",
        "destroy": "1.2.0",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "etag": "~1.8.1",
        "fresh": "~0.5.2",
        "http-errors": "~2.0.1",
        "mime": "1.6.0",
        "ms": "2.1.3",
        "on-finished": "~2.4.1",
        "range-parser": "~1.2.1",
        "statuses": "~2.0.2"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/send/node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/serve-static": {
      "version": "1.16.3",
      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "parseurl": "~1.3.3",
        "send": "~0.19.1"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/setprototypeof": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/side-channel": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3",
        "side-channel-list": "^1.0.0",
        "side-channel-map": "^1.0.1",
        "side-channel-weakmap": "^1.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-list": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.4"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-map": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-weakmap": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3",
        "side-channel-map": "^1.0.1"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/statuses": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/toidentifier": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.6"
      }
    },
    "node_modules/tsx": {
      "version": "4.21.0",
      "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "esbuild": "~0.27.0",
        "get-tsconfig": "^4.7.5"
      },
      "bin": {
        "tsx": "dist/cli.mjs"
      },
      "engines": {
        "node": ">=18.0.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.3"
      }
    },
    "node_modules/type-is": {
      "version": "1.6.18",
      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "media-typer": "0.3.0",
        "mime-types": "~2.1.24"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/undici-types": {
      "version": "7.19.2",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/unpipe": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/utils-merge": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4.0"
      }
    },
    "node_modules/vary": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/zod": {
      "version": "3.25.76",
      "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/colinhacks"
      }
    }
  }
}


path: package.json
content: {
  "name": "clawquest-agent-mine-openclaw",
  "version": "1.0.4",
  "private": true,
  "type": "module",
  "engines": {
    "node": ">=20"
  },
  "dependencies": {
    "express": "^4.21.2",
    "zod": "^3.23.8"
  },
  "scripts": {
    "start": "node index.js"
  }
}


path: tools.js
content: import { readFile } from "node:fs/promises";
import path from "node:path";
const gameApiBaseUrl = process.env.GAME_API_BASE_URL ?? "https://api.km.cocweb3.com";
const requestTimeoutMilliseconds = Number(process.env.REQUEST_TIMEOUT_MS ?? "8000");
const oreTypeNameMapPath = process.env.ORE_TYPE_NAME_MAP_PATH ??
    path.join(process.cwd(), "config", "ore-type-map.json");
const defaultManagedPollingIntervalMilliseconds = Number(process.env.MANAGED_MINING_POLL_INTERVAL_MS ?? "1000");
const defaultManagedRoundIntervalMilliseconds = Number(process.env.MANAGED_MINING_ROUND_INTERVAL_MS ?? "2000");
const defaultManagedMaxConsecutiveErrorCount = Number(process.env.MANAGED_MINING_MAX_CONSECUTIVE_ERROR_COUNT ?? "10");
const defaultAutoBuyStaminaMaxFailures = Number(process.env.MANAGED_MINING_AUTO_BUY_MAX_FAILURES ?? "3");
const defaultLanguage = "zh_CN";
const supportedLanguages = new Set([
    "zh_CN",
    "zh_TW",
    "en_US",
    "ja_JP",
    "ko_KR",
    "ru_RU",
]);
let oreTypeNameMapCache;
export class GameApiHttpError extends Error {
    statusCode;
    responseBody;
    constructor(statusCode, message, responseBody) {
        super(message);
        this.name = "GameApiHttpError";
        this.statusCode = statusCode;
        this.responseBody = responseBody;
    }
}
const SERVER_ERROR = {
    COMMON_INVALID_PARAMS: 400,
    COMMON_NOT_ENOUGH_RESOURCES: 1010,
    GAME_INSUFFICIENT_RESOURCES: 2003,
    GAME_DIAMOND_NOT_ENOUGH: 2008,
    GAME_MINING_STATE_CONFLICT: 2009,
    GAME_MINING_API_NOT_ACTIVE: 2014,
    GAME_MINING_NOT_FINISHED: 2018,
};
function isInsufficientStaminaCode(code) {
    return code === SERVER_ERROR.GAME_INSUFFICIENT_RESOURCES;
}
function isCriticalStopCode(code) {
    return (code === SERVER_ERROR.GAME_DIAMOND_NOT_ENOUGH ||
        code === SERVER_ERROR.GAME_MINING_API_NOT_ACTIVE ||
        code === SERVER_ERROR.COMMON_INVALID_PARAMS);
}
function isMiningStateConflictCode(code) {
    return code === SERVER_ERROR.GAME_MINING_STATE_CONFLICT;
}
/**
 * Whether endMining should keep polling without escalating the error.
 */
function isPollingRewardRetryableCode(code) {
    return code === SERVER_ERROR.GAME_MINING_NOT_FINISHED;
}
function extractServerErrorCode(responseBody) {
    if (!responseBody || typeof responseBody !== "object") {
        return undefined;
    }
    const body = responseBody;
    return typeof body.code === "number" ? body.code : undefined;
}
function extractGetStaminaSnapshot(envelope) {
    if (!envelope || typeof envelope !== "object") {
        return undefined;
    }
    const envelopeObject = envelope;
    if (envelopeObject.code !== 0) {
        return undefined;
    }
    const dataObject = envelopeObject.data;
    if (!dataObject || typeof dataObject !== "object") {
        return undefined;
    }
    const stamina = Number(dataObject.stamina);
    const diamonds = Number(dataObject.diamonds);
    const maxStamina = Number(dataObject.maxStamina);
    if (!Number.isFinite(stamina) ||
        !Number.isFinite(diamonds) ||
        !Number.isFinite(maxStamina)) {
        return undefined;
    }
    return { stamina, diamonds, maxStamina };
}
function isBuyStaminaDiamondInsufficientCode(code) {
    if (code === undefined) {
        return false;
    }
    return (code === SERVER_ERROR.COMMON_NOT_ENOUGH_RESOURCES ||
        code === SERVER_ERROR.GAME_DIAMOND_NOT_ENOUGH);
}
async function tryAutoBuyStaminaAfterInsufficientResources(apiCode) {
    const getResult = await executePostWithApiCode("/api/getStamina", apiCode, {});
    if (getResult.httpStatus < 200 || getResult.httpStatus >= 300) {
        return "failed";
    }
    const getCode = extractServerErrorCode(getResult.body);
    if (getCode !== undefined && getCode !== 0) {
        return "failed";
    }
    const staminaSnapshot = extractGetStaminaSnapshot(getResult.body);
    if (staminaSnapshot &&
        staminaSnapshot.maxStamina > 0 &&
        staminaSnapshot.stamina >= staminaSnapshot.maxStamina) {
        return "recovered";
    }
    if (staminaSnapshot && staminaSnapshot.diamonds <= 0) {
        return "failed";
    }
    const buyResult = await executePostWithApiCode("/api/buyStamina", apiCode, {});
    if (buyResult.httpStatus < 200 || buyResult.httpStatus >= 300) {
        return "failed";
    }
    const buyCode = extractServerErrorCode(buyResult.body);
    if (buyCode === 0) {
        return "recovered";
    }
    if (isBuyStaminaDiamondInsufficientCode(buyCode)) {
        return "failed";
    }
    return "failed";
}
export async function startMining(apiCode) {
    return await postJson("/api/startMining", apiCode, {});
}
export async function checkMiningState(apiCode) {
    return await postJson("/api/checkMiningState", apiCode, {});
}
/** 同步服务端 MiningRuntime.apiAutoMining（托管循环开始时 true，结束时 false）。 */
export async function setApiAutoMining(apiCode, enabled) {
    const body = await postJson("/api/setAutoMining", apiCode, { enabled });
    const code = extractServerErrorCode(body);
    if (code !== undefined && code !== 0) {
        throw new GameApiHttpError(502, `setAutoMining failed code=${code}`, body);
    }
}
export async function endMining(apiCode, lang) {
    const response = await postJson("/api/endMining", apiCode, {});
    return await enrichRewardResponse(response, lang);
}
export async function fetchGameApiWithApiCodePost(path, apiCode, jsonBody) {
    return await executePostWithApiCode(path, apiCode, jsonBody);
}
export async function enrichEndMiningResponseForDisplay(response, lang) {
    return await enrichRewardResponse(response, lang);
}
export async function runManagedMiningLoop(apiCode, shouldContinue, callbacks, options) {
    const normalizedLanguage = normalizeLanguage(options?.lang);
    const pollingIntervalMilliseconds = normalizePositiveInteger(options?.pollingIntervalMilliseconds, defaultManagedPollingIntervalMilliseconds);
    const roundIntervalMilliseconds = normalizePositiveInteger(options?.roundIntervalMilliseconds, defaultManagedRoundIntervalMilliseconds);
    const maxConsecutiveErrorCount = normalizePositiveInteger(options?.maxConsecutiveErrorCount, defaultManagedMaxConsecutiveErrorCount);
    const autoBuyStaminaEnabled = options?.autoBuyStaminaEnabled === true;
    const autoBuyStaminaMaxFailuresConfigured = normalizePositiveInteger(options?.autoBuyStaminaMaxFailures, defaultAutoBuyStaminaMaxFailures);
    let roundsCompleted = 0;
    let consecutiveErrorCount = 0;
    let autoBuyStaminaFailureCount = 0;
    let lastError;
    let lastRewardDetails;
    let lastCheckState;
    while (shouldContinue()) {
        try {
            callbacks?.onPhaseChanged?.("starting_round");
            let startMiningState;
            try {
                startMiningState = await startMining(apiCode);
                consecutiveErrorCount = 0;
                lastError = undefined;
            }
            catch (error) {
                throw error;
            }
            const now = Date.now();
            let estimatedEndAt = extractEstimatedEndAt(startMiningState);
            if (!estimatedEndAt || estimatedEndAt <= now) {
                estimatedEndAt = now + 60000;
            }
            else {
                estimatedEndAt = Math.min(estimatedEndAt + 10000, now + 60000);
            }
            callbacks?.onPhaseChanged?.("waiting_estimated_end_at", {
                estimatedEndAt,
            });
            await sleepWithContinueCheck(estimatedEndAt - Date.now(), shouldContinue);
            if (!shouldContinue()) {
                break;
            }
            callbacks?.onPhaseChanged?.("polling_reward");
            while (shouldContinue()) {
                try {
                    const endResult = await endMining(apiCode, normalizedLanguage);
                    const rewardDetails = extractRewardDetails(endResult);
                    lastRewardDetails = rewardDetails;
                    lastCheckState = endResult;
                    roundsCompleted += 1;
                    autoBuyStaminaFailureCount = 0;
                    consecutiveErrorCount = 0;
                    lastError = undefined;
                    callbacks?.onRoundCompleted?.({
                        rewardDetails,
                        checkState: endResult,
                    });
                    callbacks?.onPhaseChanged?.("reward_collected", {
                        rewardCount: rewardDetails.length,
                        roundsCompleted,
                    });
                    callbacks?.onPhaseChanged?.("sleeping_between_rounds", {
                        roundIntervalMilliseconds,
                    });
                    await sleepWithContinueCheck(roundIntervalMilliseconds, shouldContinue);
                    break;
                }
                catch (endError) {
                    if (endError instanceof GameApiHttpError) {
                        const serverCode = extractServerErrorCode(endError.responseBody);
                        if (serverCode !== undefined && isCriticalStopCode(serverCode)) {
                            throw endError;
                        }
                        if (serverCode !== undefined &&
                            isPollingRewardRetryableCode(serverCode)) {
                            await sleepWithContinueCheck(pollingIntervalMilliseconds, shouldContinue);
                            continue;
                        }
                    }
                    throw endError;
                }
            }
        }
        catch (error) {
            if (error instanceof GameApiHttpError) {
                const serverCode = extractServerErrorCode(error.responseBody);
                if (autoBuyStaminaEnabled &&
                    serverCode !== undefined &&
                    isInsufficientStaminaCode(serverCode)) {
                    const buyAttempt = await tryAutoBuyStaminaAfterInsufficientResources(apiCode);
                    if (buyAttempt === "recovered") {
                        autoBuyStaminaFailureCount = 0;
                        await sleepWithContinueCheck(pollingIntervalMilliseconds, shouldContinue);
                        continue;
                    }
                    autoBuyStaminaFailureCount += 1;
                    lastError = `stamina_insufficient_auto_buy_failed count=${autoBuyStaminaFailureCount} max=${autoBuyStaminaMaxFailuresConfigured}`;
                    callbacks?.onError?.(lastError, autoBuyStaminaFailureCount, autoBuyStaminaMaxFailuresConfigured);
                    if (autoBuyStaminaFailureCount >= autoBuyStaminaMaxFailuresConfigured) {
                        callbacks?.onPhaseChanged?.("stopping", {
                            stopReason: "auto_buy_stamina_exhausted",
                            autoBuyStaminaFailureCount,
                        });
                        return {
                            stopReason: "auto_buy_stamina_exhausted",
                            roundsCompleted,
                            consecutiveErrorCount,
                            maxConsecutiveErrorCount,
                            lastError,
                            criticalErrorCode: serverCode,
                            autoBuyStaminaFailureCount,
                            lastRewardDetails,
                            lastCheckState,
                        };
                    }
                    await sleepWithContinueCheck(pollingIntervalMilliseconds, shouldContinue);
                    continue;
                }
                if (serverCode !== undefined && isCriticalStopCode(serverCode)) {
                    consecutiveErrorCount += 1;
                    lastError = getErrorMessage(error);
                    callbacks?.onPhaseChanged?.("stopping", {
                        stopReason: "critical_error",
                        consecutiveErrorCount,
                        criticalErrorCode: serverCode,
                    });
                    return {
                        stopReason: "critical_error",
                        roundsCompleted,
                        consecutiveErrorCount,
                        maxConsecutiveErrorCount,
                        lastError,
                        criticalErrorCode: serverCode,
                        lastRewardDetails,
                        lastCheckState,
                    };
                }
            }
            consecutiveErrorCount += 1;
            lastError = getErrorMessage(error);
            callbacks?.onError?.(lastError, consecutiveErrorCount, maxConsecutiveErrorCount);
            if (consecutiveErrorCount >= maxConsecutiveErrorCount) {
                callbacks?.onPhaseChanged?.("stopping", {
                    stopReason: "error_limit_reached",
                    consecutiveErrorCount,
                });
                return {
                    stopReason: "error_limit_reached",
                    roundsCompleted,
                    consecutiveErrorCount,
                    maxConsecutiveErrorCount,
                    lastError,
                    lastRewardDetails,
                    lastCheckState,
                };
            }
            await sleepWithContinueCheck(pollingIntervalMilliseconds, shouldContinue);
        }
    }
    callbacks?.onPhaseChanged?.("stopping", { stopReason: "stopped_by_user" });
    return {
        stopReason: "stopped_by_user",
        roundsCompleted,
        consecutiveErrorCount,
        maxConsecutiveErrorCount,
        lastError,
        lastRewardDetails,
        lastCheckState,
    };
}
async function executePostWithApiCode(path, apiCode, jsonBody) {
    const sanitizedApiCode = apiCode.trim();
    if (!sanitizedApiCode) {
        throw new Error("invalid_api_code");
    }
    const abortController = new AbortController();
    const timeoutHandle = setTimeout(() => {
        abortController.abort();
    }, requestTimeoutMilliseconds);
    try {
        const response = await fetch(`${gameApiBaseUrl}${path}`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-Api-Code": sanitizedApiCode,
            },
            body: JSON.stringify(jsonBody),
            signal: abortController.signal,
        });
        const responseJson = (await response.json());
        return { httpStatus: response.status, body: responseJson };
    }
    catch (error) {
        if (error instanceof Error && error.name === "AbortError") {
            throw new Error(`game_api_timeout timeoutMs=${requestTimeoutMilliseconds}`);
        }
        throw error;
    }
    finally {
        clearTimeout(timeoutHandle);
    }
}
async function postJson(path, apiCode, body) {
    const { httpStatus, body: responseBody } = await executePostWithApiCode(path, apiCode, body);
    if (httpStatus < 200 || httpStatus >= 300) {
        throw new GameApiHttpError(httpStatus, `game_api_error status=${httpStatus} body=${JSON.stringify(responseBody)}`, responseBody);
    }
    return responseBody;
}
function extractEstimatedEndAt(startState) {
    if (!startState || typeof startState !== "object") {
        return undefined;
    }
    const stateObject = startState;
    const estimatedEndAt = Number(stateObject.data?.estimatedEndAt);
    if (!Number.isFinite(estimatedEndAt) || estimatedEndAt <= 0) {
        return undefined;
    }
    return estimatedEndAt;
}
function extractRewardDetails(checkState) {
    if (!checkState || typeof checkState !== "object") {
        return [];
    }
    const stateObject = checkState;
    const resourceResultList = stateObject.data?.reward?.resResults;
    if (!Array.isArray(resourceResultList)) {
        return [];
    }
    return resourceResultList.map((resourceResultItem) => ({
        ...resourceResultItem,
    }));
}
function normalizePositiveInteger(value, fallbackValue) {
    const normalizedValue = Math.floor(Number(value));
    if (!Number.isFinite(normalizedValue) || normalizedValue <= 0) {
        return fallbackValue;
    }
    return normalizedValue;
}
function getErrorMessage(error) {
    if (error instanceof Error) {
        return error.message;
    }
    return String(error);
}
async function sleepWithContinueCheck(totalMilliseconds, shouldContinue) {
    const normalizedMilliseconds = Math.max(0, Math.floor(totalMilliseconds));
    if (normalizedMilliseconds <= 0) {
        return;
    }
    let remainingMilliseconds = normalizedMilliseconds;
    while (remainingMilliseconds > 0 && shouldContinue()) {
        const currentSleepMilliseconds = Math.min(remainingMilliseconds, 1000);
        await new Promise((resolve) => setTimeout(resolve, currentSleepMilliseconds));
        remainingMilliseconds -= currentSleepMilliseconds;
    }
}
async function enrichRewardResponse(response, lang) {
    const oreTypeNameMap = await loadOreTypeNameMap();
    const normalizedLanguage = normalizeLanguage(lang);
    if (!response || typeof response !== "object") {
        return response;
    }
    const responseObject = response;
    const resultList = responseObject.data?.reward?.resResults;
    if (!Array.isArray(resultList)) {
        return response;
    }
    for (const resultItem of resultList) {
        const oreTypeValue = Number(resultItem.oreType);
        if (!Number.isFinite(oreTypeValue)) {
            resultItem.oreTypeName = "Unknown Ore";
            continue;
        }
        const oreTypeNames = oreTypeNameMap[String(oreTypeValue)];
        if (!oreTypeNames) {
            resultItem.oreTypeName = `Unknown Ore(${oreTypeValue})`;
            continue;
        }
        resultItem.oreTypeName =
            oreTypeNames[normalizedLanguage] ??
                oreTypeNames[defaultLanguage] ??
                `Unknown Ore(${oreTypeValue})`;
    }
    return responseObject;
}
async function loadOreTypeNameMap() {
    if (oreTypeNameMapCache) {
        return oreTypeNameMapCache;
    }
    try {
        const fileContent = await readFile(oreTypeNameMapPath, "utf-8");
        const parsed = JSON.parse(fileContent);
        oreTypeNameMapCache = parsed.oreTypeNameMap ?? {};
        return oreTypeNameMapCache;
    }
    catch {
        oreTypeNameMapCache = {};
        return oreTypeNameMapCache;
    }
}
function normalizeLanguage(lang) {
    const normalizedLanguage = String(lang ?? "").trim();
    if (!supportedLanguages.has(normalizedLanguage)) {
        return defaultLanguage;
    }
    return normalizedLanguage;
}


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (HIGH)