@integrity-labs/agt-cli 0.27.53 → 0.27.54

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
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-GPBGRRCV.js";
30
+ } from "../chunk-54EOGPOF.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -4710,7 +4710,7 @@ import { execFileSync, execSync } from "child_process";
4710
4710
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4711
4711
  import chalk18 from "chalk";
4712
4712
  import ora16 from "ora";
4713
- var cliVersion = true ? "0.27.53" : "dev";
4713
+ var cliVersion = true ? "0.27.54" : "dev";
4714
4714
  async function fetchLatestVersion() {
4715
4715
  const host2 = getHost();
4716
4716
  if (!host2) return null;
@@ -5488,7 +5488,7 @@ function handleError(err) {
5488
5488
  }
5489
5489
 
5490
5490
  // src/bin/agt.ts
5491
- var cliVersion2 = true ? "0.27.53" : "dev";
5491
+ var cliVersion2 = true ? "0.27.54" : "dev";
5492
5492
  var program = new Command();
5493
5493
  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");
5494
5494
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -7163,4 +7163,4 @@ export {
7163
7163
  managerInstallSystemUnitCommand,
7164
7164
  managerUninstallSystemUnitCommand
7165
7165
  };
7166
- //# sourceMappingURL=chunk-GPBGRRCV.js.map
7166
+ //# sourceMappingURL=chunk-54EOGPOF.js.map
@@ -15,7 +15,7 @@ import {
15
15
  provisionOrientHook,
16
16
  provisionStopHook,
17
17
  requireHost
18
- } from "../chunk-GPBGRRCV.js";
18
+ } from "../chunk-54EOGPOF.js";
19
19
  import {
20
20
  getProjectDir as getProjectDir2,
21
21
  getReadyTasks,
@@ -1234,6 +1234,92 @@ function formatReaperBootLine(opts) {
1234
1234
  return `[drain] step=boot-reaper total=${opts.totalRecorded} killed=${opts.killed} already_dead=${opts.alreadyDead} pid_reused_skipped=${opts.pidReusedSkipped} kanban_reset=${opts.kanbanReset}`;
1235
1235
  }
1236
1236
 
1237
+ // src/lib/direct-chat-spawn-gate.ts
1238
+ var DEFAULT_DIRECT_CHAT_HOST_CONCURRENCY = 2;
1239
+ var DEFAULT_DIRECT_CHAT_PER_AGENT_CONCURRENCY = 1;
1240
+ var DEFAULT_DIRECT_CHAT_MAX_AGE_MS = 30 * 6e4;
1241
+ function directChatHostConcurrency() {
1242
+ const raw = parseInt(process.env["AGT_DIRECT_CHAT_MAX_CONCURRENCY"] ?? "", 10);
1243
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_DIRECT_CHAT_HOST_CONCURRENCY;
1244
+ }
1245
+ function directChatMaxAgeMs() {
1246
+ const raw = parseInt(process.env["AGT_DIRECT_CHAT_MAX_AGE_MS"] ?? "", 10);
1247
+ return Number.isFinite(raw) && raw >= 0 ? raw : DEFAULT_DIRECT_CHAT_MAX_AGE_MS;
1248
+ }
1249
+ function isDirectChatMessageExpired(createdAt, nowMs, maxAgeMs) {
1250
+ if (!maxAgeMs || maxAgeMs <= 0) return false;
1251
+ if (!createdAt) return false;
1252
+ const created = Date.parse(createdAt);
1253
+ if (!Number.isFinite(created)) return false;
1254
+ return nowMs - created > maxAgeMs;
1255
+ }
1256
+ var DirectChatSpawnGate = class {
1257
+ hostMax;
1258
+ perAgentMax;
1259
+ host = 0;
1260
+ perAgent = /* @__PURE__ */ new Map();
1261
+ queue = [];
1262
+ constructor(config2) {
1263
+ this.hostMax = Math.max(1, config2?.hostMaxConcurrency ?? DEFAULT_DIRECT_CHAT_HOST_CONCURRENCY);
1264
+ this.perAgentMax = Math.max(
1265
+ 1,
1266
+ config2?.perAgentMaxConcurrency ?? DEFAULT_DIRECT_CHAT_PER_AGENT_CONCURRENCY
1267
+ );
1268
+ }
1269
+ /** Live host-wide spawn count. */
1270
+ get hostInFlight() {
1271
+ return this.host;
1272
+ }
1273
+ /** Live spawn count for a single agent. */
1274
+ agentInFlight(codeName) {
1275
+ return this.perAgent.get(codeName) ?? 0;
1276
+ }
1277
+ /** Number of acquirers currently waiting for a slot. */
1278
+ get queuedCount() {
1279
+ return this.queue.length;
1280
+ }
1281
+ canGrant(codeName) {
1282
+ return this.host < this.hostMax && this.agentInFlight(codeName) < this.perAgentMax;
1283
+ }
1284
+ grant(codeName) {
1285
+ this.host += 1;
1286
+ this.perAgent.set(codeName, this.agentInFlight(codeName) + 1);
1287
+ let released = false;
1288
+ return () => {
1289
+ if (released) return;
1290
+ released = true;
1291
+ this.host -= 1;
1292
+ const remaining = this.agentInFlight(codeName) - 1;
1293
+ if (remaining <= 0) this.perAgent.delete(codeName);
1294
+ else this.perAgent.set(codeName, remaining);
1295
+ this.drain();
1296
+ };
1297
+ }
1298
+ /** Acquire a spawn slot for `codeName`. Resolves with a single-use release. */
1299
+ acquire(codeName) {
1300
+ if (this.canGrant(codeName)) {
1301
+ return Promise.resolve(this.grant(codeName));
1302
+ }
1303
+ return new Promise((resolve) => {
1304
+ this.queue.push({ codeName, resolve });
1305
+ });
1306
+ }
1307
+ /** Grant as many queued waiters as free slots allow, in FIFO order. */
1308
+ drain() {
1309
+ let i = 0;
1310
+ while (i < this.queue.length && this.host < this.hostMax) {
1311
+ const waiter = this.queue[i];
1312
+ if (!waiter) break;
1313
+ if (this.canGrant(waiter.codeName)) {
1314
+ this.queue.splice(i, 1);
1315
+ waiter.resolve(this.grant(waiter.codeName));
1316
+ } else {
1317
+ i += 1;
1318
+ }
1319
+ }
1320
+ }
1321
+ };
1322
+
1237
1323
  // src/lib/usage-banner-monitor.ts
1238
1324
  var MIN_CHECK_INTERVAL_MS = 6e4;
1239
1325
  var PANE_TAIL_LINES_FOR_BANNER = 200;
@@ -3512,7 +3598,7 @@ var cachedFrameworkVersion = null;
3512
3598
  var lastVersionCheckAt = 0;
3513
3599
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3514
3600
  var lastResponsivenessProbeAt = 0;
3515
- var agtCliVersion = true ? "0.27.53" : "dev";
3601
+ var agtCliVersion = true ? "0.27.54" : "dev";
3516
3602
  function resolveBrewPath(execFileSync4) {
3517
3603
  try {
3518
3604
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -7670,6 +7756,9 @@ function triggerEarlyPoll(reason) {
7670
7756
  }, 0);
7671
7757
  }
7672
7758
  var directChatInFlight = /* @__PURE__ */ new Set();
7759
+ var directChatSpawnGate = new DirectChatSpawnGate({
7760
+ hostMaxConcurrency: directChatHostConcurrency()
7761
+ });
7673
7762
  async function pollDirectChatMessages(agentStates) {
7674
7763
  for (const agent of agentStates) {
7675
7764
  if (agent.status !== "active") continue;
@@ -7692,6 +7781,18 @@ async function pollDirectChatMessages(agentStates) {
7692
7781
  async function processDirectChatMessage(agent, msg) {
7693
7782
  const fw = agentFrameworkCache.get(agent.codeName) ?? "openclaw";
7694
7783
  log(`[direct-chat] Processing message for '${agent.codeName}' (fw=${fw}): id=${msg.id} len=${msg.content.length}`);
7784
+ if (isDirectChatMessageExpired(msg.created_at, Date.now(), directChatMaxAgeMs())) {
7785
+ log(`[direct-chat] Expired backlog message for '${agent.codeName}' (msg=${msg.id}, created_at=${msg.created_at}) \u2014 draining without delivery`);
7786
+ try {
7787
+ await api.post("/host/direct-chat/reply", {
7788
+ agent_id: agent.agentId,
7789
+ session_id: msg.session_id,
7790
+ content: "[Expired] This message timed out before it could be processed. Please resend it."
7791
+ });
7792
+ } catch {
7793
+ }
7794
+ return;
7795
+ }
7695
7796
  if (isSessionHealthy(agent.codeName)) {
7696
7797
  const escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
7697
7798
  const channelEnvelope = `<channel source="direct-chat" session_id="${escapeXml(msg.session_id)}" user="webapp">
@@ -7710,9 +7811,24 @@ ${escapeXml(msg.content)}
7710
7811
  }
7711
7812
  log(`[direct-chat] Inject reported unverified for '${agent.codeName}' (msg=${msg.id}) \u2014 falling back to one-shot direct-chat handling`);
7712
7813
  }
7814
+ let releaseSpawnSlot;
7713
7815
  try {
7714
7816
  let reply;
7715
7817
  if (fw === "claude-code") {
7818
+ releaseSpawnSlot = await directChatSpawnGate.acquire(agent.codeName);
7819
+ if (isDirectChatMessageExpired(msg.created_at, Date.now(), directChatMaxAgeMs())) {
7820
+ log(`[direct-chat] Message for '${agent.codeName}' expired while queued behind the spawn gate (msg=${msg.id}) \u2014 draining without a spawn`);
7821
+ try {
7822
+ await api.post("/host/direct-chat/reply", {
7823
+ agent_id: agent.agentId,
7824
+ session_id: msg.session_id,
7825
+ content: "[Expired] This message timed out before it could be processed. Please resend it."
7826
+ });
7827
+ } catch {
7828
+ }
7829
+ return;
7830
+ }
7831
+ log(`[direct-chat] One-shot spawn for '${agent.codeName}' (msg=${msg.id}; host in-flight=${directChatSpawnGate.hostInFlight}, queued=${directChatSpawnGate.queuedCount})`);
7716
7832
  const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-EM24LTGV.js");
7717
7833
  const projDir = ccProjectDir(agent.codeName);
7718
7834
  const mcpConfigPath = join7(projDir, ".mcp.json");
@@ -7813,6 +7929,8 @@ ${escapeXml(msg.content)}
7813
7929
  });
7814
7930
  } catch {
7815
7931
  }
7932
+ } finally {
7933
+ releaseSpawnSlot?.();
7816
7934
  }
7817
7935
  }
7818
7936
  var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);