@integrity-labs/agt-cli 0.28.225 → 0.28.226

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.
@@ -18,7 +18,7 @@ import {
18
18
  resolveConnectivityProbe,
19
19
  worseConnectivityOutcome,
20
20
  wrapScheduledTaskPrompt
21
- } from "./chunk-S43WVYAF.js";
21
+ } from "./chunk-C2EXC6LY.js";
22
22
  import {
23
23
  parsePsRows
24
24
  } from "./chunk-XWVM4KPK.js";
@@ -5667,7 +5667,7 @@ function requireHost() {
5667
5667
  }
5668
5668
 
5669
5669
  // src/lib/api-client.ts
5670
- var agtCliVersion = true ? "0.28.225" : "dev";
5670
+ var agtCliVersion = true ? "0.28.226" : "dev";
5671
5671
  var lastConfigHash = null;
5672
5672
  function setConfigHash(hash) {
5673
5673
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -7720,4 +7720,4 @@ export {
7720
7720
  managerInstallSystemUnitCommand,
7721
7721
  managerUninstallSystemUnitCommand
7722
7722
  };
7723
- //# sourceMappingURL=chunk-A36N2XXT.js.map
7723
+ //# sourceMappingURL=chunk-IRMBTIZO.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-I4CQEDME.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-AIX7H4CC.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-JFP2N723.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-NWOXCBWA.js.map
@@ -37,7 +37,7 @@ import {
37
37
  requireHost,
38
38
  safeWriteJsonAtomic,
39
39
  setConfigHash
40
- } from "../chunk-A36N2XXT.js";
40
+ } from "../chunk-IRMBTIZO.js";
41
41
  import {
42
42
  getProjectDir as getProjectDir2,
43
43
  getReadyTasks,
@@ -122,7 +122,7 @@ import {
122
122
  takeZombieDetection,
123
123
  transcriptActivityAgeSeconds,
124
124
  writeEgressAllowlist
125
- } from "../chunk-S43WVYAF.js";
125
+ } from "../chunk-C2EXC6LY.js";
126
126
  import {
127
127
  reapOrphanChannelMcps
128
128
  } from "../chunk-XWVM4KPK.js";
@@ -1251,6 +1251,83 @@ function decideRestartGate(opts) {
1251
1251
  return "proceed";
1252
1252
  }
1253
1253
 
