@codexhost/cli-win32-arm64 0.13.0 → 0.13.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.
@@ -27737,6 +27737,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
27737
27737
  harness,
27738
27738
  sessionId: external_exports.string().min(1).max(512),
27739
27739
  project: project.nullable(),
27740
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
27741
+ title: external_exports.string().min(1).max(200).optional(),
27740
27742
  /** Models the session used, most requests first. */
27741
27743
  models: external_exports.array(model).max(16),
27742
27744
  firstAtMs: count,
@@ -27803,7 +27805,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
27803
27805
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
27804
27806
  * requests without a native session are not listed here but count everywhere else.
27805
27807
  */
27806
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
27808
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
27809
+ /**
27810
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
27811
+ * Hosts; missing is treated as no list rather than no sessions.
27812
+ */
27813
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
27807
27814
  });
27808
27815
 
27809
27816
  // ../../shared-contracts/dist/ids.js
@@ -4200,6 +4200,20 @@ import { zstdDecompressSync } from "node:zlib";
4200
4200
  // ../../harness-adapter/dist/usage-statistics.js
4201
4201
  var MAX_SESSION_ID_LENGTH = 512;
4202
4202
  var MAX_CWD_LENGTH = 4096;
4203
+ var MAX_SESSION_TITLE_LENGTH = 200;
4204
+ function usageSessionTitle(value) {
4205
+ if (typeof value !== "string")
4206
+ return void 0;
4207
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
4208
+ if (!normalized)
4209
+ return void 0;
4210
+ if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
4211
+ return normalized;
4212
+ const characters = [...normalized];
4213
+ if (characters.length <= MAX_SESSION_TITLE_LENGTH)
4214
+ return normalized;
4215
+ return `${characters.slice(0, MAX_SESSION_TITLE_LENGTH - 1).join("").trimEnd()}…`;
4216
+ }
4203
4217
  function sessionIdOk(value) {
4204
4218
  return typeof value === "string" && value.length > 0 && value.length <= MAX_SESSION_ID_LENGTH;
4205
4219
  }
@@ -4209,12 +4223,14 @@ function cwdOk(value) {
4209
4223
  function withUsageSession(entry, session) {
4210
4224
  const sessionId = sessionIdOk(session.sessionId) ? session.sessionId : void 0;
4211
4225
  const cwd = cwdOk(session.cwd) ? session.cwd : void 0;
4226
+ const sessionTitle = sessionId !== void 0 ? usageSessionTitle(session.title) : void 0;
4212
4227
  if (sessionId === void 0 && cwd === void 0)
4213
4228
  return entry;
4214
4229
  return {
4215
4230
  ...entry,
4216
4231
  ...sessionId !== void 0 ? { sessionId } : {},
4217
- ...cwd !== void 0 ? { cwd } : {}
4232
+ ...cwd !== void 0 ? { cwd } : {},
4233
+ ...sessionTitle !== void 0 ? { sessionTitle } : {}
4218
4234
  };
4219
4235
  }
4220
4236
  function usageEntryFromRequest(request, occurredAtMs) {
@@ -18904,6 +18920,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
18904
18920
  harness,
18905
18921
  sessionId: external_exports.string().min(1).max(512),
18906
18922
  project: project.nullable(),
18923
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
18924
+ title: external_exports.string().min(1).max(200).optional(),
18907
18925
  /** Models the session used, most requests first. */
18908
18926
  models: external_exports.array(model).max(16),
18909
18927
  firstAtMs: count,
@@ -18970,7 +18988,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
18970
18988
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
18971
18989
  * requests without a native session are not listed here but count everywhere else.
18972
18990
  */
18973
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
18991
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
18992
+ /**
18993
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
18994
+ * Hosts; missing is treated as no list rather than no sessions.
18995
+ */
18996
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
18974
18997
  });
18975
18998
 
18976
18999
  // ../../shared-contracts/dist/ids.js
