openclaw-service 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -149,7 +149,7 @@ var init_logger = __esm({
149
149
  // src/core/openclaw.ts
150
150
  import { readFileSync as readFileSync2, existsSync as existsSync3, readdirSync } from "fs";
151
151
  import { join as join4 } from "path";
152
- import { homedir as homedir2 } from "os";
152
+ import { homedir as homedir2, platform } from "os";
153
153
  import { execSync } from "child_process";
154
154
  import { exec } from "child_process";
155
155
  import { promisify } from "util";
@@ -160,21 +160,23 @@ function getOpenClawHome(profile) {
160
160
  return join4(homedir2(), ".openclaw");
161
161
  }
162
162
  function findOpenClawBin() {
163
- const plistDir = join4(homedir2(), "Library", "LaunchAgents");
164
- if (existsSync3(plistDir)) {
165
- const plists = readdirSync(plistDir).filter(
166
- (f) => f.includes("openclaw") && f.endsWith(".plist")
167
- );
168
- for (const plist of plists) {
169
- const content = readFileSync2(join4(plistDir, plist), "utf-8");
170
- const nodeMatch = content.match(
171
- /<string>(\/[^<]*\/bin\/node)<\/string>/
163
+ if (PLATFORM === "darwin") {
164
+ const plistDir = join4(homedir2(), "Library", "LaunchAgents");
165
+ if (existsSync3(plistDir)) {
166
+ const plists = readdirSync(plistDir).filter(
167
+ (f) => f.includes("openclaw") && f.endsWith(".plist")
172
168
  );
173
- const cliMatch = content.match(
174
- /<string>(\/[^<]*openclaw[^<]*\.(?:js|mjs))<\/string>/
175
- );
176
- if (nodeMatch && cliMatch) {
177
- return { nodePath: nodeMatch[1], cliBinPath: cliMatch[1] };
169
+ for (const plist of plists) {
170
+ const content = readFileSync2(join4(plistDir, plist), "utf-8");
171
+ const nodeMatch = content.match(
172
+ /<string>(\/[^<]*\/bin\/node)<\/string>/
173
+ );
174
+ const cliMatch = content.match(
175
+ /<string>(\/[^<]*openclaw[^<]*\.(?:js|mjs))<\/string>/
176
+ );
177
+ if (nodeMatch && cliMatch) {
178
+ return { nodePath: nodeMatch[1], cliBinPath: cliMatch[1] };
179
+ }
178
180
  }
179
181
  }
180
182
  }
@@ -186,6 +188,7 @@ function findOpenClawBin() {
186
188
  return null;
187
189
  }
188
190
  function findLaunchdLabel() {
191
+ if (PLATFORM !== "darwin") return "ai.openclaw.gateway";
189
192
  const plistDir = join4(homedir2(), "Library", "LaunchAgents");
190
193
  if (!existsSync3(plistDir)) return "ai.openclaw.gateway";
191
194
  const plists = readdirSync(plistDir).filter(
@@ -196,6 +199,18 @@ function findLaunchdLabel() {
196
199
  }
197
200
  return "ai.openclaw.gateway";
198
201
  }
202
+ function hasSystemdService() {
203
+ try {
204
+ const { status } = __require("child_process").spawnSync(
205
+ "systemctl",
206
+ ["--user", "status", "openclaw"],
207
+ { stdio: "ignore" }
208
+ );
209
+ return status === 0 || status === 3;
210
+ } catch {
211
+ return false;
212
+ }
213
+ }
199
214
  function detectOpenClaw(profile = "default") {
200
215
  const home = getOpenClawHome(profile);
201
216
  const configPath = join4(home, "openclaw.json");
@@ -291,23 +306,51 @@ async function getGatewayHealth(info) {
291
306
  }
292
307
  }
293
308
  function getRestartCommand(info) {
309
+ if (PLATFORM === "win32") {
310
+ throw new Error("Windows native is not supported. Please use WSL 2.");
311
+ }
312
+ if (PLATFORM === "linux") {
313
+ if (hasSystemdService()) {
314
+ return "systemctl --user restart openclaw";
315
+ }
316
+ return `(pgrep -f "openclaw.*gateway" | xargs kill 2>/dev/null || true) && nohup openclaw gateway > /dev/null 2>&1 &`;
317
+ }
294
318
  const uid = process.getuid?.() ?? 501;
295
319
  return `launchctl kickstart -k gui/${uid}/${info.launchdLabel}`;
296
320
  }
297
321
  function getStopCommand(info) {
322
+ if (PLATFORM === "win32") {
323
+ throw new Error("Windows native is not supported. Please use WSL 2.");
324
+ }
325
+ if (PLATFORM === "linux") {
326
+ if (hasSystemdService()) {
327
+ return "systemctl --user stop openclaw";
328
+ }
329
+ return `pgrep -f "openclaw.*gateway" | xargs kill 2>/dev/null || true`;
330
+ }
298
331
  const uid = process.getuid?.() ?? 501;
299
332
  return `launchctl bootout gui/${uid}/${info.launchdLabel} 2>/dev/null || launchctl kill SIGTERM gui/${uid}/${info.launchdLabel} 2>/dev/null || true`;
300
333
  }
301
334
  function getStartCommand(info) {
335
+ if (PLATFORM === "win32") {
336
+ throw new Error("Windows native is not supported. Please use WSL 2.");
337
+ }
338
+ if (PLATFORM === "linux") {
339
+ if (hasSystemdService()) {
340
+ return "systemctl --user start openclaw";
341
+ }
342
+ return `nohup openclaw gateway > /dev/null 2>&1 &`;
343
+ }
302
344
  const uid = process.getuid?.() ?? 501;
303
345
  const plistDir = `${process.env.HOME}/Library/LaunchAgents`;
304
346
  return `(launchctl bootstrap gui/${uid} ${plistDir}/${info.launchdLabel}.plist 2>/dev/null || true) && launchctl kickstart gui/${uid}/${info.launchdLabel}`;
305
347
  }
306
- var execAsync;
348
+ var execAsync, PLATFORM;
307
349
  var init_openclaw = __esm({
308
350
  "src/core/openclaw.ts"() {
309
351
  "use strict";
310
352
  execAsync = promisify(exec);
353
+ PLATFORM = platform();
311
354
  }
312
355
  });
313
356
 
@@ -1339,7 +1382,7 @@ var init_server = __esm({
1339
1382
  init_process_manager();
1340
1383
  init_workspace_scanner();
1341
1384
  init_cost_scanner();
1342
- _PKG_VER = true ? "0.7.0" : "0.2.1";
1385
+ _PKG_VER = true ? "0.7.2" : "0.2.1";
1343
1386
  pkgVersion = _PKG_VER;
1344
1387
  }
1345
1388
  });
@@ -1371,7 +1414,7 @@ var API_SECRET = "qkqms1nURj2S02Q3WqO7GQ";
1371
1414
  var ENDPOINT = `https://www.google-analytics.com/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`;
1372
1415
  var TELEMETRY_FILE = join5(APP_HOME, "telemetry.json");
1373
1416
  var SESSION_ID = randomUUID();
1374
- var _version = true ? "0.7.0" : "0.0.0";
1417
+ var _version = true ? "0.7.2" : "0.0.0";
1375
1418
  function getVersion() {
1376
1419
  return _version;
1377
1420
  }
@@ -1880,22 +1923,22 @@ function showLogs(options) {
1880
1923
  console.log();
1881
1924
  }
1882
1925
  function showDoctorLogs(maxLines) {
1883
- const { readdirSync: readdirSync5 } = __require("fs");
1884
- const { join: join12 } = __require("path");
1926
+ const { readdirSync: readdirSync7 } = __require("fs");
1927
+ const { join: join14 } = __require("path");
1885
1928
  if (!existsSync10(DOCTOR_LOG_DIR)) {
1886
1929
  console.log(chalk6.yellow("No doctor logs found."));
1887
1930
  return;
1888
1931
  }
1889
- const files = readdirSync5(DOCTOR_LOG_DIR).filter((f) => f.endsWith(".log")).sort().reverse();
1932
+ const files = readdirSync7(DOCTOR_LOG_DIR).filter((f) => f.endsWith(".log")).sort().reverse();
1890
1933
  if (files.length === 0) {
1891
1934
  console.log(chalk6.yellow("No doctor log files found."));
1892
1935
  return;
1893
1936
  }
1894
1937
  const latest = files[0];
1895
1938
  console.log(chalk6.blue.bold(`
1896
- ${join12(DOCTOR_LOG_DIR, latest)}
1939
+ ${join14(DOCTOR_LOG_DIR, latest)}
1897
1940
  `));
1898
- const content = readFileSync8(join12(DOCTOR_LOG_DIR, latest), "utf-8");
1941
+ const content = readFileSync8(join14(DOCTOR_LOG_DIR, latest), "utf-8");
1899
1942
  const lines = content.trim().split("\n");
1900
1943
  const tail = lines.slice(-maxLines);
1901
1944
  for (const line of tail) {
@@ -1920,8 +1963,15 @@ init_process_manager();
1920
1963
  init_logger();
1921
1964
  import chalk7 from "chalk";
1922
1965
  import { writeFileSync as writeFileSync5, unlinkSync as unlinkSync2 } from "fs";
1923
- var _VER = true ? "0.7.0" : void 0;
1966
+ import { platform as platform2 } from "os";
1967
+ function showPlatformNote() {
1968
+ if (platform2() === "linux") {
1969
+ console.log(chalk7.cyan("Running on Linux/WSL. Using systemd or direct process management (launchctl not available)."));
1970
+ }
1971
+ }
1972
+ var _VER = true ? "0.7.2" : void 0;
1924
1973
  async function gatewayStart(options) {
1974
+ showPlatformNote();
1925
1975
  const config = loadConfig(options.config);
1926
1976
  initLogger();
1927
1977
  ensureDoctorHome();
@@ -1943,6 +1993,7 @@ async function gatewayStart(options) {
1943
1993
  }
1944
1994
  }
1945
1995
  async function gatewayStop(options) {
1996
+ showPlatformNote();
1946
1997
  const config = loadConfig(options.config);
1947
1998
  initLogger();
1948
1999
  ensureDoctorHome();
@@ -1962,6 +2013,7 @@ async function gatewayStop(options) {
1962
2013
  }
1963
2014
  }
1964
2015
  async function gatewayRestart(options) {
2016
+ showPlatformNote();
1965
2017
  const config = loadConfig(options.config);
1966
2018
  initLogger();
1967
2019
  ensureDoctorHome();
@@ -1987,12 +2039,25 @@ async function gatewayRestart(options) {
1987
2039
  init_config();
1988
2040
  init_openclaw();
1989
2041
  import chalk8 from "chalk";
1990
- import { existsSync as existsSync12, statSync as statSync3 } from "fs";
1991
- import { join as join10 } from "path";
2042
+ import { existsSync as existsSync12, statSync as statSync3, readFileSync as readFileSync9, readdirSync as readdirSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
2043
+ import { join as join10, basename as basename2 } from "path";
1992
2044
  import { homedir as homedir5 } from "os";
2045
+ import { createInterface } from "readline";
1993
2046
  function expandHome2(p) {
1994
2047
  return p.startsWith("~/") ? join10(homedir5(), p.slice(2)) : p;
1995
2048
  }
2049
+ function getAgentMemoryPaths(agents) {
2050
+ const paths = [];
2051
+ for (const agent of agents) {
2052
+ const ws = agent.workspace;
2053
+ if (!ws) continue;
2054
+ const wsPath = expandHome2(ws);
2055
+ if (existsSync12(wsPath)) {
2056
+ paths.push({ agent: agent.name, dir: wsPath });
2057
+ }
2058
+ }
2059
+ return paths;
2060
+ }
1996
2061
  async function memoryStatus(options) {
1997
2062
  const config = loadConfig(options.config);
1998
2063
  const info = detectOpenClaw(options.profile ?? config.openclawProfile);
@@ -2017,11 +2082,54 @@ async function memorySearch(query, options) {
2017
2082
  console.log(chalk8.bold(`
2018
2083
  Searching memory: "${query}"
2019
2084
  `));
2020
- const output = await runOpenClawCmd(info, `memory search "${query}"`);
2021
- if (output) {
2022
- console.log(output);
2023
- } else {
2024
- console.log(chalk8.yellow(" No results or openclaw memory search unavailable"));
2085
+ const agentPaths = getAgentMemoryPaths(info.agents);
2086
+ let found = false;
2087
+ for (const { agent, dir } of agentPaths) {
2088
+ const filesToSearch = [];
2089
+ const memPath = join10(dir, "MEMORY.md");
2090
+ if (existsSync12(memPath)) filesToSearch.push(memPath);
2091
+ const memDir = join10(dir, "memory");
2092
+ if (existsSync12(memDir)) {
2093
+ try {
2094
+ const files = readdirSync5(memDir).filter((f) => f.endsWith(".md"));
2095
+ for (const f of files) {
2096
+ filesToSearch.push(join10(memDir, f));
2097
+ }
2098
+ } catch {
2099
+ }
2100
+ }
2101
+ for (const filePath of filesToSearch) {
2102
+ try {
2103
+ const content = readFileSync9(filePath, "utf-8");
2104
+ const lines = content.split("\n");
2105
+ const lowerQuery = query.toLowerCase();
2106
+ for (let i = 0; i < lines.length; i++) {
2107
+ if (lines[i].toLowerCase().includes(lowerQuery)) {
2108
+ if (!found) found = true;
2109
+ const relPath = basename2(filePath);
2110
+ const contextStart = Math.max(0, i - 1);
2111
+ const contextEnd = Math.min(lines.length, i + 2);
2112
+ const context = lines.slice(contextStart, contextEnd).map((l, idx) => {
2113
+ const lineNum = contextStart + idx + 1;
2114
+ const prefix = lineNum === i + 1 ? chalk8.yellow("\u2192") : " ";
2115
+ return ` ${prefix} ${chalk8.gray(`${lineNum}:`)} ${l}`;
2116
+ }).join("\n");
2117
+ console.log(` ${chalk8.cyan(agent)} ${chalk8.gray("/")} ${chalk8.white(relPath)}${chalk8.gray(`:${i + 1}`)}`);
2118
+ console.log(context);
2119
+ console.log();
2120
+ }
2121
+ }
2122
+ } catch {
2123
+ }
2124
+ }
2125
+ }
2126
+ if (!found) {
2127
+ const output = await runOpenClawCmd(info, `memory search "${query}"`);
2128
+ if (output) {
2129
+ console.log(output);
2130
+ } else {
2131
+ console.log(chalk8.yellow(" No results found."));
2132
+ }
2025
2133
  }
2026
2134
  console.log();
2027
2135
  }
@@ -2040,36 +2148,512 @@ async function memoryCompact(options) {
2040
2148
  }
2041
2149
  console.log();
2042
2150
  }
2151
+ async function memoryGc(options) {
2152
+ const config = loadConfig(options.config);
2153
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
2154
+ const maxAgeDays = parseInt(options.days ?? "30", 10);
2155
+ const cutoff = Date.now() - maxAgeDays * 24 * 3600 * 1e3;
2156
+ console.log(chalk8.bold(`
2157
+ Memory GC \u2014 removing daily files older than ${maxAgeDays} days
2158
+ `));
2159
+ const agentPaths = getAgentMemoryPaths(info.agents);
2160
+ const filesToDelete = [];
2161
+ const dailyPattern = /^\d{4}-\d{2}-\d{2}\.md$/;
2162
+ for (const { agent, dir } of agentPaths) {
2163
+ const memDir = join10(dir, "memory");
2164
+ if (!existsSync12(memDir)) continue;
2165
+ try {
2166
+ const files = readdirSync5(memDir).filter((f) => dailyPattern.test(f));
2167
+ for (const f of files) {
2168
+ const fpath = join10(memDir, f);
2169
+ try {
2170
+ const stat = statSync3(fpath);
2171
+ if (stat.mtimeMs < cutoff) {
2172
+ filesToDelete.push({ path: fpath, agent, name: f, size: stat.size });
2173
+ }
2174
+ } catch {
2175
+ }
2176
+ }
2177
+ } catch {
2178
+ }
2179
+ }
2180
+ if (filesToDelete.length === 0) {
2181
+ console.log(chalk8.green(" No old daily memory files found. Nothing to clean up.\n"));
2182
+ return;
2183
+ }
2184
+ console.log(` Found ${chalk8.yellow(String(filesToDelete.length))} files to remove:
2185
+ `);
2186
+ for (const f of filesToDelete) {
2187
+ const sizeKB = Math.round(f.size / 1024);
2188
+ console.log(` ${chalk8.gray("\u2022")} ${f.agent} / ${f.name} ${chalk8.gray(`(${sizeKB}KB)`)}`);
2189
+ }
2190
+ console.log();
2191
+ const totalKB = Math.round(filesToDelete.reduce((s, f) => s + f.size, 0) / 1024);
2192
+ console.log(` Total: ${chalk8.yellow(`${totalKB}KB`)} across ${filesToDelete.length} files
2193
+ `);
2194
+ if (!options.force) {
2195
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
2196
+ const answer = await new Promise((resolve3) => {
2197
+ rl.question(" Delete these files? [y/N] ", resolve3);
2198
+ });
2199
+ rl.close();
2200
+ if (answer.toLowerCase() !== "y") {
2201
+ console.log(chalk8.gray(" Cancelled.\n"));
2202
+ return;
2203
+ }
2204
+ }
2205
+ let deleted = 0;
2206
+ for (const f of filesToDelete) {
2207
+ try {
2208
+ unlinkSync3(f.path);
2209
+ deleted++;
2210
+ } catch (err) {
2211
+ console.log(chalk8.red(` Failed to delete ${f.name}: ${err}`));
2212
+ }
2213
+ }
2214
+ console.log(chalk8.green(`
2215
+ Deleted ${deleted} files.
2216
+ `));
2217
+ }
2218
+ async function memoryExport(options) {
2219
+ const config = loadConfig(options.config);
2220
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
2221
+ const agentPaths = getAgentMemoryPaths(info.agents);
2222
+ const parts = [];
2223
+ parts.push(`# OpenClaw Memory Export`);
2224
+ parts.push(`# Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
2225
+ `);
2226
+ for (const { agent, dir } of agentPaths) {
2227
+ const agentParts = [];
2228
+ const memPath = join10(dir, "MEMORY.md");
2229
+ if (existsSync12(memPath)) {
2230
+ try {
2231
+ const content = readFileSync9(memPath, "utf-8");
2232
+ agentParts.push(`### MEMORY.md
2233
+
2234
+ ${content}`);
2235
+ } catch {
2236
+ }
2237
+ }
2238
+ const memDir = join10(dir, "memory");
2239
+ if (existsSync12(memDir)) {
2240
+ try {
2241
+ const files = readdirSync5(memDir).filter((f) => f.endsWith(".md")).sort();
2242
+ for (const f of files) {
2243
+ try {
2244
+ const content = readFileSync9(join10(memDir, f), "utf-8");
2245
+ agentParts.push(`### memory/${f}
2246
+
2247
+ ${content}`);
2248
+ } catch {
2249
+ }
2250
+ }
2251
+ } catch {
2252
+ }
2253
+ }
2254
+ if (agentParts.length > 0) {
2255
+ parts.push(`## Agent: ${agent}
2256
+ `);
2257
+ parts.push(agentParts.join("\n---\n\n"));
2258
+ parts.push("");
2259
+ }
2260
+ }
2261
+ if (parts.length <= 2) {
2262
+ console.log(chalk8.yellow("\n No memory files found to export.\n"));
2263
+ return;
2264
+ }
2265
+ const result = parts.join("\n");
2266
+ if (options.output) {
2267
+ writeFileSync6(options.output, result, "utf-8");
2268
+ console.log(chalk8.green(`
2269
+ Exported memory to ${options.output}
2270
+ `));
2271
+ } else {
2272
+ console.log(result);
2273
+ }
2274
+ }
2275
+
2276
+ // src/commands/cost.ts
2277
+ init_config();
2278
+ init_openclaw();
2279
+ import chalk9 from "chalk";
2280
+ import { existsSync as existsSync13, readdirSync as readdirSync6, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
2281
+ import { join as join11 } from "path";
2282
+ import { homedir as homedir6 } from "os";
2283
+ var RATES = {
2284
+ "claude-opus-4": { input: 15, output: 75 },
2285
+ "claude-sonnet-4": { input: 3, output: 15 },
2286
+ "claude-haiku-3-5": { input: 0.8, output: 4 },
2287
+ "gpt-4o": { input: 2.5, output: 10 },
2288
+ "gpt-4o-mini": { input: 0.15, output: 0.6 }
2289
+ };
2290
+ var DEFAULT_RATE = { input: 3, output: 15 };
2291
+ function getRate(model) {
2292
+ if (RATES[model]) return RATES[model];
2293
+ for (const [key, rate] of Object.entries(RATES)) {
2294
+ if (model.startsWith(key)) return rate;
2295
+ }
2296
+ return DEFAULT_RATE;
2297
+ }
2298
+ function calcCost(model, inputTokens, outputTokens) {
2299
+ const rate = getRate(model);
2300
+ return (inputTokens * rate.input + outputTokens * rate.output) / 1e6;
2301
+ }
2302
+ function expandHome3(p) {
2303
+ return p.startsWith("~/") ? join11(homedir6(), p.slice(2)) : p;
2304
+ }
2305
+ function scanSessionFiles(agents, sinceDays) {
2306
+ const entries = [];
2307
+ const cutoff = Date.now() - sinceDays * 24 * 3600 * 1e3;
2308
+ for (const agent of agents) {
2309
+ const searchPaths = [];
2310
+ searchPaths.push(join11(homedir6(), ".openclaw", "agents", agent.id, "sessions"));
2311
+ if (agent.workspace) {
2312
+ const ws = expandHome3(agent.workspace);
2313
+ searchPaths.push(join11(ws, "sessions"));
2314
+ searchPaths.push(join11(ws, "logs"));
2315
+ }
2316
+ for (const sessDir of searchPaths) {
2317
+ if (!existsSync13(sessDir)) continue;
2318
+ const files = readdirSync6(sessDir).filter((f) => f.endsWith(".jsonl") || f.endsWith(".json"));
2319
+ for (const file of files) {
2320
+ const fpath = join11(sessDir, file);
2321
+ try {
2322
+ const mtime = statSync4(fpath).mtimeMs;
2323
+ if (mtime < cutoff) continue;
2324
+ } catch {
2325
+ continue;
2326
+ }
2327
+ try {
2328
+ const lines = readFileSync10(fpath, "utf-8").split("\n").filter(Boolean);
2329
+ for (const line of lines) {
2330
+ try {
2331
+ const msg = JSON.parse(line);
2332
+ if (msg.type !== "message" || !msg.message?.usage) continue;
2333
+ const usage = msg.message.usage;
2334
+ const ts = msg.timestamp ? new Date(msg.timestamp).getTime() : msg.message?.timestamp ?? 0;
2335
+ if (ts < cutoff) continue;
2336
+ const model = msg.message?.model ?? msg.model ?? "unknown";
2337
+ const inputTokens = usage.input_tokens ?? usage.inputTokens ?? 0;
2338
+ const outputTokens = usage.output_tokens ?? usage.outputTokens ?? 0;
2339
+ if (inputTokens === 0 && outputTokens === 0) continue;
2340
+ entries.push({
2341
+ model,
2342
+ inputTokens,
2343
+ outputTokens,
2344
+ timestamp: ts,
2345
+ agentName: agent.name,
2346
+ agentId: agent.id
2347
+ });
2348
+ } catch {
2349
+ }
2350
+ }
2351
+ } catch {
2352
+ }
2353
+ }
2354
+ }
2355
+ }
2356
+ const globalLogDir = join11(homedir6(), ".openclaw", "logs");
2357
+ if (existsSync13(globalLogDir)) {
2358
+ const files = readdirSync6(globalLogDir).filter((f) => f.endsWith(".jsonl"));
2359
+ for (const file of files) {
2360
+ const fpath = join11(globalLogDir, file);
2361
+ try {
2362
+ const mtime = statSync4(fpath).mtimeMs;
2363
+ if (mtime < cutoff) continue;
2364
+ } catch {
2365
+ continue;
2366
+ }
2367
+ try {
2368
+ const lines = readFileSync10(fpath, "utf-8").split("\n").filter(Boolean);
2369
+ for (const line of lines) {
2370
+ try {
2371
+ const msg = JSON.parse(line);
2372
+ if (msg.type !== "message" || !msg.message?.usage) continue;
2373
+ const usage = msg.message.usage;
2374
+ const ts = msg.timestamp ? new Date(msg.timestamp).getTime() : msg.message?.timestamp ?? 0;
2375
+ if (ts < cutoff) continue;
2376
+ const model = msg.message?.model ?? msg.model ?? "unknown";
2377
+ const inputTokens = usage.input_tokens ?? usage.inputTokens ?? 0;
2378
+ const outputTokens = usage.output_tokens ?? usage.outputTokens ?? 0;
2379
+ if (inputTokens === 0 && outputTokens === 0) continue;
2380
+ const agentId = msg.agentId ?? msg.message?.agentId ?? "unknown";
2381
+ const agentName = msg.agentName ?? msg.message?.agentName ?? agentId;
2382
+ entries.push({ model, inputTokens, outputTokens, timestamp: ts, agentName, agentId });
2383
+ } catch {
2384
+ }
2385
+ }
2386
+ } catch {
2387
+ }
2388
+ }
2389
+ }
2390
+ return entries;
2391
+ }
2392
+ function formatCost(cost) {
2393
+ if (cost < 0.01) return `$${cost.toFixed(4)}`;
2394
+ return `$${cost.toFixed(2)}`;
2395
+ }
2396
+ function formatTokens(n) {
2397
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
2398
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
2399
+ return String(n);
2400
+ }
2401
+ async function showCost(options) {
2402
+ const config = loadConfig(options.config);
2403
+ const info = detectOpenClaw(options.profile ?? config.openclawProfile);
2404
+ const days = parseInt(options.days ?? "30", 10);
2405
+ if (info.agents.length === 0) {
2406
+ console.log(chalk9.yellow("\n No agents found in openclaw config."));
2407
+ console.log(chalk9.gray(" Make sure openclaw is installed and configured.\n"));
2408
+ return;
2409
+ }
2410
+ const entries = scanSessionFiles(
2411
+ info.agents.map((a) => ({ id: a.id, name: a.name, workspace: a.workspace })),
2412
+ days
2413
+ );
2414
+ if (entries.length === 0) {
2415
+ console.log(chalk9.yellow("\n No session logs found."));
2416
+ console.log(chalk9.gray(" OpenClaw stores session logs in:"));
2417
+ console.log(chalk9.gray(` ~/.openclaw/agents/<agent-id>/sessions/`));
2418
+ console.log(chalk9.gray(` ~/.openclaw/logs/
2419
+ `));
2420
+ return;
2421
+ }
2422
+ const now = Date.now();
2423
+ const todayStart = /* @__PURE__ */ new Date();
2424
+ todayStart.setHours(0, 0, 0, 0);
2425
+ const weekStart = now - 7 * 24 * 3600 * 1e3;
2426
+ const monthStart = now - 30 * 24 * 3600 * 1e3;
2427
+ const byAgent = {};
2428
+ const byModel = {};
2429
+ for (const e of entries) {
2430
+ const cost = calcCost(e.model, e.inputTokens, e.outputTokens);
2431
+ if (!byAgent[e.agentName]) byAgent[e.agentName] = { today: 0, week: 0, month: 0, tokens: 0 };
2432
+ const ag = byAgent[e.agentName];
2433
+ ag.tokens += e.inputTokens + e.outputTokens;
2434
+ if (e.timestamp >= monthStart) ag.month += cost;
2435
+ if (e.timestamp >= weekStart) ag.week += cost;
2436
+ if (e.timestamp >= todayStart.getTime()) ag.today += cost;
2437
+ if (!byModel[e.model]) byModel[e.model] = { today: 0, week: 0, month: 0, input: 0, output: 0 };
2438
+ const md = byModel[e.model];
2439
+ md.input += e.inputTokens;
2440
+ md.output += e.outputTokens;
2441
+ if (e.timestamp >= monthStart) md.month += cost;
2442
+ if (e.timestamp >= weekStart) md.week += cost;
2443
+ if (e.timestamp >= todayStart.getTime()) md.today += cost;
2444
+ }
2445
+ const totalToday = Object.values(byAgent).reduce((s, a) => s + a.today, 0);
2446
+ const totalWeek = Object.values(byAgent).reduce((s, a) => s + a.week, 0);
2447
+ const totalMonth = Object.values(byAgent).reduce((s, a) => s + a.month, 0);
2448
+ if (options.json) {
2449
+ console.log(JSON.stringify({
2450
+ period: { days },
2451
+ summary: { today: totalToday, week: totalWeek, month: totalMonth, currency: "USD" },
2452
+ byAgent: Object.entries(byAgent).map(([name, v]) => ({ name, ...v })),
2453
+ byModel: Object.entries(byModel).map(([model, v]) => ({ model, ...v })),
2454
+ entries: entries.length
2455
+ }, null, 2));
2456
+ return;
2457
+ }
2458
+ console.log(chalk9.bold("\n Token Cost Summary\n"));
2459
+ console.log(` ${"Period".padEnd(14)} ${"Cost".padStart(10)}`);
2460
+ console.log(` ${"\u2500".repeat(14)} ${"\u2500".repeat(10)}`);
2461
+ console.log(` ${"Today".padEnd(14)} ${chalk9.green(formatCost(totalToday).padStart(10))}`);
2462
+ console.log(` ${"This week".padEnd(14)} ${chalk9.cyan(formatCost(totalWeek).padStart(10))}`);
2463
+ console.log(` ${"Last 30 days".padEnd(14)} ${chalk9.yellow(formatCost(totalMonth).padStart(10))}`);
2464
+ const agentEntries = Object.entries(byAgent).sort((a, b) => b[1].month - a[1].month);
2465
+ if (agentEntries.length > 0) {
2466
+ console.log(chalk9.bold("\n By Agent\n"));
2467
+ console.log(` ${"Agent".padEnd(20)} ${"Today".padStart(10)} ${"Week".padStart(10)} ${"Month".padStart(10)} ${"Tokens".padStart(10)}`);
2468
+ console.log(` ${"\u2500".repeat(20)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)}`);
2469
+ for (const [name, v] of agentEntries) {
2470
+ console.log(` ${name.padEnd(20)} ${formatCost(v.today).padStart(10)} ${formatCost(v.week).padStart(10)} ${formatCost(v.month).padStart(10)} ${chalk9.gray(formatTokens(v.tokens).padStart(10))}`);
2471
+ }
2472
+ }
2473
+ const modelEntries = Object.entries(byModel).sort((a, b) => b[1].month - a[1].month);
2474
+ if (modelEntries.length > 0) {
2475
+ console.log(chalk9.bold("\n By Model\n"));
2476
+ console.log(` ${"Model".padEnd(24)} ${"Today".padStart(10)} ${"Week".padStart(10)} ${"Month".padStart(10)} ${"In Tokens".padStart(10)} ${"Out Tokens".padStart(10)}`);
2477
+ console.log(` ${"\u2500".repeat(24)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)} ${"\u2500".repeat(10)}`);
2478
+ for (const [model, v] of modelEntries) {
2479
+ console.log(` ${model.padEnd(24)} ${formatCost(v.today).padStart(10)} ${formatCost(v.week).padStart(10)} ${formatCost(v.month).padStart(10)} ${chalk9.gray(formatTokens(v.input).padStart(10))} ${chalk9.gray(formatTokens(v.output).padStart(10))}`);
2480
+ }
2481
+ }
2482
+ console.log();
2483
+ }
2484
+
2485
+ // src/commands/mcp.ts
2486
+ import chalk10 from "chalk";
2487
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
2488
+ import { join as join12 } from "path";
2489
+ import { homedir as homedir7 } from "os";
2490
+ import { execSync as execSync3 } from "child_process";
2491
+ var CONFIG_LOCATIONS = [
2492
+ { path: join12(homedir7(), ".config", "claude", "claude_desktop_config.json"), label: "Claude Desktop" },
2493
+ { path: join12(homedir7(), "Library", "Application Support", "Claude", "claude_desktop_config.json"), label: "Claude Desktop (macOS)" },
2494
+ { path: join12(homedir7(), ".config", "cursor", "mcp.json"), label: "Cursor" },
2495
+ { path: join12(homedir7(), ".openclaw", "config.yaml"), label: "OpenClaw" },
2496
+ { path: join12(homedir7(), ".openclaw", "mcp.json"), label: "OpenClaw MCP" }
2497
+ ];
2498
+ function findMcpConfigs() {
2499
+ const servers = [];
2500
+ for (const loc of CONFIG_LOCATIONS) {
2501
+ if (!existsSync14(loc.path)) continue;
2502
+ try {
2503
+ const raw = readFileSync11(loc.path, "utf-8");
2504
+ if (loc.path.endsWith(".yaml") || loc.path.endsWith(".yml")) {
2505
+ const mcpMatch = raw.match(/mcp_servers:\s*\n([\s\S]*?)(?:\n\w|\n*$)/);
2506
+ if (mcpMatch) {
2507
+ const lines = mcpMatch[1].split("\n");
2508
+ for (const line of lines) {
2509
+ const nameMatch = line.match(/^\s+-\s+name:\s*(.+)/);
2510
+ if (nameMatch) {
2511
+ servers.push({
2512
+ name: nameMatch[1].trim(),
2513
+ type: "unknown",
2514
+ source: loc.label,
2515
+ status: "UNKNOWN"
2516
+ });
2517
+ }
2518
+ }
2519
+ }
2520
+ continue;
2521
+ }
2522
+ const config = JSON.parse(raw);
2523
+ const mcpServers = config.mcpServers ?? config.mcp_servers ?? config.servers ?? {};
2524
+ for (const [name, def] of Object.entries(mcpServers)) {
2525
+ const d = def;
2526
+ const server = {
2527
+ name,
2528
+ type: d.command ? "stdio" : d.url ? "http" : "unknown",
2529
+ command: d.command,
2530
+ url: d.url,
2531
+ args: d.args,
2532
+ env: d.env,
2533
+ source: loc.label,
2534
+ status: "UNKNOWN"
2535
+ };
2536
+ if (server.type === "stdio" && server.command) {
2537
+ server.status = checkProcessRunning(server.command) ? "RUNNING" : "STOPPED";
2538
+ } else if (server.type === "http") {
2539
+ server.status = "UNKNOWN";
2540
+ }
2541
+ servers.push(server);
2542
+ }
2543
+ } catch {
2544
+ }
2545
+ }
2546
+ return servers;
2547
+ }
2548
+ function checkProcessRunning(command) {
2549
+ try {
2550
+ const baseName = command.split("/").pop() ?? command;
2551
+ const result = execSync3(`pgrep -f "${baseName}"`, { encoding: "utf-8", timeout: 3e3 });
2552
+ return result.trim().length > 0;
2553
+ } catch {
2554
+ return false;
2555
+ }
2556
+ }
2557
+ function statusColor(status) {
2558
+ switch (status) {
2559
+ case "RUNNING":
2560
+ return chalk10.green(status);
2561
+ case "STOPPED":
2562
+ return chalk10.red(status);
2563
+ default:
2564
+ return chalk10.gray(status);
2565
+ }
2566
+ }
2567
+ async function mcpList() {
2568
+ const servers = findMcpConfigs();
2569
+ if (servers.length === 0) {
2570
+ console.log(chalk10.yellow("\n No MCP server configurations found."));
2571
+ console.log(chalk10.gray(" Checked:"));
2572
+ for (const loc of CONFIG_LOCATIONS) {
2573
+ console.log(chalk10.gray(` ${loc.path}`));
2574
+ }
2575
+ console.log(chalk10.gray("\n Configure MCP servers in Claude Desktop:"));
2576
+ console.log(chalk10.gray(` ${CONFIG_LOCATIONS[0].path}
2577
+ `));
2578
+ return;
2579
+ }
2580
+ console.log(chalk10.bold("\n MCP Servers\n"));
2581
+ console.log(` ${"Name".padEnd(24)} ${"Type".padEnd(8)} ${"Status".padEnd(12)} ${"Source".padEnd(20)} ${"Command/URL"}`);
2582
+ console.log(` ${"\u2500".repeat(24)} ${"\u2500".repeat(8)} ${"\u2500".repeat(12)} ${"\u2500".repeat(20)} ${"\u2500".repeat(30)}`);
2583
+ for (const s of servers) {
2584
+ const endpoint = s.command ? `${s.command}${s.args?.length ? " " + s.args.join(" ") : ""}` : s.url ?? "";
2585
+ const truncEndpoint = endpoint.length > 50 ? endpoint.slice(0, 47) + "..." : endpoint;
2586
+ console.log(
2587
+ ` ${s.name.padEnd(24)} ${s.type.padEnd(8)} ${statusColor(s.status).padEnd(12 + 10)} ${chalk10.gray(s.source.padEnd(20))} ${chalk10.gray(truncEndpoint)}`
2588
+ );
2589
+ }
2590
+ console.log();
2591
+ }
2592
+ async function mcpStatus(name) {
2593
+ const servers = findMcpConfigs();
2594
+ const server = servers.find((s) => s.name === name);
2595
+ if (!server) {
2596
+ console.log(chalk10.red(`
2597
+ MCP server "${name}" not found.`));
2598
+ const available = servers.map((s) => s.name).join(", ");
2599
+ if (available) {
2600
+ console.log(chalk10.gray(` Available: ${available}
2601
+ `));
2602
+ } else {
2603
+ console.log(chalk10.gray(" No MCP servers configured.\n"));
2604
+ }
2605
+ return;
2606
+ }
2607
+ console.log(chalk10.bold(`
2608
+ MCP Server: ${server.name}
2609
+ `));
2610
+ console.log(` Status: ${statusColor(server.status)}`);
2611
+ console.log(` Type: ${server.type}`);
2612
+ console.log(` Source: ${chalk10.gray(server.source)}`);
2613
+ if (server.command) {
2614
+ console.log(` Command: ${server.command}`);
2615
+ if (server.args?.length) {
2616
+ console.log(` Args: ${server.args.join(" ")}`);
2617
+ }
2618
+ }
2619
+ if (server.url) {
2620
+ console.log(` URL: ${server.url}`);
2621
+ }
2622
+ if (server.env && Object.keys(server.env).length > 0) {
2623
+ console.log(` Env: ${Object.keys(server.env).join(", ")}`);
2624
+ }
2625
+ console.log();
2626
+ }
2043
2627
 
2044
2628
  // src/index.ts
2045
2629
  init_server();
2046
2630
  init_openclaw();
2047
2631
 
2048
2632
  // src/commands/telemetry.ts
2049
- import chalk9 from "chalk";
2633
+ import chalk11 from "chalk";
2050
2634
  function telemetryOn() {
2051
2635
  setOptOut(false);
2052
- console.log(chalk9.green("\u2713 Telemetry enabled. Thanks for helping improve OpenClaw!"));
2636
+ console.log(chalk11.green("\u2713 Telemetry enabled. Thanks for helping improve OpenClaw!"));
2053
2637
  }
2054
2638
  function telemetryOff() {
2055
2639
  setOptOut(true);
2056
- console.log(chalk9.yellow("\u2713 Telemetry disabled. Set OPENCLAW_NO_TELEMETRY=1 to suppress permanently."));
2640
+ console.log(chalk11.yellow("\u2713 Telemetry disabled. Set OPENCLAW_NO_TELEMETRY=1 to suppress permanently."));
2057
2641
  }
2058
2642
  function telemetryStatus() {
2059
2643
  const { optOut, clientId } = getTelemetryStatus();
2060
- const status = optOut ? chalk9.red("disabled") : chalk9.green("enabled");
2644
+ const status = optOut ? chalk11.red("disabled") : chalk11.green("enabled");
2061
2645
  console.log(`Telemetry: ${status}`);
2062
- console.log(`Client ID: ${chalk9.dim(clientId)}`);
2646
+ console.log(`Client ID: ${chalk11.dim(clientId)}`);
2063
2647
  console.log();
2064
- console.log(chalk9.dim("Toggle: openclaw telemetry on/off"));
2065
- console.log(chalk9.dim("Env: OPENCLAW_NO_TELEMETRY=1"));
2648
+ console.log(chalk11.dim("Toggle: openclaw telemetry on/off"));
2649
+ console.log(chalk11.dim("Env: OPENCLAW_NO_TELEMETRY=1"));
2066
2650
  }
2067
2651
 
2068
2652
  // src/commands/remote.ts
2069
2653
  init_config();
2070
- import chalk10 from "chalk";
2071
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync13, mkdirSync as mkdirSync3 } from "fs";
2072
- import { join as join11 } from "path";
2654
+ import chalk12 from "chalk";
2655
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, existsSync as existsSync15, mkdirSync as mkdirSync3 } from "fs";
2656
+ import { join as join13 } from "path";
2073
2657
  import { randomUUID as randomUUID2, randomBytes, createHash as createHash2 } from "crypto";
2074
2658
  import { createServer as createServer2 } from "http";
2075
2659
  import { exec as exec3 } from "child_process";
@@ -2087,11 +2671,11 @@ async function proxyFetch(url, init) {
2087
2671
  return fetch(url, init);
2088
2672
  }
2089
2673
  var REMOTE_API_URL = "https://api.openclaw-cli.app";
2090
- var REMOTE_CONFIG_FILE = join11(DOCTOR_HOME, "remote.json");
2674
+ var REMOTE_CONFIG_FILE = join13(DOCTOR_HOME, "remote.json");
2091
2675
  function loadRemoteConfig() {
2092
2676
  try {
2093
- if (existsSync13(REMOTE_CONFIG_FILE)) {
2094
- return JSON.parse(readFileSync10(REMOTE_CONFIG_FILE, "utf-8"));
2677
+ if (existsSync15(REMOTE_CONFIG_FILE)) {
2678
+ return JSON.parse(readFileSync12(REMOTE_CONFIG_FILE, "utf-8"));
2095
2679
  }
2096
2680
  } catch {
2097
2681
  }
@@ -2104,9 +2688,9 @@ function loadRemoteConfig() {
2104
2688
  };
2105
2689
  }
2106
2690
  function saveRemoteConfig(config) {
2107
- const dir = join11(REMOTE_CONFIG_FILE, "..");
2108
- if (!existsSync13(dir)) mkdirSync3(dir, { recursive: true });
2109
- writeFileSync6(REMOTE_CONFIG_FILE, JSON.stringify(config, null, 2));
2691
+ const dir = join13(REMOTE_CONFIG_FILE, "..");
2692
+ if (!existsSync15(dir)) mkdirSync3(dir, { recursive: true });
2693
+ writeFileSync7(REMOTE_CONFIG_FILE, JSON.stringify(config, null, 2));
2110
2694
  }
2111
2695
  var OAUTH_CLIENT_ID = Buffer.from(
2112
2696
  "MjM5NDk1OTI0Nzk4LTJtZWFhaTllcjZybTR1bnN0bW4zZmRldHRqZHM2bGJjLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29t",
@@ -2196,8 +2780,8 @@ function waitForOAuthCallback(codeVerifier) {
2196
2780
  }
2197
2781
  async function remoteLogin(_options) {
2198
2782
  const config = loadRemoteConfig();
2199
- console.log(chalk10.cyan.bold("\n Remote Monitoring Login\n"));
2200
- console.log(chalk10.gray(" Opening browser for Google sign-in...\n"));
2783
+ console.log(chalk12.cyan.bold("\n Remote Monitoring Login\n"));
2784
+ console.log(chalk12.gray(" Opening browser for Google sign-in...\n"));
2201
2785
  const codeVerifier = generateCodeVerifier();
2202
2786
  const codeChallenge = generateCodeChallenge(codeVerifier);
2203
2787
  const authUrl = OAUTH_AUTH_ENDPOINT + "?" + new URLSearchParams({
@@ -2217,11 +2801,11 @@ async function remoteLogin(_options) {
2217
2801
  idToken = result.idToken;
2218
2802
  email = result.email;
2219
2803
  } catch (err) {
2220
- console.log(chalk10.red(` ${String(err)}`));
2804
+ console.log(chalk12.red(` ${String(err)}`));
2221
2805
  await trackCommand("remote login", false, getVersion());
2222
2806
  return;
2223
2807
  }
2224
- console.log(chalk10.gray(" Registering this machine..."));
2808
+ console.log(chalk12.gray(" Registering this machine..."));
2225
2809
  try {
2226
2810
  const host = hostname();
2227
2811
  const os = process.platform + "/" + process.arch;
@@ -2239,7 +2823,7 @@ async function remoteLogin(_options) {
2239
2823
  clearTimeout(timer);
2240
2824
  if (!res.ok) {
2241
2825
  const err = await res.text();
2242
- console.log(chalk10.red(` Registration failed: ${res.status} ${err}`));
2826
+ console.log(chalk12.red(` Registration failed: ${res.status} ${err}`));
2243
2827
  return;
2244
2828
  }
2245
2829
  const data = await res.json();
@@ -2248,15 +2832,15 @@ async function remoteLogin(_options) {
2248
2832
  config.enabled = true;
2249
2833
  config.reportUrl = REMOTE_API_URL + "/v1/report";
2250
2834
  saveRemoteConfig(config);
2251
- console.log(chalk10.green.bold(`
2835
+ console.log(chalk12.green.bold(`
2252
2836
  Logged in as ${email}`));
2253
- console.log(chalk10.gray(` Machine registered: ${host}`));
2837
+ console.log(chalk12.gray(` Machine registered: ${host}`));
2254
2838
  console.log(
2255
- chalk10.gray(" Remote monitoring ready. Run: openclaw-cli remote enable\n")
2839
+ chalk12.gray(" Remote monitoring ready. Run: openclaw-cli remote enable\n")
2256
2840
  );
2257
2841
  await trackCommand("remote login", true, getVersion());
2258
2842
  } catch (err) {
2259
- console.log(chalk10.red(` Error: ${err}`));
2843
+ console.log(chalk12.red(` Error: ${err}`));
2260
2844
  await trackCommand("remote login", false, getVersion());
2261
2845
  }
2262
2846
  }
@@ -2264,47 +2848,47 @@ async function remoteEnable(_options) {
2264
2848
  const config = loadRemoteConfig();
2265
2849
  if (!config.machineToken) {
2266
2850
  console.log(
2267
- chalk10.red(" \u2717 Not logged in. Run: openclaw-cli remote login")
2851
+ chalk12.red(" \u2717 Not logged in. Run: openclaw-cli remote login")
2268
2852
  );
2269
2853
  await trackCommand("remote enable", false, getVersion());
2270
2854
  return;
2271
2855
  }
2272
2856
  config.enabled = true;
2273
2857
  saveRemoteConfig(config);
2274
- console.log(chalk10.green(" Remote reporting enabled."));
2858
+ console.log(chalk12.green(" Remote reporting enabled."));
2275
2859
  await trackCommand("remote enable", true, getVersion());
2276
2860
  }
2277
2861
  async function remoteDisable(_options) {
2278
2862
  const config = loadRemoteConfig();
2279
2863
  config.enabled = false;
2280
2864
  saveRemoteConfig(config);
2281
- console.log(chalk10.yellow(" Remote reporting disabled."));
2865
+ console.log(chalk12.yellow(" Remote reporting disabled."));
2282
2866
  await trackCommand("remote disable", true, getVersion());
2283
2867
  }
2284
2868
  async function remoteStatus(_options) {
2285
2869
  await trackCommand("remote status", true, getVersion());
2286
2870
  const config = loadRemoteConfig();
2287
- console.log(chalk10.cyan.bold("\n Remote Monitoring Status\n"));
2871
+ console.log(chalk12.cyan.bold("\n Remote Monitoring Status\n"));
2288
2872
  console.log(
2289
- ` Enabled: ${config.enabled ? chalk10.green("yes") : chalk10.gray("no")}`
2873
+ ` Enabled: ${config.enabled ? chalk12.green("yes") : chalk12.gray("no")}`
2290
2874
  );
2291
2875
  console.log(
2292
- ` Machine ID: ${chalk10.white(config.machineId || "(none)")}`
2876
+ ` Machine ID: ${chalk12.white(config.machineId || "(none)")}`
2293
2877
  );
2294
2878
  console.log(
2295
- ` Token: ${config.machineToken ? chalk10.green("configured") : chalk10.red("not set")}`
2879
+ ` Token: ${config.machineToken ? chalk12.green("configured") : chalk12.red("not set")}`
2296
2880
  );
2297
2881
  console.log(
2298
- ` Report URL: ${chalk10.gray(config.reportUrl)}`
2882
+ ` Report URL: ${chalk12.gray(config.reportUrl)}`
2299
2883
  );
2300
2884
  console.log(
2301
- ` Last Report: ${config.lastReport ? chalk10.gray(config.lastReport) : chalk10.gray("never")}`
2885
+ ` Last Report: ${config.lastReport ? chalk12.gray(config.lastReport) : chalk12.gray("never")}`
2302
2886
  );
2303
2887
  console.log();
2304
2888
  }
2305
2889
 
2306
2890
  // src/index.ts
2307
- var _PKG_VER2 = true ? "0.7.0" : "0.2.1";
2891
+ var _PKG_VER2 = true ? "0.7.2" : "0.2.1";
2308
2892
  var version = _PKG_VER2;
2309
2893
  printFirstRunNotice();
2310
2894
  var program = new Command();
@@ -2329,6 +2913,12 @@ var gw = program.command("gateway").description("Manage the OpenClaw gateway ser
2329
2913
  addGlobalOpts(gw.command("start").description("Start the gateway")).action(gatewayStart);
2330
2914
  addGlobalOpts(gw.command("stop").description("Stop the gateway")).action(gatewayStop);
2331
2915
  addGlobalOpts(gw.command("restart").description("Restart the gateway")).action(gatewayRestart);
2916
+ addGlobalOpts(
2917
+ program.command("cost").description("Show token usage and cost summary per agent/model").option("--json", "Machine-readable JSON output").option("--days <n>", "Limit date range (default: 30)")
2918
+ ).action(showCost);
2919
+ var mcp = program.command("mcp").description("Manage local MCP (Model Context Protocol) servers");
2920
+ mcp.command("list").description("List configured MCP servers and their status").action(mcpList);
2921
+ mcp.command("status").description("Show detailed info for an MCP server").argument("<name>", "Server name").action(mcpStatus);
2332
2922
  var tele = program.command("telemetry").description("Manage anonymous usage telemetry");
2333
2923
  tele.command("on").description("Enable telemetry").action(telemetryOn);
2334
2924
  tele.command("off").description("Disable telemetry").action(telemetryOff);
@@ -2341,6 +2931,12 @@ addGlobalOpts(
2341
2931
  addGlobalOpts(
2342
2932
  mem.command("compact").description("Compact agent memory (proxies to openclaw memory compact)").option("--dry-run", "Preview without applying")
2343
2933
  ).action(memoryCompact);
2934
+ addGlobalOpts(
2935
+ mem.command("gc").description("Remove old daily memory files").option("--days <n>", "Max age in days (default: 30)").option("--force", "Skip confirmation prompt")
2936
+ ).action(memoryGc);
2937
+ addGlobalOpts(
2938
+ mem.command("export").description("Export all memory files to a single markdown file").option("-o, --output <file>", "Output file (default: stdout)")
2939
+ ).action(memoryExport);
2344
2940
  var remote = program.command("remote").description("Remote monitoring \u2014 report gateway status to openclaw-cli.app");
2345
2941
  addGlobalOpts(remote.command("login").description("Authenticate and register this machine")).action(remoteLogin);
2346
2942
  addGlobalOpts(remote.command("enable").description("Enable remote reporting")).action(remoteEnable);