1254
+ // src/lib/model-api-error.ts
1255
+ function classifyHttpStatus(status) {
1256
+ if (status === 529) return "overloaded_529";
1257
+ if (status === 429) return "rate_limit_429";
1258
+ if (status >= 500 && status <= 599) return "server_error_5xx";
1259
+ return null;
1260
+ }
1261
+ function classifyModelApiError(input) {
1262
+ if (typeof input.status === "number") {
1263
+ const cls = classifyHttpStatus(input.status);
1264
+ if (cls) return { errorClass: cls, httpStatus: input.status };
1265
+ }
1266
+ const err = input.error;
1267
+ const rawMessage = input.message ?? (err instanceof Error ? err.message : typeof err === "string" ? err : "");
1268
+ const errName = err instanceof Error ? err.name : "";
1269
+ const haystack = `${errName} ${rawMessage}`.toLowerCase();
1270
+ if (!haystack.trim()) return null;
1271
+ const statusMatch = haystack.match(/returned\s+(\d{3})\b/);
1272
+ if (statusMatch) {
1273
+ const status = Number(statusMatch[1]);
1274
+ const cls = classifyHttpStatus(status);
1275
+ if (cls) return { errorClass: cls, httpStatus: status };
1276
+ }
1277
+ if (errName === "TimeoutError" || errName === "AbortError" || /\btimed?\s*out\b|\btimeout\b|\baborted\b|etimedout/.test(haystack)) {
1278
+ return { errorClass: "timeout", httpStatus: null };
1279
+ }
1280
+ if (/econnreset|econnrefused|enotfound|eai_again|epipe|socket hang up|network error|fetch failed|und_err/.test(
1281
+ haystack
1282
+ )) {
1283
+ return { errorClass: "connection_error", httpStatus: null };
1284
+ }
1285
+ if (/overloaded/.test(haystack)) {
1286
+ return { errorClass: "overloaded_529", httpStatus: null };
1287
+ }
1288
+ return null;
1289
+ }
1290
+ var AGENT_API_ERROR_RE = /API\s*Error[:\s]+(?:(\d{3})\b|([A-Za-z][^\n]{0,60}))/gi;
1291
+ function scrapeAgentRuntimeModelApiError(paneTail) {
1292
+ if (!paneTail) return null;
1293
+ let last = null;
1294
+ let m;
1295
+ AGENT_API_ERROR_RE.lastIndex = 0;
1296
+ while ((m = AGENT_API_ERROR_RE.exec(paneTail)) !== null) {
1297
+ if (m[1]) {
1298
+ const status = Number(m[1]);
1299
+ const cls = classifyHttpStatus(status);
1300
+ if (cls) last = { errorClass: cls, httpStatus: status };
1301
+ continue;
1302
+ }
1303
+ const text = (m[2] ?? "").toLowerCase();
1304
+ if (/overloaded/.test(text)) last = { errorClass: "overloaded_529", httpStatus: null };
1305
+ else if (/\btimed?\s*out\b|\btimeout\b/.test(text)) last = { errorClass: "timeout", httpStatus: null };
1306
+ }
1307
+ return last;
1308
+ }
1309
+ async function reportModelApiError(opts) {
1310
+ try {
1311
+ const hostId = await getHostId();
1312
+ if (!hostId) return;
1313
+ await api.post("/host/model-api-error-events", {
1314
+ host_id: hostId,
1315
+ agent_code_name: opts.agentCodeName ?? null,
1316
+ source: opts.source,
1317
+ error_class: opts.errorClass,
1318
+ http_status: opts.httpStatus ?? null,
1319
+ model_id: opts.modelId ?? null,
1320
+ // Content-free by contract, but bound it defensively.
1321
+ detail: opts.detail ? opts.detail.slice(0, 500) : null,
1322
+ occurred_at: opts.occurredAt ?? (/* @__PURE__ */ new Date()).toISOString()
1323
+ });
1324
+ } catch (err) {
1325
+ opts.log?.(
1326
+ `[model-api-error] report failed (${opts.source}/${opts.errorClass}): ${err instanceof Error ? err.message : String(err)}`
1327
+ );
1328
+ }
1329
+ }
1330
+
1254
1331
  // src/lib/claude-pid-tracker.ts
1255
1332
  import { existsSync, readFileSync as readFileSync5 } from "fs";
