@integrity-labs/agt-cli 0.28.748 → 0.28.750

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.
@@ -57,7 +57,7 @@ import {
57
57
  safeWriteJsonAtomic,
58
58
  setConfigHash,
59
59
  tripClass
60
- } from "../chunk-G7GWXCPV.js";
60
+ } from "../chunk-5GJ2JEFA.js";
61
61
  import {
62
62
  getProjectDir as getProjectDir2,
63
63
  getReadyTasks,
@@ -1695,7 +1695,28 @@ async function runConnectivityProbes(integrations, options = {}) {
1695
1695
  // assumed. Defaults to 'none' rather than being omitted — an absent field
1696
1696
  // from an older manager and a probe that contacted nothing must land in
1697
1697
  // the same, conservative place.
1698
- evidence: outcome.evidence ?? "none"
1698
+ evidence: outcome.evidence ?? "none",
1699
+ // ENG-9173's other half. That ticket added `last_connectivity_cause` and
1700
+ // the API-side write for it, and the probes compute a cause today
1701
+ // (`causeForHttp` in connectivity-http-probes.ts, and the did-not-run
1702
+ // branches in cli-probe.ts). This line is what puts it ON THE WIRE.
1703
+ //
1704
+ // Without it `ConnectivityReport` had no `cause` field at all, so the
1705
+ // host lane never sent one and the API's
1706
+ // `last_connectivity_cause: item.cause ?? 'unknown'` resolved to
1707
+ // `'unknown'` for EVERY host-probed row on the fleet, forever. The column
1708
+ // added to stop an escalation boundary matching prose was itself never
1709
+ // populated by the lane that does almost all the probing — the identical
1710
+ // parse-then-drop the ENG-9173 header describes, one layer further up.
1711
+ //
1712
+ // Omitted rather than defaulted when absent: unlike `evidence`, where a
1713
+ // missing value and "contacted nothing" must both land conservatively on
1714
+ // `'none'`, the API already coerces an absent or unrecognised cause to
1715
+ // `'unknown'` (`isConnectivityCause`, integration-connectivity-report.ts).
1716
+ // Sending an explicit `'unknown'` would be indistinguishable from an older
1717
+ // manager that cannot classify at all, and that distinction is worth
1718
+ // keeping while this rolls out across hosts.
1719
+ ...outcome.cause ? { cause: outcome.cause } : {}
1699
1720
  });
1700
1721
  }
1701
1722
  return { reports, due: due.length, probed: batch.length, skipped };
@@ -4010,6 +4031,39 @@ function detectMissedIdentifiers(turns, candidates) {
4010
4031
  }
4011
4032
  return out;
4012
4033
  }
4034
+ async function salvageIdentifiers(args) {
4035
+ const forced = detectMissedIdentifiers(args.turns, []);
4036
+ if (forced.length === 0) return 0;
4037
+ const scrubbed = forced.map((c) => ({
4038
+ ...c,
4039
+ content: scrubSensitive(c.content),
4040
+ rationale: scrubSensitive(c.rationale)
4041
+ }));
4042
+ try {
4043
+ const res = await args.api.post(
4044
+ "/host/memories/identifiers",
4045
+ {
4046
+ agent_id: args.agentId,
4047
+ conversation_id: args.conversationId,
4048
+ candidates: scrubbed
4049
+ }
4050
+ );
4051
+ if (!res?.ok) return 0;
4052
+ return res.promoted ?? 0;
4053
+ } catch {
4054
+ return 0;
4055
+ }
4056
+ }
4057
+ async function salvageOnce(st, conversationId, fn) {
4058
+ if (st.salvaged.has(conversationId)) return 0;
4059
+ st.salvaged.add(conversationId);
4060
+ return fn();
4061
+ }
4062
+ function pruneSalvaged(st, stillPending) {
4063
+ for (const id of st.salvaged) {
4064
+ if (!stillPending.has(id)) st.salvaged.delete(id);
4065
+ }
4066
+ }
4013
4067
  async function maybeExtractMemories(args) {
4014
4068
  const { api: api2, backend, codeName, agentId, log: log2 } = args;
4015
4069
  const now = args.now ?? /* @__PURE__ */ new Date();
@@ -4018,7 +4072,8 @@ async function maybeExtractMemories(args) {
4018
4072
  if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS5) {
4019
4073
  return;
4020
4074
  }
4021
- state5.set(codeName, { lastCheckedAt: nowMs });
4075
+ const st = { lastCheckedAt: nowMs, salvaged: existing?.salvaged ?? /* @__PURE__ */ new Set() };
4076
+ state5.set(codeName, st);
4022
4077
  let pending2;
4023
4078
  try {
4024
4079
  const resp = await api2.get(
@@ -4029,6 +4084,7 @@ async function maybeExtractMemories(args) {
4029
4084
  log2(`[memory-extract] ${codeName}: pending fetch failed: ${err.message}`);
4030
4085
  return;
4031
4086
  }
4087
+ pruneSalvaged(st, new Set(pending2.map((p) => p.conversation_id)));
4032
4088
  if (pending2.length === 0) return;
4033
4089
  const dir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
4034
4090
  const allTurns = readRecentTurns(dir, nowMs);
@@ -4038,6 +4094,7 @@ async function maybeExtractMemories(args) {
4038
4094
  }
4039
4095
  return;
4040
4096
  }
4097
+ let salvaged = 0;
4041
4098
  for (const conv of pending2) {
4042
4099
  const windowStart = Date.parse(conv.started_at) - WINDOW_PAD_MS2;
4043
4100
  const windowEnd = Date.parse(conv.last_message_at) + WINDOW_PAD_MS2;
@@ -4058,10 +4115,20 @@ async function maybeExtractMemories(args) {
4058
4115
  } catch (err) {
4059
4116
  log2(`[memory-extract] ${codeName}: extraction failed: ${err.message}`);
4060
4117
  args.onModelCallError?.(err);
4118
+ salvaged += await salvageOnce(
4119
+ st,
4120
+ conv.conversation_id,
4121
+ () => salvageIdentifiers({ api: api2, agentId, conversationId: conv.conversation_id, turns, log: log2, codeName })
4122
+ );
4061
4123
  continue;
4062
4124
  }
4063
4125
  if (candidates === null) {
4064
4126
  log2(`[memory-extract] ${codeName}: unparseable output for ${conv.conversation_id.slice(0, 8)} \u2014 will retry`);
4127
+ salvaged += await salvageOnce(
4128
+ st,
4129
+ conv.conversation_id,
4130
+ () => salvageIdentifiers({ api: api2, agentId, conversationId: conv.conversation_id, turns, log: log2, codeName })
4131
+ );
4065
4132
  continue;
4066
4133
  }
4067
4134
  const forced = detectMissedIdentifiers(turns, candidates);
@@ -4098,6 +4165,9 @@ async function maybeExtractMemories(args) {
4098
4165
  onModelCallError: args.onModelCallError
4099
4166
  });
4100
4167
  }
4168
+ if (salvaged > 0) {
4169
+ log2(`[memory-extract] ${codeName}: identifiers_salvaged=${salvaged} (model call failed)`);
4170
+ }
4101
4171
  }
4102
4172
  async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
4103
4173
  try {
@@ -13321,7 +13391,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13321
13391
  var lastVersionCheckAt = 0;
13322
13392
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13323
13393
  var lastResponsivenessProbeAt = 0;
13324
- var agtCliVersion = true ? "0.28.748" : "dev";
13394
+ var agtCliVersion = true ? "0.28.750" : "dev";
13325
13395
  function resolveBrewPath(execFileSync3) {
13326
13396
  try {
13327
13397
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();