@integrity-labs/agt-cli 0.28.730 → 0.28.732

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.
@@ -17,7 +17,7 @@ import {
17
17
  rotateDailySession,
18
18
  sessionFileExists,
19
19
  todayLocalIso
20
- } from "./chunk-WVYNQJRS.js";
20
+ } from "./chunk-BADE2W6M.js";
21
21
  import {
22
22
  reapOrphanChannelMcps
23
23
  } from "./chunk-XWVM4KPK.js";
@@ -4880,4 +4880,4 @@ export {
4880
4880
  stopAllSessionsAndWait,
4881
4881
  getProjectDir
4882
4882
  };
4883
- //# sourceMappingURL=chunk-KF3IFJVV.js.map
4883
+ //# sourceMappingURL=chunk-QB6TIA3Z.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-KHGH6UKC.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-BHJLZTYX.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-BHULWRDO.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-BZVFVAMR.js.map
@@ -57,7 +57,7 @@ import {
57
57
  safeWriteJsonAtomic,
58
58
  setConfigHash,
59
59
  tripClass
60
- } from "../chunk-3V7HETFZ.js";
60
+ } from "../chunk-DGIYNBDG.js";
61
61
  import {
62
62
  getProjectDir as getProjectDir2,
63
63
  getReadyTasks,
@@ -118,7 +118,7 @@ import {
118
118
  takeZombieDetection,
119
119
  toOpencodeModel,
120
120
  writeEgressAllowlist
121
- } from "../chunk-KF3IFJVV.js";
121
+ } from "../chunk-QB6TIA3Z.js";
122
122
  import {
123
123
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
124
124
  AnchorSessionClient,
@@ -203,7 +203,7 @@ import {
203
203
  subagentActivityAgeSeconds,
204
204
  sumTranscriptUsageInWindow,
205
205
  transcriptActivityAgeSeconds
206
- } from "../chunk-WVYNQJRS.js";
206
+ } from "../chunk-BADE2W6M.js";
207
207
  import {
208
208
  reapOrphanChannelMcps
209
209
  } from "../chunk-XWVM4KPK.js";