@@ -22117,9 +22140,11 @@ async function readDshUsage(file2) {
22117
22140
  if (entries.length === 0 && line.startsWith('{"type":"session"')) {
22118
22141
  try {
22119
22142
  const header = JSON.parse(line);
22143
+ const title = usageSessionTitle(header.title ?? header.name);
22120
22144
  session = {
22121
22145
  ...typeof header.id === "string" ? { sessionId: header.id } : {},
22122
- ...typeof header.cwd === "string" ? { cwd: header.cwd } : {}
22146
+ ...typeof header.cwd === "string" ? { cwd: header.cwd } : {},
22147
+ ...title ? { title } : {}
22123
22148
  };
22124
22149
  } catch {
22125
22150
  }
@@ -384,6 +384,20 @@ import path4 from "node:path";
384
384
  import { createInterface } from "node:readline";
385
385
  var MAX_SESSION_ID_LENGTH = 512;
386
386
  var MAX_CWD_LENGTH = 4096;
387
+ var MAX_SESSION_TITLE_LENGTH = 200;
388
+ function usageSessionTitle(value) {
389
+ if (typeof value !== "string")
390
+ return void 0;
391
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
392
+ if (!normalized)
393
+ return void 0;
394
+ if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
395
+ return normalized;
396
+ const characters = [...normalized];
397
+ if (characters.length <= MAX_SESSION_TITLE_LENGTH)
398
+ return normalized;
399
+ return `${characters.slice(0, MAX_SESSION_TITLE_LENGTH - 1).join("").trimEnd()}…`;
400
+ }
387
401
  function sessionIdOk(value) {
388
402
  return typeof value === "string" && value.length > 0 && value.length <= MAX_SESSION_ID_LENGTH;
389
403
  }
@@ -393,12 +407,14 @@ function cwdOk(value) {
393
407
  function withUsageSession(entry, session) {
394
408
  const sessionId = sessionIdOk(session.sessionId) ? session.sessionId : void 0;
395
409
  const cwd = cwdOk(session.cwd) ? session.cwd : void 0;
410
+ const sessionTitle = sessionId !== void 0 ? usageSessionTitle(session.title) : void 0;
396
411
  if (sessionId === void 0 && cwd === void 0)
397
412
  return entry;
398
413
  return {
399
414
  ...entry,
400
415
  ...sessionId !== void 0 ? { sessionId } : {},
401
- ...cwd !== void 0 ? { cwd } : {}
416
+ ...cwd !== void 0 ? { cwd } : {},
417
+ ...sessionTitle !== void 0 ? { sessionTitle } : {}
402
418
  };
403
419
  }
404
420
  async function jsonlUsageSources(root, maxDepth, signal) {
@@ -464,12 +480,18 @@ function count(value) {
464
480
  function grokHome(environment) {
465
481
  return environment.GROK_HOME || path5.join(environment.HOME || os2.homedir(), ".grok");
466
482
  }
467
- async function forkedAtMs(directory) {
483
+ async function grokSummary(directory) {
468
484
  try {
469
485
  const summary = JSON.parse(await readFile(path5.join(directory, "summary.json"), "utf8"));
470
- return isRecord(summary) && typeof summary.parent_session_id === "string" ? nativeTimeMs(summary.created_at) : null;
486
+ if (!isRecord(summary))
487
+ return { forkedAt: null };
488
+ const title = usageSessionTitle(summary.generated_title) ?? usageSessionTitle(summary.session_summary);
489
+ return {
490
+ forkedAt: typeof summary.parent_session_id === "string" ? nativeTimeMs(summary.created_at) : null,
491
+ ...title ? { title } : {}
492
+ };
471
493
  } catch {
472
- return null;
494
+ return { forkedAt: null };
473
495
  }
474
496
  }
475
497
  function grokSession(file2) {
@@ -483,12 +505,18 @@ function grokSession(file2) {
483
505
  return { sessionId: path5.basename(directory), cwd };
484
506
  }
485
507
  async function readGrokUsage(file2, signal) {
486
- const forkedAt = await forkedAtMs(path5.dirname(file2));
508
+ const summary = await grokSummary(path5.dirname(file2));
509
+ const forkedAt = summary.forkedAt;
510
+ let title = summary.title;
487
511
  const session = grokSession(file2);
488
512
  const entries = [];
489
- for await (const line of jsonlRecords(file2, '"turn_completed"', signal)) {
513
+ for await (const line of jsonlRecords(file2, '"sessionUpdate"', signal)) {
490
514
  const params = isRecord(line.params) ? line.params : {};
491
515
  const update = isRecord(params.update) ? params.update : {};
516
+ if (!title && update.sessionUpdate === "user_message_chunk") {
517
+ title = usageSessionTitle(isRecord(update.content) ? update.content.text : void 0);
518
+ continue;
519
+ }
492
520
  const usage = isRecord(update.usage) ? update.usage : {};
493
521
  if (update.sessionUpdate !== "turn_completed" || typeof update.prompt_id !== "string")
494
522
  continue;
@@ -519,7 +547,7 @@ async function readGrokUsage(file2, signal) {
519
547
  // A turn Grok marks incomplete has no cost of its own; it counts as free rather
520
548
  // than as a model without a price.
521
549
  ...ticks !== null ? { costUsd: ticks / USD_TICKS } : usage.usageIsIncomplete === true ? { costUsd: 0 } : {}
522
- }, session));
550
+ }, { ...session, ...title ? { title } : {} }));
523
551
  }
524
552
  }
525
553
  return entries;
@@ -15245,6 +15273,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
15245
15273
  harness,
15246
15274
  sessionId: external_exports.string().min(1).max(512),
15247
15275
  project: project.nullable(),
15276
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
15277
+ title: external_exports.string().min(1).max(200).optional(),
15248
15278
  /** Models the session used, most requests first. */
15249
15279
  models: external_exports.array(model).max(16),
15250
15280
  firstAtMs: count2,
@@ -15311,7 +15341,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
15311
15341
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
15312
15342
  * requests without a native session are not listed here but count everywhere else.
15313
15343
  */
15314
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
15344
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
15345
+ /**
15346
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
15347
+ * Hosts; missing is treated as no list rather than no sessions.
15348
+ */
15349
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
15315
15350
  });
15316
15351
 
15317
15352
  // ../../shared-contracts/dist/ids.js
@@ -1138,10 +1138,10 @@ function mergeDefs(...defs) {
1138
1138
  function cloneDef(schema) {
1139
1139
  return mergeDefs(schema._zod.def);
1140
1140
  }
1141
- function getElementAtPath(obj, path8) {
1142
- if (!path8)
1141
+ function getElementAtPath(obj, path9) {
1142
+ if (!path9)
1143
1143
  return obj;
1144
- return path8.reduce((acc, key) => acc?.[key], obj);
1144
+ return path9.reduce((acc, key) => acc?.[key], obj);
1145
1145
  }
1146
1146
  function promiseAllObject(promisesObj) {
1147
1147
  const keys = Object.keys(promisesObj);
@@ -1550,11 +1550,11 @@ function explicitlyAborted(x, startIndex = 0) {
1550
1550
  }
1551
1551
  return false;
1552
1552
  }
1553
- function prefixIssues(path8, issues) {
1553
+ function prefixIssues(path9, issues) {
1554
1554
  return issues.map((iss) => {
1555
1555
  var _a3;
1556
1556
  (_a3 = iss).path ?? (_a3.path = []);
1557
- iss.path.unshift(path8);
1557
+ iss.path.unshift(path9);
1558
1558
  return iss;
1559
1559
  });
1560
1560
  }
@@ -1701,16 +1701,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1701
1701
  }
1702
1702
  function formatError(error51, mapper = (issue2) => issue2.message) {
1703
1703
  const fieldErrors = { _errors: [] };
1704
- const processError = (error52, path8 = []) => {
1704
+ const processError = (error52, path9 = []) => {
1705
1705
  for (const issue2 of error52.issues) {
1706
1706
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1707
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1707
+ issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1708
1708
  } else if (issue2.code === "invalid_key") {
1709
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1709
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1710
1710
  } else if (issue2.code === "invalid_element") {
1711
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1711
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1712
1712
  } else {
1713
- const fullpath = [...path8, ...issue2.path];
1713
+ const fullpath = [...path9, ...issue2.path];
1714
1714
  if (fullpath.length === 0) {
1715
1715
  fieldErrors._errors.push(mapper(issue2));
1716
1716
  } else {
@@ -1737,17 +1737,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1737
1737
  }
1738
1738
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1739
1739
  const result = { errors: [] };
1740
- const processError = (error52, path8 = []) => {
1740
+ const processError = (error52, path9 = []) => {
1741
1741
  var _a3, _b;
1742
1742
  for (const issue2 of error52.issues) {
1743
1743
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1744
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1744
+ issue2.errors.map((issues) => processError({ issues }, [...path9, ...issue2.path]));
1745
1745
  } else if (issue2.code === "invalid_key") {
1746
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1746
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1747
1747
  } else if (issue2.code === "invalid_element") {
1748
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1748
+ processError({ issues: issue2.issues }, [...path9, ...issue2.path]);
1749
1749
  } else {
1750
- const fullpath = [...path8, ...issue2.path];
1750
+ const fullpath = [...path9, ...issue2.path];
1751
1751
  if (fullpath.length === 0) {
1752
1752
  result.errors.push(mapper(issue2));
1753
1753
  continue;
@@ -1779,8 +1779,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1779
1779
  }
1780
1780
  function toDotPath(_path) {
1781
1781
  const segs = [];
1782
- const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1783
- for (const seg of path8) {
1782
+ const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1783
+ for (const seg of path9) {
1784
1784
  if (typeof seg === "number")
1785
1785
  segs.push(`[${seg}]`);
1786
1786
  else if (typeof seg === "symbol")
@@ -14472,13 +14472,13 @@ function resolveRef(ref, ctx) {
14472
14472
  if (!ref.startsWith("#")) {
14473
14473
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14474
14474
  }
14475
- const path8 = ref.slice(1).split("/").filter(Boolean);
14476
- if (path8.length === 0) {
14475
+ const path9 = ref.slice(1).split("/").filter(Boolean);
14476
+ if (path9.length === 0) {
14477
14477
  return ctx.rootSchema;
14478
14478
  }
14479
14479
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14480
- if (path8[0] === defsKey) {
14481
- const key = path8[1];
14480
+ if (path9[0] === defsKey) {
14481
+ const key = path9[1];
14482
14482
  if (!key || !ctx.defs[key]) {
14483
14483
  throw new Error(`Reference not found: ${ref}`);
14484
14484
  }
@@ -15043,6 +15043,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
15043
15043
  harness,
15044
15044
  sessionId: external_exports.string().min(1).max(512),
15045
15045
  project: project.nullable(),
15046
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
15047
+ title: external_exports.string().min(1).max(200).optional(),
15046
15048
  /** Models the session used, most requests first. */
15047
15049
  models: external_exports.array(model).max(16),
15048
15050
  firstAtMs: count,
@@ -15109,7 +15111,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
15109
15111
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
15110
15112
  * requests without a native session are not listed here but count everywhere else.
15111
15113
  */
15112
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
15114
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
15115
+ /**
15116
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
15117
+ * Hosts; missing is treated as no list rather than no sessions.
15118
+ */
15119
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
15113
15120
  });
15114
15121
 
15115
15122
  // ../../shared-contracts/dist/ids.js
@@ -18003,14 +18010,14 @@ function gatewayDiff(text2) {
18003
18010
  if (!text2 || text2.length > 1024 * 1024)
18004
18011
  return [];
18005
18012
  const result = [];
18006
- let path8 = "";
18013
+ let path9 = "";
18007
18014
  let inHunk = false;
18008
18015
  let oldLines = [], newLines = [];
18009
18016
  const flush = () => {
18010
- if (path8)
18017
+ if (path9)
18011
18018
  result.push({
18012
18019
  type: "diff",
18013
- path: path8,
18020
+ path: path9,
18014
18021
  oldText: oldLines.join("\n"),
18015
18022
  newText: newLines.join("\n")
18016
18023
  });
@@ -18023,24 +18030,24 @@ function gatewayDiff(text2) {
18023
18030
  if (header) {
18024
18031
  flush();
18025
18032
  inHunk = false;
18026
- path8 = (header[2] === "/dev/null" ? header[1] ?? "" : header[2] ?? "").replace(/^[ab]\//u, "");
18033
+ path9 = (header[2] === "/dev/null" ? header[1] ?? "" : header[2] ?? "").replace(/^[ab]\//u, "");
18027
18034
  continue;
18028
18035
  }
18029
18036
  if (line.startsWith("--- ") && !inHunk) {
18030
18037
  flush();
18031
- path8 = line.slice(4).replace(/^a\//u, "");
18038
+ path9 = line.slice(4).replace(/^a\//u, "");
18032
18039
  } else if (line.startsWith("+++ ") && !inHunk) {
18033
18040
  const next = line.slice(4);
18034
18041
  if (next !== "/dev/null")
18035
- path8 = next.replace(/^b\//u, "");
18042
+ path9 = next.replace(/^b\//u, "");
18036
18043
  } else if (line.startsWith("@@")) {
18037
18044
  inHunk = true;
18038
18045
  continue;
18039
- } else if (path8 && line.startsWith("-"))
18046
+ } else if (path9 && line.startsWith("-"))
18040
18047
  oldLines.push(line.slice(1));
18041
- else if (path8 && line.startsWith("+"))
18048
+ else if (path9 && line.startsWith("+"))
18042
18049
  newLines.push(line.slice(1));
18043
- else if (path8 && line.startsWith(" ")) {
18050
+ else if (path9 && line.startsWith(" ")) {
18044
18051
  oldLines.push(line.slice(1));
18045
18052
  newLines.push(line.slice(1));
18046
18053
  }
@@ -18464,8 +18471,150 @@ var HermesGatewaySessionTransport = class {
18464
18471
  }
18465
18472
  };
18466
18473
 
18467
- // dist/gateway-open.js
18474
+ // dist/usage-statistics.js
18475
+ import os3 from "node:os";
18468
18476
  import path7 from "node:path";
18477
+ import { lstat } from "node:fs/promises";
18478
+
18479
+ // ../../harness-adapter/dist/usage-statistics.js
18480
+ var MAX_SESSION_ID_LENGTH = 512;
18481
+ var MAX_CWD_LENGTH = 4096;
18482
+ var MAX_SESSION_TITLE_LENGTH = 200;
18483
+ function usageSessionTitle(value) {
18484
+ if (typeof value !== "string")
18485
+ return void 0;
18486
+ const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
18487
+ if (!normalized)
18488
+ return void 0;
18489
+ if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
18490
+ return normalized;
18491
+ const characters = [...normalized];
18492
+ if (characters.length <= MAX_SESSION_TITLE_LENGTH)
18493
+ return normalized;
18494
+ return `${characters.slice(0, MAX_SESSION_TITLE_LENGTH - 1).join("").trimEnd()}…`;
18495
+ }
18496
+ function sessionIdOk(value) {
18497
+ return typeof value === "string" && value.length > 0 && value.length <= MAX_SESSION_ID_LENGTH;
18498
+ }
18499
+ function cwdOk(value) {
18500
+ return typeof value === "string" && value.length > 0 && value.length <= MAX_CWD_LENGTH && !value.includes("\0") && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value) || value.startsWith("\\\\"));
18501
+ }
18502
+ function withUsageSession(entry, session) {
18503
+ const sessionId = sessionIdOk(session.sessionId) ? session.sessionId : void 0;
18504
+ const cwd = cwdOk(session.cwd) ? session.cwd : void 0;
18505
+ const sessionTitle = sessionId !== void 0 ? usageSessionTitle(session.title) : void 0;
18506
+ if (sessionId === void 0 && cwd === void 0)
18507
+ return entry;
18508
+ return {
18509
+ ...entry,
18510
+ ...sessionId !== void 0 ? { sessionId } : {},
18511
+ ...cwd !== void 0 ? { cwd } : {},
18512
+ ...sessionTitle !== void 0 ? { sessionTitle } : {}
18513
+ };
18514
+ }
18515
+ function usageEntryFromRequest(request, occurredAtMs) {
18516
+ if (!Number.isSafeInteger(occurredAtMs) || occurredAtMs <= 0)
18517
+ return null;
18518
+ return {
18519
+ id: request.requestId,
18520
+ occurredAtMs,
18521
+ ...request.model !== void 0 ? { model: request.model } : {},
18522
+ inputTokens: request.inputTokens,
18523
+ ...request.cachedInputTokens !== void 0 ? { cachedInputTokens: request.cachedInputTokens } : {},
18524
+ ...request.cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens: request.cacheWriteInputTokens } : {},
18525
+ ...request.cacheWrite1hInputTokens !== void 0 ? { cacheWrite1hInputTokens: request.cacheWrite1hInputTokens } : {},
18526
+ outputTokens: request.outputTokens,
18527
+ ...request.reasoningOutputTokens !== void 0 ? { reasoningOutputTokens: request.reasoningOutputTokens } : {}
18528
+ };
18529
+ }
18530
+
18531
+ // dist/usage-statistics.js
18532
+ function hermesStateDatabasePath(environment) {
18533
+ const home = environment.HOME || environment.USERPROFILE || os3.homedir();
18534
+ const configured = environment.HERMES_HOME;
18535
+ return path7.resolve(configured ? path7.join(configured, "state.db") : path7.join(home, ".hermes", "state.db"));
18536
+ }
18537
+ async function fingerprint(file2) {
18538
+ const info = await lstat(file2).catch(() => null);
18539
+ if (!info?.isFile())
18540
+ return null;
18541
+ const wal = await lstat(`${file2}-wal`).catch(() => null);
18542
+ return `${info.ino}:${info.size}:${info.mtimeMs}:${wal ? `${wal.size}:${wal.mtimeMs}` : "-"}`;
18543
+ }
18544
+ function tokenCount(value) {
18545
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
18546
+ }
18547
+ function hermesUsageEntry(row) {
18548
+ const apiCalls = tokenCount(row.api_call_count) ? row.api_call_count : 0;
18549
+ const input = tokenCount(row.input_tokens) ? row.input_tokens : 0;
18550
+ const output = tokenCount(row.output_tokens) ? row.output_tokens : 0;
18551
+ const cacheRead = tokenCount(row.cache_read_tokens) ? row.cache_read_tokens : 0;
18552
+ const cacheWrite = tokenCount(row.cache_write_tokens) ? row.cache_write_tokens : 0;
18553
+ const reasoning = tokenCount(row.reasoning_tokens) ? row.reasoning_tokens : 0;
18554
+ if (apiCalls === 0 && input === 0 && output === 0 && cacheRead === 0 && cacheWrite === 0) {
18555
+ return null;
18556
+ }
18557
+ const id = typeof row.id === "string" && row.id.length > 0 ? row.id : null;
18558
+ const epochSeconds = (value) => {
18559
+ if (typeof value !== "number" || !Number.isFinite(value))
18560
+ return null;
18561
+ const ms = Math.floor(value * 1e3);
18562
+ return Number.isSafeInteger(ms) && !Number.isNaN(new Date(ms).getTime()) ? ms : null;
18563
+ };
18564
+ const at = epochSeconds(row.last_activity_at) ?? epochSeconds(row.started_at);
18565
+ if (id === null || at === null)
18566
+ return null;
18567
+ const request = {
18568
+ requestId: id,
18569
+ ...typeof row.model === "string" && row.model.length > 0 ? { model: row.model } : {},
18570
+ inputTokens: input + cacheRead + cacheWrite,
18571
+ outputTokens: output,
18572
+ ...reasoning > 0 ? { reasoningOutputTokens: reasoning } : {},
18573
+ // Both buckets exist whenever either does: the writer records them as a pair.
18574
+ ...cacheRead > 0 || cacheWrite > 0 ? { cachedInputTokens: cacheRead, cacheWriteInputTokens: cacheWrite } : {}
18575
+ };
18576
+ const entry = usageEntryFromRequest(request, at);
18577
+ if (!entry)
18578
+ return null;
18579
+ return withUsageSession(entry, {
18580
+ sessionId: id,
18581
+ cwd: typeof row.cwd === "string" ? row.cwd : void 0,
18582
+ title: usageSessionTitle(row.title ?? row.display_name)
18583
+ });
18584
+ }
18585
+ var SESSIONS_QUERY = `
18586
+ SELECT id, model, cwd, title, display_name, started_at, last_activity_at,
18587
+ api_call_count, input_tokens, output_tokens, cache_read_tokens,
18588
+ cache_write_tokens, reasoning_tokens
18589
+ FROM sessions`;
18590
+ async function readHermesUsage(file2) {
18591
+ const { DatabaseSync } = await import("node:sqlite");
18592
+ const database = new DatabaseSync(file2, { readOnly: true });
18593
+ try {
18594
+ const entries = [];
18595
+ for (const row of database.prepare(SESSIONS_QUERY).iterate()) {
18596
+ const entry = hermesUsageEntry(row);
18597
+ if (entry)
18598
+ entries.push(entry);
18599
+ }
18600
+ return entries;
18601
+ } finally {
18602
+ database.close();
18603
+ }
18604
+ }
18605
+ function createHermesUsageStatistics(environment) {
18606
+ return Object.freeze({
18607
+ async listSources() {
18608
+ const file2 = hermesStateDatabasePath(environment);
18609
+ const stamp = await fingerprint(file2);
18610
+ return stamp ? [{ id: file2, fingerprint: stamp }] : [];
18611
+ },
18612
+ readSource: (id) => readHermesUsage(id)
18613
+ });
18614
+ }
18615
+
18616
+ // dist/gateway-open.js
18617
+ import path8 from "node:path";
18469
18618
  import { realpath } from "node:fs/promises";
18470
18619
 
18471
18620
  // dist/hermes-session.js
@@ -18675,16 +18824,16 @@ var Diff = class {
18675
18824
  }
18676
18825
  }
18677
18826
  }
18678
- addToPath(path8, added, removed, oldPosInc, options) {
18679
- const last = path8.lastComponent;
18827
+ addToPath(path9, added, removed, oldPosInc, options) {
18828
+ const last = path9.lastComponent;
18680
18829
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
18681
18830
  return {
18682
- oldPos: path8.oldPos + oldPosInc,
18831
+ oldPos: path9.oldPos + oldPosInc,
18683
18832
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
18684
18833
  };
18685
18834
  } else {
18686
18835
  return {
18687
- oldPos: path8.oldPos + oldPosInc,
18836
+ oldPos: path9.oldPos + oldPosInc,
18688
18837
  lastComponent: { count: 1, added, removed, previousComponent: last }
18689
18838
  };
18690
18839
  }
@@ -18999,8 +19148,8 @@ function hermesFileChanges(update) {
18999
19148
  for (const block of update.content ?? []) {
19000
19149
  if (block.type !== "diff")
19001
19150
  continue;
19002
- const { path: path8, oldText, newText } = block;
19003
- if (!path8.trim() || /[\0\r\n]/u.test(path8) || typeof newText !== "string")
19151
+ const { path: path9, oldText, newText } = block;
19152
+ if (!path9.trim() || /[\0\r\n]/u.test(path9) || typeof newText !== "string")
19004
19153
  continue;
19005
19154
  if (oldText === newText)
19006
19155
  continue;
@@ -19008,10 +19157,10 @@ function hermesFileChanges(update) {
19008
19157
  if (bytes > MAX_DIFF_BYTES || changes.length === MAX_DIFFS)
19009
19158
  return [];
19010
19159
  changes.push({
19011
- path: path8,
19160
+ path: path9,
19012
19161
  kind: "update",
19013
19162
  diffScope: "fragment",
19014
- unifiedDiff: createTwoFilesPatch(path8, path8, oldText ?? "", newText, "", "", {
19163
+ unifiedDiff: createTwoFilesPatch(path9, path9, oldText ?? "", newText, "", "", {
19015
19164
  context: 3
19016
19165
  })
19017
19166
  });
@@ -19814,7 +19963,7 @@ ${reason}` }
19814
19963
 
19815
19964
  // dist/gateway-open.js
19816
19965
  async function sameDirectory(left, right) {
19817
- return await realpath(left).catch(() => path7.resolve(left)) === await realpath(right).catch(() => path7.resolve(right));
19966
+ return await realpath(left).catch(() => path8.resolve(left)) === await realpath(right).catch(() => path8.resolve(right));
19818
19967
  }
19819
19968
  var gatewayCapabilities = {
19820
19969
  configuration: {
@@ -19956,8 +20105,10 @@ var HermesAdapter = class {
19956
20105
  #gatewayTransports = /* @__PURE__ */ new Set();
19957
20106
  #gatewayProbes = /* @__PURE__ */ new Map();
19958
20107
  #openingNativeIds = /* @__PURE__ */ new Set();
20108
+ usageStatistics;
19959
20109
  constructor(options = {}) {
19960
20110
  this.#options = options;
20111
+ this.usageStatistics = createHermesUsageStatistics(options.environment ?? process.env);
19961
20112
  }
19962
20113
  async inspect(input = {}) {
19963
20114
  const cwd = input.cwd ?? process.cwd();
@@ -15163,6 +15163,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
15163
15163
  harness,
15164
15164
  sessionId: external_exports.string().min(1).max(512),
15165
15165
  project: project.nullable(),
15166
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
15167
+ title: external_exports.string().min(1).max(200).optional(),
15166
15168
  /** Models the session used, most requests first. */
15167
15169
  models: external_exports.array(model).max(16),
15168
15170
  firstAtMs: count,
@@ -15229,7 +15231,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
15229
15231
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
15230
15232
  * requests without a native session are not listed here but count everywhere else.
15231
15233
  */
15232
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
15234
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
15235
+ /**
15236
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
15237
+ * Hosts; missing is treated as no list rather than no sessions.
15238
+ */
15239
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
15233
15240
  });
15234
15241
 
15235
15242
  // ../../shared-contracts/dist/ids.js
@@ -15022,6 +15022,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
15022
15022
  harness,
15023
15023
  sessionId: external_exports.string().min(1).max(512),
15024
15024
  project: project.nullable(),
15025
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
15026
+ title: external_exports.string().min(1).max(200).optional(),
15025
15027
  /** Models the session used, most requests first. */
15026
15028
  models: external_exports.array(model).max(16),
15027
15029
  firstAtMs: count,
@@ -15088,7 +15090,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
15088
15090
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
15089
15091
  * requests without a native session are not listed here but count everywhere else.
15090
15092
  */
15091
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
15093
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
15094
+ /**
15095
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
15096
+ * Hosts; missing is treated as no list rather than no sessions.
15097
+ */
15098
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
15092
15099
  });
15093
15100
 
15094
15101
  // ../../shared-contracts/dist/ids.js