@integrity-labs/agt-cli 0.28.1139 → 0.28.1140

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/bin/agt.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-PI2WUKWD.js";
43
+ } from "../chunk-DRAZDG3U.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
@@ -5474,7 +5474,7 @@ import { execFileSync, execSync } from "child_process";
5474
5474
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5475
5475
  import chalk18 from "chalk";
5476
5476
  import ora16 from "ora";
5477
- var cliVersion = true ? "0.28.1139" : "dev";
5477
+ var cliVersion = true ? "0.28.1140" : "dev";
5478
5478
  async function fetchLatestVersion() {
5479
5479
  const host2 = getHost();
5480
5480
  if (!host2) return null;
@@ -6734,7 +6734,7 @@ function handleError(err) {
6734
6734
  }
6735
6735
 
6736
6736
  // src/bin/agt.ts
6737
- var cliVersion2 = true ? "0.28.1139" : "dev";
6737
+ var cliVersion2 = true ? "0.28.1140" : "dev";
6738
6738
  var program = new Command();
6739
6739
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6740
6740
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -8076,7 +8076,7 @@ function exchangeFailureKind(err) {
8076
8076
  }
8077
8077
 
8078
8078
  // src/lib/api-client.ts
8079
- var agtCliVersion = true ? "0.28.1139" : "dev";
8079
+ var agtCliVersion = true ? "0.28.1140" : "dev";
8080
8080
  var lastConfigHash = null;
8081
8081
  function setConfigHash(hash) {
8082
8082
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -13227,4 +13227,4 @@ export {
13227
13227
  managerInstallSystemUnitCommand,
13228
13228
  managerUninstallSystemUnitCommand
13229
13229
  };
13230
- //# sourceMappingURL=chunk-PI2WUKWD.js.map
13230
+ //# sourceMappingURL=chunk-DRAZDG3U.js.map
@@ -76,7 +76,7 @@ import {
76
76
  setConfigHash,
77
77
  shellGuard,
78
78
  tripClass
79
- } from "../chunk-PI2WUKWD.js";
79
+ } from "../chunk-DRAZDG3U.js";
80
80
  import {
81
81
  getProjectDir as getProjectDir2,
82
82
  getReadyTasks,
@@ -488,6 +488,38 @@ var HostNodeConvergence = class {
488
488
  }
489
489
  };
490
490
 
491
+ // src/lib/host-node-report.ts
492
+ var HOST_NODE_PROBE_INTERVAL_MS = 15 * 60 * 1e3;
493
+ function shouldReprobeHostNode(lastObservedAt, now) {
494
+ if (lastObservedAt === 0) return true;
495
+ return now - lastObservedAt >= HOST_NODE_PROBE_INTERVAL_MS;
496
+ }
497
+ function normalizeReportedNodeVersion(raw) {
498
+ if (raw == null) return null;
499
+ const v = raw.trim().replace(/^v/, "");
500
+ return HOST_NODE_PIN_VERSION_RE.test(v) ? v : null;
501
+ }
502
+ function parsePathNodeVersion(stdout) {
503
+ const m = /^v?(\d+\.\d+\.\d+)/.exec(stdout.trim());
504
+ return m ? normalizeReportedNodeVersion(m[1]) : null;
505
+ }
506
+ function parseRpmNodeVersion(stdout) {
507
+ return normalizeReportedNodeVersion(stdout.trim());
508
+ }
509
+ function heartbeatHostNodeFields(observation, pin, pinState) {
510
+ if (!observation) return {};
511
+ return {
512
+ host_node_version: normalizeReportedNodeVersion(observation.pathVersion),
513
+ host_node_rpm_version: normalizeReportedNodeVersion(observation.rpmVersion),
514
+ // A state without a pin would be meaningless, so the two are resolved
515
+ // together: no pin in force means no state, whatever the converger's
516
+ // internal maps happen to still hold for an older pin.
517
+ host_node_pin: pin,
518
+ host_node_pin_state: pin ? pinState : null,
519
+ host_node_observed: true
520
+ };
521
+ }
522
+
491
523
  // src/lib/manager-worker.ts
492
524
  import { execFileSync as syncExecFile } from "child_process";
493
525
  import { join as join43, dirname as dirname11, delimiter as pathDelimiter } from "path";
@@ -15416,7 +15448,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
15416
15448
  var lastVersionCheckAt = 0;
15417
15449
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
15418
15450
  var lastResponsivenessProbeAt = 0;
15419
- var agtCliVersion = true ? "0.28.1139" : "dev";
15451
+ var agtCliVersion = true ? "0.28.1140" : "dev";
15420
15452
  function resolveBrewPath(execFileSync3) {
15421
15453
  try {
15422
15454
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15597,8 +15629,26 @@ function recordHostNodeFailure(pin, reason) {
15597
15629
  async function diskNodeVersion() {
15598
15630
  const probe = await runAsync("node", ["--version"], { timeout: 15e3 });
15599
15631
  if (probe.code !== 0) return null;
15600
- const m = /^v?(\d+\.\d+\.\d+)/.exec(probe.stdout.trim());
15601
- return m?.[1] ?? null;
15632
+ return parsePathNodeVersion(probe.stdout);
15633
+ }
15634
+ var hostNodeObservation = null;
15635
+ var hostNodeObservedAt = 0;
15636
+ async function probeOrNull(probe) {
15637
+ try {
15638
+ return await probe();
15639
+ } catch {
15640
+ return null;
15641
+ }
15642
+ }
15643
+ async function refreshHostNodeObservation(now = Date.now()) {
15644
+ if (!shouldReprobeHostNode(hostNodeObservedAt, now)) return;
15645
+ hostNodeObservedAt = now;
15646
+ const pathVersion = await probeOrNull(() => diskNodeVersion());
15647
+ const rpmVersion = await probeOrNull(async () => {
15648
+ const rpm = await runAsync("rpm", ["-q", "--qf", "%{VERSION}", "nodejs"], { timeout: 15e3 });
15649
+ return rpm.code === 0 ? parseRpmNodeVersion(rpm.stdout) : null;
15650
+ });
15651
+ hostNodeObservation = { pathVersion, rpmVersion };
15602
15652
  }
15603
15653
  async function ensureHostNodeVersion(rawPin) {
15604
15654
  const pin = normalizeHostNodePinVersion(rawPin);
@@ -17317,6 +17367,8 @@ async function pollCycleInner() {
17317
17367
  } else {
17318
17368
  lastManagedSettingsStatus = null;
17319
17369
  }
17370
+ await refreshHostNodeObservation();
17371
+ const hostNodePin = hostNodeConvergence.desiredPin();
17320
17372
  const hbResp = await api.post("/host/heartbeat", {
17321
17373
  host_id: hostId,
17322
17374
  framework_version: cachedFrameworkVersion ?? void 0,
@@ -17330,6 +17382,17 @@ async function pollCycleInner() {
17330
17382
  // rather than as two fields a future edit could separate. See
17331
17383
  // `heartbeatRuntimeAuthFields`.
17332
17384
  ...heartbeatRuntimeAuthFields(runtimeAuthProbeVerdict),
17385
+ // ENG-11639: host Node, and how the pin stands with this host. Spread as
17386
+ // ONE unit for the same reason as the line above — the API stamps a
17387
+ // freshness timestamp on receipt, so the values and their
17388
+ // `host_node_observed` marker must never be editable apart. Omitted
17389
+ // entirely until the first measurement, because ABSENCE MEANS NO SIGNAL
17390
+ // here and must not be readable as either patched or unpatched.
17391
+ ...heartbeatHostNodeFields(
17392
+ hostNodeObservation,
17393
+ hostNodePin,
17394
+ hostNodePin ? hostNodeConvergence.stateOf(hostNodePin) : null
17395
+ ),
17333
17396
  agent_diagnostics: agentDiagnostics,
17334
17397
  hostname: tailscaleHostname,
17335
17398
  os_username: osUsername,