1256
1333
  function readPidFile(path) {
@@ -2179,6 +2256,7 @@ async function maybeEvaluateConversations(args) {
2179
2256
  } catch (err) {
2180
2257
  backendError = toHealthErrorMessage(err);
2181
2258
  log2(`[conversation-eval] ${codeName}: scoring failed: ${backendError}`);
2259
+ args.onModelCallError?.(err);
2182
2260
  continue;
2183
2261
  }
2184
2262
  if (!verdict) {
@@ -2394,6 +2472,7 @@ async function maybeExtractMemories(args) {
2394
2472
  candidates = parseCandidates(out);
2395
2473
  } catch (err) {
2396
2474
  log2(`[memory-extract] ${codeName}: extraction failed: ${err.message}`);
2475
+ args.onModelCallError?.(err);
2397
2476
  continue;
2398
2477
  }
2399
2478
  if (candidates === null) {
@@ -6242,6 +6321,7 @@ function clearAgentCaches(agentId, codeName) {
6242
6321
  claudeSchedulerStates.delete(codeName);
6243
6322
  claudeTaskConcurrency.delete(codeName);
6244
6323
  lastMcpFailedBannerCount.delete(codeName);
6324
+ lastModelApiErrorSig.delete(codeName);
6245
6325
  memoryFileHashes.delete(agentId);
6246
6326
  lastDownloadHash.delete(agentId);
6247
6327
  lastLocalFileHash.delete(agentId);
@@ -6258,7 +6338,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
6258
6338
  var lastVersionCheckAt = 0;
6259
6339
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6260
6340
  var lastResponsivenessProbeAt = 0;
6261
- var agtCliVersion = true ? "0.28.225" : "dev";
6341
+ var agtCliVersion = true ? "0.28.226" : "dev";
6262
6342
  function resolveBrewPath(execFileSync2) {
6263
6343
  try {
6264
6344
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -6980,6 +7060,22 @@ function hostFlagStore() {
6980
7060
  }
6981
7061
  return _hostFlagStore;
6982
7062
  }
7063
+ function reportManagerModelCallError(source, err, modelId) {
7064
+ try {
7065
+ if (!hostFlagStore().getBoolean("model-api-error-reporting")) return;
7066
+ const classified = classifyModelApiError({ error: err });
7067
+ if (!classified) return;
7068
+ void reportModelApiError({
7069
+ source,
7070
+ errorClass: classified.errorClass,
7071
+ httpStatus: classified.httpStatus,
7072
+ modelId,
7073
+ detail: err instanceof Error ? err.message : String(err),
7074
+ log
7075
+ });
7076
+ } catch {
7077
+ }
7078
+ }
6983
7079
  function channelQuarantineMode() {
6984
7080
  return hostFlagStore().getString("channel-quarantine-mode");
6985
7081
  }
@@ -7167,7 +7263,7 @@ async function pollCycle() {
7167
7263
  }
7168
7264
  try {
7169
7265
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
7170
- const { collectDiagnostics } = await import("../persistent-session-I4CQEDME.js");
7266
+ const { collectDiagnostics } = await import("../persistent-session-AIX7H4CC.js");
7171
7267
  const diagCodeNames = [...agentState.persistentSessionAgents];
7172
7268
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
7173
7269
  let tailscaleHostname;
@@ -7315,7 +7411,7 @@ async function pollCycle() {
7315
7411
  const {
7316
7412
  collectResponsivenessProbes,
7317
7413
  getResponsivenessIntervalMs
7318
- } = await import("../responsiveness-probe-MIUMXKV4.js");
7414
+ } = await import("../responsiveness-probe-VBXDCOHO.js");
7319
7415
  const probeIntervalMs = getResponsivenessIntervalMs();
7320
7416
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
7321
7417
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -7347,7 +7443,7 @@ async function pollCycle() {
7347
7443
  collectResponsivenessProbes,
7348
7444
  livePendingInboundOldestAgeSeconds,
7349
7445
  parkPendingInbound
7350
- } = await import("../responsiveness-probe-MIUMXKV4.js");
7446
+ } = await import("../responsiveness-probe-VBXDCOHO.js");
7351
7447
  const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
7352
7448
  const wedgeNow = /* @__PURE__ */ new Date();
7353
7449
  const liveAgents = agentState.persistentSessionAgents;
@@ -7480,11 +7576,27 @@ async function pollCycle() {
7480
7576
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
7481
7577
  const observations = [];
7482
7578
  const pendingCacheCommits = [];
7579
+ const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
7483
7580
  for (const codeName of agentState.persistentSessionAgents) {
7484
7581
  const agentId = agentState.codeNameToAgentId.get(codeName);
7485
7582
  if (!agentId) continue;
7486
7583
  const tail = readPaneLogTail(codeName, 40);
7487
7584
  if (!tail) continue;
7585
+ if (modelApiErrorReportingOn) {
7586
+ const observedErr = scrapeAgentRuntimeModelApiError(tail);
7587
+ const sig = observedErr ? `${observedErr.errorClass}:${observedErr.httpStatus ?? ""}` : "";
7588
+ if (observedErr && sig !== (lastModelApiErrorSig.get(codeName) ?? "")) {
7589
+ void reportModelApiError({
7590
+ source: "agent_runtime",
7591
+ errorClass: observedErr.errorClass,
7592
+ httpStatus: observedErr.httpStatus,
7593
+ agentCodeName: codeName,
7594
+ detail: `agent pane: ${observedErr.errorClass}`,
7595
+ log
7596
+ });
7597
+ }
7598
+ lastModelApiErrorSig.set(codeName, sig);
7599
+ }
7488
7600
  const observed = scrapeMcpFailedBannerCount(tail);
7489
7601
  const count = observed ?? 0;
7490
7602
  const last = lastMcpFailedBannerCount.get(codeName);
@@ -7602,7 +7714,7 @@ async function pollCycle() {
7602
7714
  if (restartedCodeNames.length > 0) {
7603
7715
  void (async () => {
7604
7716
  try {
7605
- const { collectDiagnostics } = await import("../persistent-session-I4CQEDME.js");
7717
+ const { collectDiagnostics } = await import("../persistent-session-AIX7H4CC.js");
7606
7718
  const freshDiagnostics = collectDiagnostics(restartedCodeNames);
7607
7719
  await api.post("/host/heartbeat", {
7608
7720
  host_id: hostId,
@@ -7833,21 +7945,25 @@ async function processAgent(agent, agentStates) {
7833
7945
  logMeteredScorerSuppressed();
7834
7946
  }
7835
7947
  if (!scorerSuppressed) {
7948
+ const evalBackend = resolveConversationEvalBackend();
7836
7949
  void maybeEvaluateConversations({
7837
7950
  api,
7838
- backend: resolveConversationEvalBackend(),
7951
+ backend: evalBackend,
7839
7952
  codeName: agent.code_name,
7840
7953
  agentId: agent.agent_id,
7841
- log
7954
+ log,
7955
+ onModelCallError: (err) => reportManagerModelCallError("conversation_eval", err, evalBackend.model ?? null)
7842
7956
  });
7843
7957
  }
7844
7958
  if (memoryExtractionEnabled() && !scorerSuppressed) {
7959
+ const memBackend = resolveConversationEvalBackend();
7845
7960
  void maybeExtractMemories({
7846
7961
  api,
7847
- backend: resolveConversationEvalBackend(),
7962
+ backend: memBackend,
7848
7963
  codeName: agent.code_name,
7849
7964
  agentId: agent.agent_id,
7850
- log
7965
+ log,
7966
+ onModelCallError: (err) => reportManagerModelCallError("memory_extraction", err, memBackend.model ?? null)
7851
7967
  });
7852
7968
  }
7853
7969
  }
@@ -9592,6 +9708,7 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
9592
9708
  });
9593
9709
  }
9594
9710
  var lastMcpFailedBannerCount = /* @__PURE__ */ new Map();
9711
+ var lastModelApiErrorSig = /* @__PURE__ */ new Map();
9595
9712
  var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
9596
9713
  var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
9597
9714
  var egressAllowlistBySession = /* @__PURE__ */ new Map();
@@ -10100,7 +10217,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
10100
10217
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
10101
10218
  void (async () => {
10102
10219
  try {
10103
- const { collectDiagnostics } = await import("../persistent-session-I4CQEDME.js");
10220
+ const { collectDiagnostics } = await import("../persistent-session-AIX7H4CC.js");
10104
10221
  await api.post("/host/heartbeat", {
10105
10222
  host_id: hostId,
10106
10223
  agent_diagnostics: collectDiagnostics([codeName])
@@ -10494,7 +10611,7 @@ async function processClaudePairSessions(agents) {
10494
10611
  killPairSession,
10495
10612
  pairTmuxSession,
10496
10613
  finalizeClaudePairOnboarding
10497
- } = await import("../claude-pair-runtime-JFP2N723.js");
10614
+ } = await import("../claude-pair-runtime-NWOXCBWA.js");
10498
10615
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
10499
10616
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
10500
10617
  const killed = await killPairSession(pairTmuxSession(pairId));