@mutmutco/hub 3.139.0 → 3.139.1

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.
Files changed (2) hide show
  1. package/dist/index.cjs +168 -27
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -21,17 +21,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ enumerateSurfaces: () => enumerateSurfaces,
25
+ hermesArm: () => hermesArm,
26
+ hermesHome: () => hermesHome,
24
27
  hubStatus: () => hubStatus,
25
28
  launcherVbs: () => launcherVbs,
26
29
  localStartBoundary: () => localStartBoundary,
27
30
  main: () => main,
28
31
  ownVersion: () => ownVersion,
32
+ probeHermesInstallation: () => probeHermesInstallation,
29
33
  schedulerStatus: () => schedulerStatus,
30
34
  taskXml: () => taskXml
31
35
  });
32
36
  module.exports = __toCommonJS(index_exports);
33
- var import_node_fs15 = require("node:fs");
34
- var import_node_path12 = require("node:path");
37
+ var import_node_fs16 = require("node:fs");
38
+ var import_node_path13 = require("node:path");
35
39
 
36
40
  // src/state.ts
37
41
  var import_node_fs = require("node:fs");
@@ -321,6 +325,11 @@ function kimiHome(env = process.env) {
321
325
  function jervcodeAgentDir(env = process.env) {
322
326
  return env.MMI_UPDATER_JERVCODE_AGENT_DIR?.trim() || env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".jerv", "agent");
323
327
  }
328
+ function hermesHome(env = process.env, platform = process.platform) {
329
+ if (env.HERMES_HOME?.trim()) return env.HERMES_HOME.trim();
330
+ if (platform === "win32") return (0, import_node_path3.join)(env.LOCALAPPDATA?.trim() || (0, import_node_path3.join)((0, import_node_os2.homedir)(), "AppData", "Local"), "hermes");
331
+ return (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".hermes");
332
+ }
324
333
  function enumerateSurfaces(env = process.env) {
325
334
  const home = (0, import_node_os2.homedir)();
326
335
  const codexHome = env.CODEX_HOME || (0, import_node_path3.join)(home, ".codex");
@@ -333,7 +342,10 @@ function enumerateSurfaces(env = process.env) {
333
342
  // itself — so a machine running Kimi WITHOUT the plugin enumerated as "no Kimi" and the arm
334
343
  // could never make the first install. The plugin's absence is a converge action, not a skip.
335
344
  { id: "kimi", marker: kimiHome(env) },
336
- { id: "jervcode", marker: (0, import_node_path3.join)(jervcodeAgentDir(env), "settings.json") }
345
+ { id: "jervcode", marker: (0, import_node_path3.join)(jervcodeAgentDir(env), "settings.json") },
346
+ // The host root is the marker, not plugins/mmi: an installed Hermes without MMI must be
347
+ // discovered so its native plugin tree can be converged for the first time.
348
+ { id: "hermes", marker: hermesHome(env) }
337
349
  ].map((probe) => ({ ...probe, present: (0, import_node_fs4.existsSync)(probe.marker) }));
338
350
  }
339
351
 
@@ -1287,10 +1299,133 @@ function jervcodeArm(options) {
1287
1299
  };
1288
1300
  }
1289
1301
 
1290
- // src/reap.ts
1291
- var import_node_child_process8 = require("node:child_process");
1302
+ // src/arm-hermes.ts
1292
1303
  var import_node_fs12 = require("node:fs");
1293
1304
  var import_node_path10 = require("node:path");
1305
+ var PACKAGE2 = "@mutmutco/hermes-plugin";
1306
+ var MANIFEST2 = "plugin.yaml";
1307
+ var TREE_MARKERS2 = [MANIFEST2, "__init__.py", "skills"];
1308
+ function yamlVersion(root) {
1309
+ try {
1310
+ const text = (0, import_node_fs12.readFileSync)((0, import_node_path10.join)(root, MANIFEST2), "utf8");
1311
+ try {
1312
+ const version = JSON.parse(text).version;
1313
+ if (typeof version === "string" && version.trim()) return version.trim();
1314
+ } catch {
1315
+ }
1316
+ const match = /^version:\s*["']?([^\s"'#]+)["']?\s*(?:#.*)?$/m.exec(text);
1317
+ return match?.[1] ?? null;
1318
+ } catch {
1319
+ return null;
1320
+ }
1321
+ }
1322
+ function treeHealthy3(root) {
1323
+ return TREE_MARKERS2.slice(0, 2).every((file) => (0, import_node_fs12.existsSync)((0, import_node_path10.join)(root, file))) && (() => {
1324
+ try {
1325
+ return (0, import_node_fs12.statSync)((0, import_node_path10.join)(root, "skills")).isDirectory();
1326
+ } catch {
1327
+ return false;
1328
+ }
1329
+ })();
1330
+ }
1331
+ function packageIdentity(root) {
1332
+ try {
1333
+ return JSON.parse((0, import_node_fs12.readFileSync)((0, import_node_path10.join)(root, "package.json"), "utf8")).name === PACKAGE2;
1334
+ } catch {
1335
+ return false;
1336
+ }
1337
+ }
1338
+ function probeHermesInstallation(env = process.env) {
1339
+ const location = (0, import_node_path10.join)(hermesHome(env), "plugins", "mmi");
1340
+ const version = yamlVersion(location);
1341
+ return { version, location, detail: version ? "installed Hermes plugin manifest" : "installed Hermes plugin manifest was unreadable" };
1342
+ }
1343
+ function mmiOwned2(root) {
1344
+ return packageIdentity(root);
1345
+ }
1346
+ function discard2(path) {
1347
+ try {
1348
+ (0, import_node_fs12.rmSync)(path, { recursive: true, force: true });
1349
+ } catch {
1350
+ }
1351
+ }
1352
+ function message2(error) {
1353
+ return String(error?.message ?? error).replace(/\s+/g, " ").slice(0, 200);
1354
+ }
1355
+ function hermesArm(options) {
1356
+ const env = options.env ?? process.env;
1357
+ const home = hermesHome(env);
1358
+ const parent = (0, import_node_path10.join)(home, "plugins");
1359
+ const live = (0, import_node_path10.join)(parent, "mmi");
1360
+ const installed = yamlVersion(live);
1361
+ const result = (from, to, verdict, detail) => ({
1362
+ surface: "hermes",
1363
+ from,
1364
+ to,
1365
+ verdict,
1366
+ detail
1367
+ });
1368
+ if (!(0, import_node_fs12.existsSync)(home)) return result(null, options.target, "skip", `absent (${home}) \u2014 skipped without writes`);
1369
+ if ((0, import_node_fs12.existsSync)(live) && !mmiOwned2(live)) {
1370
+ return result(installed, options.target, "defer", `${live} carries no ${PACKAGE2} package identity \u2014 refusing to displace an unmanaged Hermes mmi plugin`);
1371
+ }
1372
+ if (installed && compareSemver(installed, options.target) > 0) return result(installed, installed, "skip", `installed ${installed} is above candidate ${options.target} (monotonic)`);
1373
+ const highWater = journalHighWater(options.paths.journalPath, "hermes");
1374
+ if (highWater && compareSemver(highWater, options.target) > 0) return result(installed, highWater, "skip", `journal high-water ${highWater} is above candidate ${options.target} (monotonic)`);
1375
+ if (installed === options.target && treeHealthy3(live)) return result(installed, options.target, "ok", `already at target ${options.target}`);
1376
+ if (options.dryRun) return result(installed, options.target, "ok", `dry-run: would stage ${PACKAGE2}@${options.target} and atomically switch ${installed ?? "absent"} -> ${options.target}`);
1377
+ const staged = stagePackage({ surface: "hermes", packageName: PACKAGE2, target: options.target, witness: MANIFEST2, paths: options.paths, env });
1378
+ if ("defer" in staged) return result(installed, options.target, "defer", staged.defer);
1379
+ if (yamlVersion(staged.packageRoot) !== options.target || !treeHealthy3(staged.packageRoot)) {
1380
+ return result(installed, options.target, "defer", `staged Hermes manifest is ${yamlVersion(staged.packageRoot) ?? "unreadable"} or its tree is incomplete (expected ${options.target})`);
1381
+ }
1382
+ const scratch = (0, import_node_path10.join)(home, ".mmi-updater");
1383
+ const incomingRoot = (0, import_node_path10.join)(scratch, "incoming");
1384
+ const incoming = (0, import_node_path10.join)(incomingRoot, options.target);
1385
+ const quarantine = (0, import_node_path10.join)(scratch, "quarantine", `${installed ?? "unknown"}-${Date.now()}`);
1386
+ try {
1387
+ (0, import_node_fs12.mkdirSync)(parent, { recursive: true });
1388
+ (0, import_node_fs12.mkdirSync)((0, import_node_path10.join)(scratch, "quarantine"), { recursive: true });
1389
+ discard2(incomingRoot);
1390
+ (0, import_node_fs12.cpSync)(staged.packageRoot, incoming, { recursive: true });
1391
+ } catch (error) {
1392
+ return result(installed, options.target, "defer", `cannot place incoming Hermes generation: ${message2(error)}`);
1393
+ }
1394
+ if (yamlVersion(incoming) !== options.target || !treeHealthy3(incoming)) {
1395
+ discard2(incomingRoot);
1396
+ return result(installed, options.target, "defer", "incoming Hermes generation did not reproduce the verified payload");
1397
+ }
1398
+ const displaced = (0, import_node_fs12.existsSync)(live);
1399
+ try {
1400
+ if (displaced) (0, import_node_fs12.renameSync)(live, quarantine);
1401
+ (0, import_node_fs12.renameSync)(incoming, live);
1402
+ } catch (error) {
1403
+ if (displaced && !(0, import_node_fs12.existsSync)(live)) try {
1404
+ (0, import_node_fs12.renameSync)(quarantine, live);
1405
+ } catch {
1406
+ }
1407
+ discard2(incomingRoot);
1408
+ return result(installed, options.target, "defer", `Hermes generation switch failed; previous generation retained: ${message2(error)}`);
1409
+ }
1410
+ if (yamlVersion(live) !== options.target || !treeHealthy3(live)) {
1411
+ const broken = (0, import_node_path10.join)(scratch, "rejected", `${options.target}-${Date.now()}`);
1412
+ try {
1413
+ (0, import_node_fs12.mkdirSync)((0, import_node_path10.join)(scratch, "rejected"), { recursive: true });
1414
+ (0, import_node_fs12.renameSync)(live, broken);
1415
+ if (displaced) (0, import_node_fs12.renameSync)(quarantine, live);
1416
+ } catch (error) {
1417
+ return result(installed, yamlVersion(live) ?? "unknown", "fail", `post-switch Hermes verification failed and recovery failed: ${message2(error)}`);
1418
+ }
1419
+ return result(installed, displaced ? installed ?? "unknown" : "none", "fail", `post-switch Hermes verification failed; rejected generation parked at ${broken}${displaced ? "; previous generation restored" : ""}`);
1420
+ }
1421
+ discard2(incomingRoot);
1422
+ return result(installed, options.target, "ok", `converged ${installed ?? "absent"} -> ${options.target} (staged, verified, atomically switched${displaced ? `; previous generation quarantined at ${quarantine}` : ""})`);
1423
+ }
1424
+
1425
+ // src/reap.ts
1426
+ var import_node_child_process8 = require("node:child_process");
1427
+ var import_node_fs13 = require("node:fs");
1428
+ var import_node_path11 = require("node:path");
1294
1429
  var KEEP_GENERATIONS2 = 2;
1295
1430
  var SCRATCH_AGE_MS = 24 * 60 * 6e4;
1296
1431
  var ORPHAN_MIN_AGE_MS = 10 * 6e4;
@@ -1298,7 +1433,7 @@ var SNAPSHOT_TIMEOUT_MS = 2e4;
1298
1433
  var MAX_UNWIND_ROUNDS = 4;
1299
1434
  function listDirs(path) {
1300
1435
  try {
1301
- return (0, import_node_fs12.readdirSync)(path, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1436
+ return (0, import_node_fs13.readdirSync)(path, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1302
1437
  } catch {
1303
1438
  return [];
1304
1439
  }
@@ -1306,7 +1441,7 @@ function listDirs(path) {
1306
1441
  function generationSets(root) {
1307
1442
  const children = listDirs(root);
1308
1443
  if (children.some((name) => parseSemver(name))) return [root];
1309
- return children.map((name) => (0, import_node_path10.join)(root, name)).filter((path) => listDirs(path).some((name) => parseSemver(name)));
1444
+ return children.map((name) => (0, import_node_path11.join)(root, name)).filter((path) => listDirs(path).some((name) => parseSemver(name)));
1310
1445
  }
1311
1446
  function pruneGenerations(root, category, dryRun) {
1312
1447
  let reaped = 0;
@@ -1319,7 +1454,7 @@ function pruneGenerations(root, category, dryRun) {
1319
1454
  continue;
1320
1455
  }
1321
1456
  try {
1322
- (0, import_node_fs12.rmSync)((0, import_node_path10.join)(set, version), { recursive: true, force: true });
1457
+ (0, import_node_fs13.rmSync)((0, import_node_path11.join)(set, version), { recursive: true, force: true });
1323
1458
  reaped += 1;
1324
1459
  } catch (error) {
1325
1460
  failures.push(`${version}: ${error?.code ?? error?.message ?? error}`);
@@ -1333,8 +1468,8 @@ function pruneGenerations(root, category, dryRun) {
1333
1468
  }
1334
1469
  var LEASE_STEAL_SCRATCH = /^lease\.lock\.stale-\d+$/;
1335
1470
  function atomicWriteScratch(path) {
1336
- const literal = (0, import_node_path10.basename)(path).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1337
- return { dir: (0, import_node_path10.dirname)(path), pattern: new RegExp(`^${literal}\\.tmp-\\d+$`) };
1471
+ const literal = (0, import_node_path11.basename)(path).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1472
+ return { dir: (0, import_node_path11.dirname)(path), pattern: new RegExp(`^${literal}\\.tmp-\\d+$`) };
1338
1473
  }
1339
1474
  function reapScratch(context, dryRun) {
1340
1475
  const category = "scratch";
@@ -1352,7 +1487,7 @@ function reapScratch(context, dryRun) {
1352
1487
  for (const [dir, patterns] of scanned) {
1353
1488
  let entries;
1354
1489
  try {
1355
- entries = (0, import_node_fs12.readdirSync)(dir, { withFileTypes: true });
1490
+ entries = (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true });
1356
1491
  } catch {
1357
1492
  unreadable.push(dir);
1358
1493
  continue;
@@ -1360,10 +1495,10 @@ function reapScratch(context, dryRun) {
1360
1495
  for (const entry of entries) {
1361
1496
  if (!patterns.some((pattern) => pattern.test(entry.name))) continue;
1362
1497
  if (!entry.isFile()) continue;
1363
- const path = (0, import_node_path10.join)(dir, entry.name);
1498
+ const path = (0, import_node_path11.join)(dir, entry.name);
1364
1499
  let ageMs;
1365
1500
  try {
1366
- ageMs = now - (0, import_node_fs12.statSync)(path).mtimeMs;
1501
+ ageMs = now - (0, import_node_fs13.statSync)(path).mtimeMs;
1367
1502
  } catch {
1368
1503
  continue;
1369
1504
  }
@@ -1373,7 +1508,7 @@ function reapScratch(context, dryRun) {
1373
1508
  continue;
1374
1509
  }
1375
1510
  try {
1376
- (0, import_node_fs12.rmSync)(path, { force: true });
1511
+ (0, import_node_fs13.rmSync)(path, { force: true });
1377
1512
  reaped += 1;
1378
1513
  } catch (error) {
1379
1514
  failures.push(`${entry.name}: ${error?.code ?? error?.message ?? error}`);
@@ -1675,7 +1810,7 @@ function reconcile(options) {
1675
1810
  continue;
1676
1811
  }
1677
1812
  say(`${probe.id}: converging to v${summary.target}`);
1678
- const arm = probe.id === "claude" ? claudeArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "codex" ? codexArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "kilo" ? kiloArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "kimi" ? kimiArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : probe.id === "cursor" ? cursorArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : probe.id === "jervcode" ? jervcodeArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : null;
1813
+ const arm = probe.id === "claude" ? claudeArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "codex" ? codexArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "kilo" ? kiloArm({ target: summary.target, dryRun: options.dryRun, env }) : probe.id === "kimi" ? kimiArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : probe.id === "cursor" ? cursorArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : probe.id === "jervcode" ? jervcodeArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : probe.id === "hermes" ? hermesArm({ target: summary.target, dryRun: options.dryRun, paths, env }) : null;
1679
1814
  if (arm) {
1680
1815
  summary.plugins.push(arm);
1681
1816
  summary.surfaces.push({ id: probe.id, present: true, action: `arm-${arm.verdict}` });
@@ -1708,8 +1843,8 @@ function reconcile(options) {
1708
1843
 
1709
1844
  // src/scheduler.ts
1710
1845
  var import_node_child_process9 = require("node:child_process");
1711
- var import_node_fs13 = require("node:fs");
1712
- var import_node_path11 = require("node:path");
1846
+ var import_node_fs14 = require("node:fs");
1847
+ var import_node_path12 = require("node:path");
1713
1848
  var TASK_NAME = "MMI Fleet Updater";
1714
1849
  var LAUNCHER_FILE = "reconcile-hidden.vbs";
1715
1850
  var RUN_BOUND = "PT15M";
@@ -1781,7 +1916,7 @@ function taskXml(launcherPath, workDir, userId, startBoundary) {
1781
1916
  }
1782
1917
  function readLauncher(path) {
1783
1918
  try {
1784
- return (0, import_node_fs13.readFileSync)(path, "utf8");
1919
+ return (0, import_node_fs14.readFileSync)(path, "utf8");
1785
1920
  } catch {
1786
1921
  return null;
1787
1922
  }
@@ -1833,7 +1968,7 @@ function schedulerStatus(env = process.env) {
1833
1968
  return { ok: false, supported: true, enabled: false, ...empty, detail: `"${TASK_NAME}" is not registered \u2014 run \`mmi-hub autoupdate on\`` };
1834
1969
  }
1835
1970
  const hubDist = globalDist(env, "@mutmutco/hub", "dist/index.cjs");
1836
- const launcherPath = (0, import_node_path11.join)(statePaths(env).root, LAUNCHER_FILE);
1971
+ const launcherPath = (0, import_node_path12.join)(statePaths(env).root, LAUNCHER_FILE);
1837
1972
  const info = taskRunInfo();
1838
1973
  const runInfo = info ?? empty;
1839
1974
  const fail = (detail) => ({ ok: false, supported: true, enabled: true, ...runInfo, detail });
@@ -1866,10 +2001,10 @@ function installTask(env = process.env) {
1866
2001
  const paths = ensureState(env);
1867
2002
  const userId = `${env.USERDOMAIN || env.COMPUTERNAME || ""}\\${env.USERNAME || ""}`.replace(/^\\/, "");
1868
2003
  if (!env.USERNAME) return { ok: false, detail: "cannot resolve the registering user (USERNAME unset) \u2014 the task principal must be explicit" };
1869
- const launcherPath = (0, import_node_path11.join)(paths.root, LAUNCHER_FILE);
1870
- (0, import_node_fs13.writeFileSync)(launcherPath, launcherVbs(process.execPath, hubDist), "utf8");
1871
- const xmlPath = (0, import_node_path11.join)(paths.root, "task.xml");
1872
- (0, import_node_fs13.writeFileSync)(xmlPath, "\uFEFF" + taskXml(launcherPath, paths.root, userId, localStartBoundary(/* @__PURE__ */ new Date())), "utf16le");
2004
+ const launcherPath = (0, import_node_path12.join)(paths.root, LAUNCHER_FILE);
2005
+ (0, import_node_fs14.writeFileSync)(launcherPath, launcherVbs(process.execPath, hubDist), "utf8");
2006
+ const xmlPath = (0, import_node_path12.join)(paths.root, "task.xml");
2007
+ (0, import_node_fs14.writeFileSync)(xmlPath, "\uFEFF" + taskXml(launcherPath, paths.root, userId, localStartBoundary(/* @__PURE__ */ new Date())), "utf16le");
1873
2008
  const create = schtasks(["/create", "/tn", TASK_NAME, "/xml", xmlPath, "/f"]);
1874
2009
  if (create.status !== 0) {
1875
2010
  const denied = /access is denied/i.test(create.stderr + create.stdout);
@@ -1903,16 +2038,16 @@ function uninstallTask(env = process.env) {
1903
2038
  }
1904
2039
  function dropLauncher(env) {
1905
2040
  try {
1906
- (0, import_node_fs13.rmSync)((0, import_node_path11.join)(statePaths(env).root, LAUNCHER_FILE), { force: true });
2041
+ (0, import_node_fs14.rmSync)((0, import_node_path12.join)(statePaths(env).root, LAUNCHER_FILE), { force: true });
1907
2042
  } catch {
1908
2043
  }
1909
2044
  }
1910
2045
 
1911
2046
  // src/status.ts
1912
- var import_node_fs14 = require("node:fs");
2047
+ var import_node_fs15 = require("node:fs");
1913
2048
  function readJournal(path) {
1914
2049
  try {
1915
- const events = (0, import_node_fs14.readFileSync)(path, "utf8").split("\n").filter((line) => line.trim()).map((line) => {
2050
+ const events = (0, import_node_fs15.readFileSync)(path, "utf8").split("\n").filter((line) => line.trim()).map((line) => {
1916
2051
  try {
1917
2052
  return JSON.parse(line);
1918
2053
  } catch {
@@ -1950,6 +2085,8 @@ function hubStatus(hubVersion, env = process.env, invokedPath = process.argv[1])
1950
2085
  actual.set(surface.id, probeCursorInstallation());
1951
2086
  } else if (surface.id === "jervcode") {
1952
2087
  actual.set(surface.id, probeJervcodeInstallation(env));
2088
+ } else if (surface.id === "hermes") {
2089
+ actual.set(surface.id, probeHermesInstallation(env));
1953
2090
  }
1954
2091
  }
1955
2092
  const installed = {};
@@ -2011,7 +2148,7 @@ function formatHubStatus(status) {
2011
2148
  // src/index.ts
2012
2149
  function ownVersion() {
2013
2150
  try {
2014
- return JSON.parse((0, import_node_fs15.readFileSync)((0, import_node_path12.join)(__dirname, "..", "package.json"), "utf8")).version;
2151
+ return JSON.parse((0, import_node_fs16.readFileSync)((0, import_node_path13.join)(__dirname, "..", "package.json"), "utf8")).version;
2015
2152
  } catch {
2016
2153
  return "0.0.0";
2017
2154
  }
@@ -2113,11 +2250,15 @@ if (typeof require !== "undefined" && require.main === module) {
2113
2250
  }
2114
2251
  // Annotate the CommonJS export names for ESM import in node:
2115
2252
  0 && (module.exports = {
2253
+ enumerateSurfaces,
2254
+ hermesArm,
2255
+ hermesHome,
2116
2256
  hubStatus,
2117
2257
  launcherVbs,
2118
2258
  localStartBoundary,
2119
2259
  main,
2120
2260
  ownVersion,
2261
+ probeHermesInstallation,
2121
2262
  schedulerStatus,
2122
2263
  taskXml
2123
2264
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/hub",
3
- "version": "3.139.0",
3
+ "version": "3.139.1",
4
4
  "description": "Install and maintain the MMI CLI and every present host surface from one release-gated Hub command.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",