@@ -12347,7 +12347,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
12347
12347
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
12348
12348
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
12349
12349
  async function channelInboundActivityAgeSecondsFor(codeName) {
12350
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-ASAPVDUQ.js");
12350
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-457EYSWZ.js");
12351
12351
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
12352
12352
  if (newest === null) return null;
12353
12353
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -12995,7 +12995,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
12995
12995
  var lastVersionCheckAt = 0;
12996
12996
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
12997
12997
  var lastResponsivenessProbeAt = 0;
12998
- var agtCliVersion = true ? "0.28.730" : "dev";
12998
+ var agtCliVersion = true ? "0.28.732" : "dev";
12999
12999
  function resolveBrewPath(execFileSync3) {
13000
13000
  try {
13001
13001
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -14522,7 +14522,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
14522
14522
  if (codeNames.length === 0) return;
14523
14523
  void (async () => {
14524
14524
  try {
14525
- const { collectDiagnostics } = await import("../persistent-session-KHGH6UKC.js");
14525
+ const { collectDiagnostics } = await import("../persistent-session-BHJLZTYX.js");
14526
14526
  await api.post("/host/heartbeat", {
14527
14527
  host_id: hostId,
14528
14528
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -14663,7 +14663,7 @@ async function pollCycleInner() {
14663
14663
  }
14664
14664
  try {
14665
14665
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
14666
- const { collectDiagnostics } = await import("../persistent-session-KHGH6UKC.js");
14666
+ const { collectDiagnostics } = await import("../persistent-session-BHJLZTYX.js");
14667
14667
  const diagCodeNames = [...agentState.persistentSessionAgents];
14668
14668
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
14669
14669
  let tailscaleHostname;
@@ -14832,7 +14832,7 @@ async function pollCycleInner() {
14832
14832
  collectPanelessActivityProbes,
14833
14833
  getResponsivenessIntervalMs,
14834
14834
  occupancyQualificationClassifications
14835
- } = await import("../responsiveness-probe-ASAPVDUQ.js");
14835
+ } = await import("../responsiveness-probe-457EYSWZ.js");
14836
14836
  const probeIntervalMs = getResponsivenessIntervalMs();
14837
14837
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
14838
14838
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -14942,7 +14942,7 @@ async function pollCycleInner() {
14942
14942
  collectResponsivenessProbes,
14943
14943
  livePendingInboundOldestAgeSeconds,
14944
14944
  parkPendingInbound
14945
- } = await import("../responsiveness-probe-ASAPVDUQ.js");
14945
+ } = await import("../responsiveness-probe-457EYSWZ.js");
14946
14946
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
14947
14947
  const wedgeNow = /* @__PURE__ */ new Date();
14948
14948
  const liveAgents = agentState.persistentSessionAgents;
@@ -15098,7 +15098,7 @@ async function pollCycleInner() {
15098
15098
  }
15099
15099
  try {
15100
15100
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
15101
- const { probeSessionAuth } = await import("../session-auth-dead-ABEYQHK3.js");
15101
+ const { probeSessionAuth } = await import("../session-auth-dead-YUPZGR3F.js");
15102
15102
  const observations = [];
15103
15103
  const pendingCacheCommits = [];
15104
15104
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -19009,7 +19009,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
19009
19009
  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}`));
19010
19010
  void (async () => {
19011
19011
  try {
19012
- const { collectDiagnostics } = await import("../persistent-session-KHGH6UKC.js");
19012
+ const { collectDiagnostics } = await import("../persistent-session-BHJLZTYX.js");
19013
19013
  await api.post("/host/heartbeat", {
19014
19014
  host_id: hostId,
19015
19015
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -19055,7 +19055,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
19055
19055
  }
19056
19056
  try {
19057
19057
  const hostId = await getHostId();
19058
- const { collectDiagnostics } = await import("../persistent-session-KHGH6UKC.js");
19058
+ const { collectDiagnostics } = await import("../persistent-session-BHJLZTYX.js");
19059
19059
  await api.post("/host/heartbeat", {
19060
19060
  host_id: hostId,
19061
19061
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -19687,7 +19687,7 @@ async function processClaudePairSessions(agents) {
19687
19687
  killPairSession,
19688
19688
  pairTmuxSession,
19689
19689
  finalizeClaudePairOnboarding
19690
- } = await import("../claude-pair-runtime-BHULWRDO.js");
19690
+ } = await import("../claude-pair-runtime-BZVFVAMR.js");
19691
19691
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
19692
19692
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
19693
19693
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -38165,6 +38165,20 @@ async function readCursorAdvanceBody(res) {
38165
38165
  };
38166
38166
  }
38167
38167
 
38168
+ // src/direct-chat-mcp-instructions.ts
38169
+ function buildDirectChatMcpInstructions() {
38170
+ return [
38171
+ "CRITICAL: every response to a direct-chat <channel> tag MUST go through direct_chat.reply (passing the session_id verbatim). Text in your session WITHOUT a direct_chat.reply call never reaches the operator \u2014 the reply dies inside the agent process.",
38172
+ 'Messages from the webapp Direct Chat arrive as <channel source="direct-chat" session_id="..." user="...">.',
38173
+ "When the tag carries user_name (and sometimes user_email / user_role), that is the verified human you are talking with; address them by name and tailor your reply to who they are. If those attributes are absent, the sender is unknown, so just reply helpfully without personalization.",
38174
+ "Reply using the direct_chat.reply tool, passing the session_id from the tag.",
38175
+ "Always reply to every direct chat message that expects a reply (its meta has requires_reply=true, or no requires_reply field) \u2014 the user is waiting in the webapp.",
38176
+ "NEVER call direct_chat.reply for a NOTICE \u2014 a notification whose meta has requires_reply=false (ENG-6381). It is an informational FYI (e.g. an integration-status update), not a question, and it has ALREADY been acknowledged for you. Replying would wrongly post into the operator\u2019s chat history and burn a turn. Just take it into account and carry on.",
38177
+ "In the rare case you deliberately handle a reply-expecting message without replying (e.g. an internal command), call direct_chat.consume with the session_id so it is not treated as undelivered and redelivered.",
38178
+ "Keep replies concise and helpful. You have full access to all your MCP tools."
38179
+ ].join(" ");
38180
+ }
38181
+
38168
38182
  // src/usage-limit-reactive-decision.ts
38169
38183
  import { createHash } from "crypto";
38170
38184
  function shouldArmWatch(opts) {
@@ -38531,23 +38545,12 @@ var mcp = new Server(
38531
38545
  experimental: { "claude/channel": {} },
38532
38546
  tools: {}
38533
38547
  },
38534
- instructions: [
38535
- // ENG-5845: highest-priority guard first. Without this framing,
38536
- // Opus 4.8 reads the softer "Reply using…" line as a suggestion and
38537
- // emits plain text — the reply lives in the local Claude session
38538
- // but never reaches the operator's session_id through the channel
38539
- // API. Mirrors the slack-channel CRITICAL line shipped in
38540
- // ENG-5830. Total instructions string is ~850 / 2048 chars so we
38541
- // have room to be explicit.
38542
- "CRITICAL: every response to a direct-chat <channel> tag MUST go through direct_chat.reply (passing the session_id verbatim). Text in your session WITHOUT a direct_chat.reply call never reaches the operator \u2014 the reply dies inside the agent process.",
38543
- 'Messages from the webapp Direct Chat arrive as <channel source="direct-chat" session_id="..." user="...">.',
38544
- "When the tag carries user_name (and sometimes user_email / user_role), that is the verified human you are talking with; address them by name and tailor your reply to who they are. If those attributes are absent, the sender is unknown, so just reply helpfully without personalization.",
38545
- "Reply using the direct_chat.reply tool, passing the session_id from the tag.",
38546
- "Always reply to every direct chat message that expects a reply (its meta has requires_reply=true, or no requires_reply field) \u2014 the user is waiting in the webapp.",
38547
- "NEVER call direct_chat.reply for a NOTICE \u2014 a notification whose meta has requires_reply=false (ENG-6381). It is an informational FYI (e.g. an integration-status update), not a question, and it has ALREADY been acknowledged for you. Replying would wrongly post into the operator\u2019s chat history and burn a turn. Just take it into account and carry on.",
38548
- "In the rare case you deliberately handle a reply-expecting message without replying (e.g. an internal command), call direct_chat.consume with the session_id so it is not treated as undelivered and redelivered.",
38549
- "Keep replies concise and helpful. You have full access to all your MCP tools."
38550
- ].join(" ")
38548
+ // NOTE: Claude Code truncates MCP server instructions at 2048 chars.
38549
+ // ENG-9649: built by a pure, length-tested builder
38550
+ // (direct-chat-mcp-instructions.ts). The budget used to be tracked in a
38551
+ // comment here, which had drifted 668 chars out of date without anything
38552
+ // noticing.
38553
+ instructions: buildDirectChatMcpInstructions()
38551
38554
  }
38552
38555
  );
38553
38556
  var claimTracker = new DirectChatClaimTracker();
@@ -40533,6 +40533,24 @@ async function actuateHostRestart(opts) {
40533
40533
  }
40534
40534
  }
40535
40535
 
40536
+ // src/telegram-mcp-instructions.ts
40537
+ var MAX_SKIP_REACTION_UNITS = 8;
40538
+ var REACT_POLICY = `Reacting is egress and does NOT settle anything \u2014 telegram.consume is what settles. Never react in a chat you are barred from, and never post a "this wasn't for me" message.`;
40539
+ function buildTelegramMcpInstructions(opts) {
40540
+ const emoji2 = opts.skipReaction ?? "";
40541
+ const skipReactionOn = opts.skipReactionOn && emoji2.length > 0 && emoji2.length <= MAX_SKIP_REACTION_UNITS;
40542
+ return [
40543
+ "CRITICAL: every response to a Telegram <channel> tag MUST go through telegram.reply with the chat_id from the tag \u2014 typed text never reaches the user. Slow work: interim ack (telegram.reply interim:true), then your FINAL answer as a separate telegram.reply (interim omitted). An ack is not the answer.",
40544
+ 'Messages from Telegram arrive as <channel source="telegram" chat_id="..." user="..." user_name="..." message_id="...">. Pass reply_to_message_id from the tag so the response lands as a quote-reply in busy chats.',
40545
+ "Deliberately NOT replying (a standing rule bars you from that chat, or the message only changed state)? Call telegram.consume with the chat_id and a short reason: it settles the message without posting anything. Without a reply or a consume it counts as undelivered and re-delivers to you forever.",
40546
+ "Inbound attachments: `files` on the tag is a JSON string \u2014 JSON.parse it. An entry with `path` (or top-level `image_path`) is already downloaded \u2014 Read it. Entries with `file_id` and no `path` need telegram.download_attachment (file_id + chat_id), then Read the returned path.",
40547
+ 'For work >30s follow the CLAUDE.md kanban flow: kanban_add \u2192 reply "On it \u2014 tracking here: <kanban URL>" \u2192 in_progress \u2192 reply the result. Simple lookups skip kanban but still reply.',
40548
+ "Address users by user_name; user is the numeric Telegram ID. Resolve ambiguous times against your own Timezone from CLAUDE.md \u2014 do not ask.",
40549
+ "Reactions (telegram.react sparingly \u2014 prefer a reply): \u{1F440} = ack (auto-added, do not duplicate); \u{1F44D} or \u{1F389} = success." + (skipReactionOn ? ` ${emoji2} = seen, not replying.` : "") + " NEVER react to signal failure of YOUR work \u2014 telegram.reply one sentence explaining it. Free-tier emoji only: \u{1F44D} \u{1F44E} \u2764 \u{1F525} \u{1F389} \u{1F64F} \u{1F44C} \u{1F440} \u{1F4AF} \u{1FAE1}.",
40550
+ skipReactionOn ? `${REACT_POLICY} Where engaging IS permitted you may also telegram.react "${emoji2}" after consuming.` : REACT_POLICY
40551
+ ].filter(Boolean).join(" ");
40552
+ }
40553
+
40536
40554
  // src/telegram-channel.ts
40537
40555
  function redactId(id) {
40538
40556
  return createHash3("sha256").update(String(id)).digest("hex").slice(0, 8);
@@ -42953,19 +42971,14 @@ var mcp = new Server(
42953
42971
  tools: {}
42954
42972
  },
42955
42973
  // NOTE: Claude Code truncates MCP server instructions at 2048 chars.
42956
- // Attachments rules live near the top because they get chopped otherwise
42957
- // and the agent silently loses attachment-handling guidance.
42958
- instructions: [
42959
- // Highest-priority lines first — Claude Code truncates this string at
42960
- // 2048 chars, so anything appended late silently disappears.
42961
- "CRITICAL: every response to a Telegram <channel> tag MUST go through telegram.reply with the chat_id from the tag \u2014 typed text never reaches the user. Slow work: interim ack (telegram.reply interim:true), then your FINAL answer as a separate telegram.reply (interim omitted). An ack is not the answer.",
42962
- 'Messages from Telegram arrive as <channel source="telegram" chat_id="..." user="..." user_name="..." message_id="...">. Pass reply_to_message_id from the tag so the response lands as a quote-reply in busy chats.',
42963
- "Inbound attachments: <channel> `files` is a JSON-serialised array \u2014 JSON.parse it. If an entry has `path`, the image is already downloaded \u2014 Read it directly, do NOT call telegram.download_attachment. Use that tool only for entries with `file_id` but NO `path` (PDF, docx, voice, audio, video, animations): pass file_id + chat_id verbatim, then Read the returned path. Single-image messages also get a top-level `image_path`. Caption arrives as channel content. Don't surface internal file-handling errors that don't affect the answer.",
42964
- 'For work >30s follow CLAUDE.md kanban flow: kanban_add \u2192 reply "On it \u2014 tracking here: <kanban URL>" \u2192 move to in_progress \u2192 do the work \u2192 reply with the result. Simple lookups skip kanban but still reply.',
42965
- "Address users by user_name; user is the numeric Telegram ID. Resolve ambiguous times against your own Timezone from CLAUDE.md \u2014 do not ask.",
42966
- "Reaction taxonomy (use telegram.react sparingly \u2014 prefer telegram.reply): \u{1F440} = ack (already auto-added on inbound, do not duplicate); \u{1F44D} or \u{1F389} = success." + (SKIP_REACTION_ON ? ` ${TELEGRAM_SKIP_REACTION} = seen but not replying (see below).` : "") + ` NEVER react to signal failure of YOUR work. On failure, telegram.reply with one sentence explaining what went wrong. Free-tier emoji: \u{1F44D} \u{1F44E} \u2764 \u{1F525} \u{1F389} \u{1F914} \u{1F92F} \u{1F64F} \u{1F44C} \u{1F440} \u{1F4AF} \u270D \u{1FAE1} \u{1F192} \u{1F973} \u{1F494}. (If a message arrived while you were offline you may see a system-posted "can't respond right now" notice \u2014 that's the runtime, not you; don't repeat or apologise for it.)`,
42967
- SKIP_REACTION_ON ? `When you read a message you decide NOT to reply to (nothing useful to add): call telegram.react with emoji "${TELEGRAM_SKIP_REACTION}" so the sender knows you saw it \u2014 never post a "this wasn't for me" message.` : ""
42968
- ].filter(Boolean).join(" ")
42974
+ // ENG-9649: built by a pure, length-tested builder
42975
+ // (telegram-mcp-instructions.ts) so a line can no longer fall off the end
42976
+ // unnoticed — which is exactly what happened to the do-not-reply guidance
42977
+ // while the reaction taxonomy went on pointing at it.
42978
+ instructions: buildTelegramMcpInstructions({
42979
+ skipReactionOn: SKIP_REACTION_ON,
42980
+ skipReaction: TELEGRAM_SKIP_REACTION
42981
+ })
42969
42982
  }
42970
42983
  );
42971
42984
  mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
@@ -46,8 +46,8 @@ import {
46
46
  writeDirectChatSessionState,
47
47
  writeEgressAllowlist,
48
48
  writePersistentClaudeWrapper
49
- } from "./chunk-KF3IFJVV.js";
50
- import "./chunk-WVYNQJRS.js";
49
+ } from "./chunk-QB6TIA3Z.js";
50
+ import "./chunk-BADE2W6M.js";
51
51
  import "./chunk-XWVM4KPK.js";
52
52
  export {
53
53
  EGRESS_BASELINE_DOMAINS,
@@ -98,4 +98,4 @@ export {
98
98
  writeEgressAllowlist,
99
99
  writePersistentClaudeWrapper
100
100
  };
101
- //# sourceMappingURL=persistent-session-KHGH6UKC.js.map
101
+ //# sourceMappingURL=persistent-session-BHJLZTYX.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-KF3IFJVV.js";
4
- import "./chunk-WVYNQJRS.js";
3
+ } from "./chunk-QB6TIA3Z.js";
4
+ import "./chunk-BADE2W6M.js";
5
5
  import "./chunk-XWVM4KPK.js";
6
6
 
7
7
  // src/lib/responsiveness-probe.ts
@@ -745,4 +745,4 @@ export {
745
745
  readAndResetSlackReplyBindingClassifications,
746
746
  readAndResetSlackReplyTargetClassifications
747
747
  };
748
- //# sourceMappingURL=responsiveness-probe-ASAPVDUQ.js.map
748
+ //# sourceMappingURL=responsiveness-probe-457EYSWZ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionTranscriptDir
3
- } from "./chunk-WVYNQJRS.js";
3
+ } from "./chunk-BADE2W6M.js";
4
4
 
5
5
  // src/lib/session-auth-dead.ts
6
6
  import { closeSync, openSync, readSync, readdirSync, statSync } from "fs";
@@ -203,4 +203,4 @@ export {
203
203
  decideSessionAuthState,
204
204
  probeSessionAuth
205
205
  };
206
- //# sourceMappingURL=session-auth-dead-ABEYQHK3.js.map
206
+ //# sourceMappingURL=session-auth-dead-YUPZGR3F.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.730",
3
+ "version": "0.28.732",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {