@integrity-labs/agt-cli 0.28.523 → 0.28.525

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-HERASX7X.js";
43
+ } from "../chunk-NFBAZOKX.js";
44
44
  import {
45
45
  AnchorSessionClient,
46
46
  CHANNEL_REGISTRY,
@@ -4834,7 +4834,7 @@ import { execFileSync, execSync } from "child_process";
4834
4834
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4835
4835
  import chalk18 from "chalk";
4836
4836
  import ora16 from "ora";
4837
- var cliVersion = true ? "0.28.523" : "dev";
4837
+ var cliVersion = true ? "0.28.525" : "dev";
4838
4838
  async function fetchLatestVersion() {
4839
4839
  const host2 = getHost();
4840
4840
  if (!host2) return null;
@@ -6006,7 +6006,7 @@ function handleError(err) {
6006
6006
  }
6007
6007
 
6008
6008
  // src/bin/agt.ts
6009
- var cliVersion2 = true ? "0.28.523" : "dev";
6009
+ var cliVersion2 = true ? "0.28.525" : "dev";
6010
6010
  var program = new Command();
6011
6011
  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");
6012
6012
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -5317,7 +5317,7 @@ function exchangeFailureKind(err) {
5317
5317
  }
5318
5318
 
5319
5319
  // src/lib/api-client.ts
5320
- var agtCliVersion = true ? "0.28.523" : "dev";
5320
+ var agtCliVersion = true ? "0.28.525" : "dev";
5321
5321
  var lastConfigHash = null;
5322
5322
  function setConfigHash(hash) {
5323
5323
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8629,4 +8629,4 @@ export {
8629
8629
  managerInstallSystemUnitCommand,
8630
8630
  managerUninstallSystemUnitCommand
8631
8631
  };
8632
- //# sourceMappingURL=chunk-HERASX7X.js.map
8632
+ //# sourceMappingURL=chunk-NFBAZOKX.js.map
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-HERASX7X.js";
56
+ } from "../chunk-NFBAZOKX.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -6448,6 +6448,11 @@ function isAppMentionEcho(evt, botUserId) {
6448
6448
  return false;
6449
6449
  return typeof evt.text === "string" && evt.text.includes(`<@${botUserId}>`);
6450
6450
  }
6451
+ function slackInboundDedupId(evt) {
6452
+ if (!evt.channel || !evt.ts)
6453
+ return null;
6454
+ return `${evt.channel}:${evt.ts}:${evt.type ?? "unknown"}`;
6455
+ }
6451
6456
  function extractAugmentedSlackLabel(evt) {
6452
6457
  if (evt.metadata?.event_type !== "augmented_agent_message")
6453
6458
  return null;
@@ -6866,7 +6871,7 @@ async function dispatchSlackInbound(event, ctx) {
6866
6871
  if (isAppMentionEcho(event, ctx.botUserId ?? null)) {
6867
6872
  return "dropped_echo";
6868
6873
  }
6869
- const dedupKey = event.channel && event.ts ? `${event.channel}:${event.ts}` : null;
6874
+ const dedupKey = slackInboundDedupId(event);
6870
6875
  if (dedupKey) {
6871
6876
  if (ctx.seen.has(dedupKey)) return "dropped_duplicate";
6872
6877
  ctx.seen.add(dedupKey);
@@ -9567,6 +9572,7 @@ var RESTART_DEFER_RECHECK_MS = 6e4;
9567
9572
  var DEFER_LOG_THROTTLE_MS = 6e5;
9568
9573
  var deferLogThrottle = /* @__PURE__ */ new Map();
9569
9574
  var lastInboundMs = /* @__PURE__ */ new Map();
9575
+ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
9570
9576
  var consecutiveWedgeCycles = /* @__PURE__ */ new Map();
9571
9577
  var wedgeExemptionLogged = /* @__PURE__ */ new Set();
9572
9578
  var wedgeRestartsByCard = /* @__PURE__ */ new Map();
@@ -9578,6 +9584,66 @@ function inboundAgeSecondsFor(codeName) {
9578
9584
  if (ts === void 0) return null;
9579
9585
  return Math.max(0, Math.floor((Date.now() - ts) / 1e3));
9580
9586
  }
9587
+ function decideDayRolloverAction(i) {
9588
+ if (!i.staleForToday || !i.sessionHealthy || !i.hasCurrent) return "none";
9589
+ if (i.idle) return "defer-idle";
9590
+ return i.overdueMin >= i.graceMin ? "force-reset" : "busy-wait";
9591
+ }
9592
+ function classifyLazyDayRolloverReset(i) {
9593
+ if (!i.flagged) return "skip";
9594
+ if (!i.sessionHealthy) return "clear-stale";
9595
+ if (!i.staleForToday) return "clear-stale";
9596
+ if (!i.hasCurrent) return "skip";
9597
+ return i.idle ? "reset" : "skip";
9598
+ }
9599
+ function resolveEffectiveAgentTimezone(inputs) {
9600
+ const orgTierTz = cachedMaintenanceWindow?.timezone ?? null;
9601
+ const ownTzEffective = isAgentTimezoneOverrideExpired(inputs.agentTimezoneExpiresAt) ? null : inputs.agentTimezone;
9602
+ if (isUnsetTimezone(ownTzEffective) && isUnsetTimezone(inputs.teamTimezone) && isUnsetTimezone(orgTierTz)) {
9603
+ return void 0;
9604
+ }
9605
+ return resolveAgentTimezone(
9606
+ ownTzEffective,
9607
+ inputs.teamTimezone,
9608
+ orgTierTz,
9609
+ inputs.agentTimezoneExpiresAt
9610
+ );
9611
+ }
9612
+ function cachedAgentTimezoneFor(codeName) {
9613
+ const inputs = agentRestartTimezoneInputs.get(codeName);
9614
+ if (!inputs) return void 0;
9615
+ return resolveEffectiveAgentTimezone({
9616
+ agentTimezone: inputs.agentTimezone,
9617
+ teamTimezone: inputs.teamTimezone,
9618
+ agentTimezoneExpiresAt: inputs.agentTimezoneExpiresAt
9619
+ });
9620
+ }
9621
+ function performLazyDayRolloverReset(codeName, agentTimezone) {
9622
+ const flagged = pendingDayRolloverReset.has(codeName);
9623
+ const sessionHealthy = flagged && isSessionHealthy(codeName);
9624
+ const staleForToday = flagged ? isStaleForToday(codeName, /* @__PURE__ */ new Date(), agentTimezone ?? void 0) : false;
9625
+ const current = flagged && sessionHealthy && staleForToday ? peekCurrentSession(codeName) : null;
9626
+ const outcome = classifyLazyDayRolloverReset({
9627
+ flagged,
9628
+ staleForToday,
9629
+ sessionHealthy,
9630
+ hasCurrent: current !== null,
9631
+ idle: current ? isAgentIdle(getProjectDir(codeName), current.sessionId) : false
9632
+ });
9633
+ if (outcome === "clear-stale") {
9634
+ pendingDayRolloverReset.delete(codeName);
9635
+ return false;
9636
+ }
9637
+ if (outcome === "skip" || !current) return false;
9638
+ log(
9639
+ `[persistent-session] Day rollover for '${codeName}' (yesterday=${current.date}) \u2014 first real trigger after an idle rollover; minting a fresh session now (deferred boot, paid alongside real work) [ENG-8461]`
9640
+ );
9641
+ stopPersistentSessionAndForgetMcpBaseline(codeName, "day-rollover");
9642
+ agentState.persistentSessionAgents.delete(codeName);
9643
+ rotatePaneLogForDayRollover(codeName, log, agentTimezone);
9644
+ pendingDayRolloverReset.delete(codeName);
9645
+ return true;
9646
+ }
9581
9647
  function paneLogAgeSecondsFor(codeName) {
9582
9648
  try {
9583
9649
  const mtimeMs = statSync6(paneLogPath(codeName)).mtimeMs;
@@ -10106,7 +10172,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10106
10172
  var lastVersionCheckAt = 0;
10107
10173
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10108
10174
  var lastResponsivenessProbeAt = 0;
10109
- var agtCliVersion = true ? "0.28.523" : "dev";
10175
+ var agtCliVersion = true ? "0.28.525" : "dev";
10110
10176
  function resolveBrewPath(execFileSync2) {
10111
10177
  try {
10112
10178
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11536,7 +11602,7 @@ async function pollCycle() {
11536
11602
  collectResponsivenessProbes,
11537
11603
  collectPanelessActivityProbes,
11538
11604
  getResponsivenessIntervalMs
11539
- } = await import("../responsiveness-probe-KW7KQJUY.js");
11605
+ } = await import("../responsiveness-probe-MWTX6VNY.js");
11540
11606
  const probeIntervalMs = getResponsivenessIntervalMs();
11541
11607
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
11542
11608
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -11600,7 +11666,7 @@ async function pollCycle() {
11600
11666
  collectResponsivenessProbes,
11601
11667
  livePendingInboundOldestAgeSeconds,
11602
11668
  parkPendingInbound
11603
- } = await import("../responsiveness-probe-KW7KQJUY.js");
11669
+ } = await import("../responsiveness-probe-MWTX6VNY.js");
11604
11670
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
11605
11671
  const wedgeNow = /* @__PURE__ */ new Date();
11606
11672
  const liveAgents = agentState.persistentSessionAgents;
@@ -14505,14 +14571,13 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
14505
14571
  const ownTz = typeof ownTzRaw === "string" && ownTzRaw.trim() !== "" ? ownTzRaw.trim() : null;
14506
14572
  const tz = teamSettingsForTz?.["timezone"];
14507
14573
  const teamTz = typeof tz === "string" && tz.trim() !== "" ? tz.trim() : null;
14508
- const orgTierTz = cachedMaintenanceWindow?.timezone ?? null;
14509
14574
  const ownTzExpiresAtRaw = refreshData.agent?.timezone_expires_at;
14510
14575
  const ownTzExpiresAt = typeof ownTzExpiresAtRaw === "string" && ownTzExpiresAtRaw.trim() !== "" ? ownTzExpiresAtRaw : null;
14511
- const ownTzEffective = isAgentTimezoneOverrideExpired(ownTzExpiresAt) ? null : ownTz;
14512
- if (isUnsetTimezone(ownTzEffective) && isUnsetTimezone(teamTz) && isUnsetTimezone(orgTierTz)) {
14513
- return void 0;
14514
- }
14515
- return resolveAgentTimezone(ownTzEffective, teamTz, orgTierTz, ownTzExpiresAt);
14576
+ return resolveEffectiveAgentTimezone({
14577
+ agentTimezone: ownTz,
14578
+ teamTimezone: teamTz,
14579
+ agentTimezoneExpiresAt: ownTzExpiresAt
14580
+ });
14516
14581
  })();
14517
14582
  const frameworkId = agentFrameworkCache.get(codeName) ?? DEFAULT_FRAMEWORK;
14518
14583
  if (frameworkId === "opencode") {
@@ -14649,35 +14714,40 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
14649
14714
  agentState.persistentSessionAgents.delete(codeName);
14650
14715
  restartTrigger = "auth-tuple";
14651
14716
  }
14652
- if (isStaleForToday(codeName, /* @__PURE__ */ new Date(), agentTimezone) && isSessionHealthy(codeName)) {
14653
- const current = peekCurrentSession(codeName);
14654
- if (current) {
14655
- const idle = isAgentIdle(projectDir, current.sessionId);
14656
- if (idle) {
14657
- log(
14658
- `[persistent-session] Day rollover for '${codeName}' (yesterday=${current.date}) \u2014 agent idle, restarting to mint fresh session`
14659
- );
14660
- stopPersistentSessionAndForgetMcpBaseline(codeName, "day-rollover");
14661
- agentState.persistentSessionAgents.delete(codeName);
14662
- restartTrigger = "day-rollover";
14663
- } else {
14664
- const overdueMin = minutesSinceLocalMidnight(/* @__PURE__ */ new Date(), agentTimezone);
14665
- if (overdueMin >= DAY_ROLLOVER_FORCE_GRACE_MIN) {
14666
- log(
14667
- `[persistent-session] Day rollover FORCED for '${codeName}' (yesterday=${current.date}) \u2014 agent busy-blocked ${overdueMin}m past the day boundary (grace ${DAY_ROLLOVER_FORCE_GRACE_MIN}m), restarting anyway to reset context`
14668
- );
14669
- stopPersistentSessionAndForgetMcpBaseline(codeName, "day-rollover");
14670
- agentState.persistentSessionAgents.delete(codeName);
14671
- restartTrigger = "day-rollover";
14672
- dayRolloverForced = true;
14673
- } else {
14674
- log(
14675
- `[persistent-session] Day rollover for '${codeName}' deferred \u2014 agent still active on session ${current.sessionId} (${overdueMin}m past boundary, will force at ${DAY_ROLLOVER_FORCE_GRACE_MIN}m)`
14676
- );
14677
- dayRolloverDeferred = true;
14678
- }
14679
- }
14717
+ const staleForToday = isStaleForToday(codeName, /* @__PURE__ */ new Date(), agentTimezone);
14718
+ if (!staleForToday) pendingDayRolloverReset.delete(codeName);
14719
+ const rolloverSessionHealthy = isSessionHealthy(codeName);
14720
+ const rolloverCurrent = staleForToday && rolloverSessionHealthy ? peekCurrentSession(codeName) : null;
14721
+ const overdueMin = rolloverCurrent ? minutesSinceLocalMidnight(/* @__PURE__ */ new Date(), agentTimezone) : 0;
14722
+ const rolloverDecision = decideDayRolloverAction({
14723
+ staleForToday,
14724
+ sessionHealthy: rolloverSessionHealthy,
14725
+ hasCurrent: rolloverCurrent !== null,
14726
+ idle: rolloverCurrent ? isAgentIdle(projectDir, rolloverCurrent.sessionId) : false,
14727
+ overdueMin,
14728
+ graceMin: DAY_ROLLOVER_FORCE_GRACE_MIN
14729
+ });
14730
+ if (rolloverDecision === "defer-idle" && rolloverCurrent) {
14731
+ if (!pendingDayRolloverReset.has(codeName)) {
14732
+ pendingDayRolloverReset.add(codeName);
14733
+ log(
14734
+ `[persistent-session] Day rollover for '${codeName}' (yesterday=${rolloverCurrent.date}) \u2014 agent idle; keeping the warm session and deferring the fresh-session mint to the first real trigger (no boot booked as utilization) [ENG-8461]`
14735
+ );
14680
14736
  }
14737
+ } else if (rolloverDecision === "force-reset" && rolloverCurrent) {
14738
+ log(
14739
+ `[persistent-session] Day rollover FORCED for '${codeName}' (yesterday=${rolloverCurrent.date}) \u2014 agent busy-blocked ${overdueMin}m past the day boundary (grace ${DAY_ROLLOVER_FORCE_GRACE_MIN}m), restarting anyway to reset context`
14740
+ );
14741
+ stopPersistentSessionAndForgetMcpBaseline(codeName, "day-rollover");
14742
+ agentState.persistentSessionAgents.delete(codeName);
14743
+ pendingDayRolloverReset.delete(codeName);
14744
+ restartTrigger = "day-rollover";
14745
+ dayRolloverForced = true;
14746
+ } else if (rolloverDecision === "busy-wait" && rolloverCurrent) {
14747
+ log(
14748
+ `[persistent-session] Day rollover for '${codeName}' deferred \u2014 agent still active on session ${rolloverCurrent.sessionId} (${overdueMin}m past boundary, will force at ${DAY_ROLLOVER_FORCE_GRACE_MIN}m)`
14749
+ );
14750
+ dayRolloverDeferred = true;
14681
14751
  }
14682
14752
  if (restartTrigger === "day-rollover") {
14683
14753
  rotatePaneLogForDayRollover(codeName, log, agentTimezone);
@@ -14897,7 +14967,15 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
14897
14967
  deferReadyForUsageCap = true;
14898
14968
  }
14899
14969
  }
14900
- for (const task of deferReadyForUsageCap ? [] : ready) {
14970
+ let deferReadyForRollover = false;
14971
+ if (!deferReadyForUsageCap && ready.length > 0 && performLazyDayRolloverReset(codeName, agentTimezone)) {
14972
+ restartTrigger = "day-rollover";
14973
+ deferReadyForRollover = true;
14974
+ log(
14975
+ `[persistent-session] Deferring ${ready.length} ready task(s) for '${codeName}' \u2014 minting a fresh session after an idle day-rollover; schedule NOT advanced, task fires on the fresh session next tick [ENG-8461]`
14976
+ );
14977
+ }
14978
+ for (const task of deferReadyForUsageCap || deferReadyForRollover ? [] : ready) {
14901
14979
  if (KANBAN_WORK_TEMPLATES.has(task.templateId)) {
14902
14980
  const updated = markTaskFired(codeName, task.taskId, "ok");
14903
14981
  claudeSchedulerStates.set(codeName, updated);
@@ -15485,6 +15563,12 @@ async function processDirectChatMessage(agent, msg) {
15485
15563
  await processDirectChatMessageOpencode(agent, msg);
15486
15564
  return;
15487
15565
  }
15566
+ if (performLazyDayRolloverReset(agent.codeName, cachedAgentTimezoneFor(agent.codeName))) {
15567
+ log(
15568
+ `[direct-chat] Reset '${agent.codeName}' to a fresh session on first inbound after an idle day-rollover (msg=${msg.id}) \u2014 leaving pending for durable replay on the fresh session [ENG-8461]`
15569
+ );
15570
+ return;
15571
+ }
15488
15572
  if (isSessionHealthy(agent.codeName)) {
15489
15573
  const useDoorbell = hostFlagStore().getBoolean("direct-chat-doorbell") || isolationMode(agent.codeName) === "docker";
15490
15574
  if (useDoorbell) {
@@ -16599,10 +16683,12 @@ export {
16599
16683
  DAY_ROLLOVER_FORCE_GRACE_MIN,
16600
16684
  applyRestartAcks,
16601
16685
  cancelKanbanNoticeOnDrain,
16686
+ classifyLazyDayRolloverReset,
16602
16687
  claudeCodeUpgradeMarkerPath,
16603
16688
  claudeCodeUpgradeThrottled,
16604
16689
  claudeManagedSettingsPath,
16605
16690
  dashboardRestartBreakerReason,
16691
+ decideDayRolloverAction,
16606
16692
  ensureClaudeManagedSettings,
16607
16693
  extractCharterSlackPeers,
16608
16694
  extractCharterTelegramPeers,