@integrity-labs/agt-cli 0.26.2-eng5706.1 → 0.27.0

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.
@@ -14296,18 +14296,18 @@ import https from "https";
14296
14296
  import { createHash, randomUUID as randomUUID2 } from "crypto";
14297
14297
  import {
14298
14298
  createWriteStream,
14299
- existsSync,
14300
- mkdirSync as mkdirSync2,
14301
- readFileSync,
14299
+ existsSync as existsSync2,
14300
+ mkdirSync as mkdirSync3,
14301
+ readFileSync as readFileSync2,
14302
14302
  readdirSync,
14303
- renameSync as renameSync2,
14303
+ renameSync as renameSync3,
14304
14304
  statSync,
14305
- unlinkSync as unlinkSync2,
14305
+ unlinkSync as unlinkSync3,
14306
14306
  watch,
14307
- writeFileSync as writeFileSync2
14307
+ writeFileSync as writeFileSync3
14308
14308
  } from "fs";
14309
14309
  import { homedir as homedir2 } from "os";
14310
- import { join as join2 } from "path";
14310
+ import { join as join3 } from "path";
14311
14311
 
14312
14312
  // src/channel-attachments.ts
14313
14313
  import { homedir } from "os";
@@ -15317,6 +15317,75 @@ function createConversationIngestClient(args) {
15317
15317
  };
15318
15318
  }
15319
15319
 
15320
+ // src/inbound-context-client.ts
15321
+ var REQUEST_TIMEOUT_MS4 = 1e4;
15322
+ function createInboundContextClient(args) {
15323
+ if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
15324
+ const fetchImpl = args.fetchImpl ?? fetch;
15325
+ const log = args.log ?? (() => {
15326
+ });
15327
+ const base = args.agtHost.replace(/\/+$/, "");
15328
+ const agentId = args.agentId;
15329
+ const apiKey = args.agtApiKey;
15330
+ let cachedToken = null;
15331
+ let cachedTokenExpiresAt = 0;
15332
+ async function getToken() {
15333
+ if (cachedToken && Date.now() < cachedTokenExpiresAt) return cachedToken;
15334
+ const resp = await fetchImpl(`${base}/host/exchange`, {
15335
+ method: "POST",
15336
+ headers: { "Content-Type": "application/json" },
15337
+ body: JSON.stringify({ host_key: apiKey }),
15338
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS4)
15339
+ });
15340
+ if (!resp.ok) {
15341
+ const body = await resp.text().catch(() => "");
15342
+ throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
15343
+ }
15344
+ const data = await resp.json();
15345
+ cachedToken = data.token;
15346
+ cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : Date.now() + 55 * 6e4;
15347
+ return cachedToken;
15348
+ }
15349
+ async function postOnce(body) {
15350
+ const token = await getToken();
15351
+ return fetchImpl(`${base}/host/inbound-context`, {
15352
+ method: "POST",
15353
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
15354
+ body: JSON.stringify(body),
15355
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS4)
15356
+ });
15357
+ }
15358
+ async function emit(args2) {
15359
+ const body = {
15360
+ agent_id: agentId,
15361
+ source_integration: args2.sourceIntegration,
15362
+ source_external_id: args2.sourceExternalId,
15363
+ ...args2.sourceUrl ? { source_url: args2.sourceUrl } : {}
15364
+ };
15365
+ try {
15366
+ let resp = await postOnce(body);
15367
+ if (resp.status === 401) {
15368
+ cachedToken = null;
15369
+ cachedTokenExpiresAt = 0;
15370
+ resp = await postOnce(body);
15371
+ }
15372
+ if (!resp.ok) {
15373
+ const text = await resp.text().catch(() => "");
15374
+ log(
15375
+ `inbound-context: POST failed (${resp.status}) integration=${args2.sourceIntegration}: ${text.slice(0, 200)}`
15376
+ );
15377
+ }
15378
+ } catch (err) {
15379
+ log(`inbound-context: emit threw integration=${args2.sourceIntegration}: ${err.message}`);
15380
+ }
15381
+ }
15382
+ return {
15383
+ recordInbound(args2) {
15384
+ void emit(args2);
15385
+ }
15386
+ };
15387
+ }
15388
+
15320
15389
  // src/progress-tools.ts
15321
15390
  import { randomUUID } from "crypto";
15322
15391
 
@@ -15741,12 +15810,82 @@ function createTelegramProgressFlush(opts) {
15741
15810
  };
15742
15811
  }
15743
15812
 
15813
+ // src/mcp-spawn-lock.ts
15814
+ import {
15815
+ existsSync,
15816
+ mkdirSync as mkdirSync2,
15817
+ readFileSync,
15818
+ renameSync as renameSync2,
15819
+ unlinkSync as unlinkSync2,
15820
+ writeFileSync as writeFileSync2
15821
+ } from "fs";
15822
+ import { join as join2 } from "path";
15823
+ function defaultIsPidAlive(pid) {
15824
+ if (!Number.isFinite(pid) || pid <= 0) return false;
15825
+ try {
15826
+ process.kill(pid, 0);
15827
+ return true;
15828
+ } catch (err) {
15829
+ const code = err.code;
15830
+ if (code === "ESRCH") return false;
15831
+ return true;
15832
+ }
15833
+ }
15834
+ function acquireMcpSpawnLock(args) {
15835
+ const { agentDir, basename, options = {} } = args;
15836
+ if (!agentDir) return { kind: "no-agent-dir" };
15837
+ const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
15838
+ const selfPid = options.selfPid ?? process.pid;
15839
+ const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
15840
+ const path = join2(agentDir, basename);
15841
+ const existing = readLockHolder(path);
15842
+ if (existing) {
15843
+ if (existing.pid === selfPid) {
15844
+ return { kind: "acquired", path };
15845
+ }
15846
+ if (isPidAlive(existing.pid)) {
15847
+ return { kind: "blocked", path, holder: existing };
15848
+ }
15849
+ }
15850
+ mkdirSync2(agentDir, { recursive: true, mode: 448 });
15851
+ const tmpPath = `${path}.${selfPid}.tmp`;
15852
+ const payload = { pid: selfPid, started_at: now() };
15853
+ writeFileSync2(tmpPath, JSON.stringify(payload), { mode: 384 });
15854
+ renameSync2(tmpPath, path);
15855
+ return { kind: "acquired", path };
15856
+ }
15857
+ function releaseMcpSpawnLock(lockPath, opts = {}) {
15858
+ if (!lockPath) return;
15859
+ const selfPid = opts.selfPid ?? process.pid;
15860
+ const existing = readLockHolder(lockPath);
15861
+ if (!existing) return;
15862
+ if (existing.pid !== selfPid) return;
15863
+ try {
15864
+ unlinkSync2(lockPath);
15865
+ } catch {
15866
+ }
15867
+ }
15868
+ function readLockHolder(path) {
15869
+ if (!existsSync(path)) return null;
15870
+ try {
15871
+ const raw = readFileSync(path, "utf8");
15872
+ const parsed = JSON.parse(raw);
15873
+ const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
15874
+ if (!Number.isFinite(pid) || pid <= 0) return null;
15875
+ const startedAt = typeof parsed.started_at === "string" ? parsed.started_at : "";
15876
+ return { pid, started_at: startedAt };
15877
+ } catch {
15878
+ return null;
15879
+ }
15880
+ }
15881
+
15744
15882
  // src/telegram-channel.ts
15745
15883
  function redactId(id) {
15746
15884
  return createHash("sha256").update(String(id)).digest("hex").slice(0, 8);
15747
15885
  }
15748
15886
  var BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
15749
15887
  var AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
15888
+ var TELEGRAM_AGENT_DIR = AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown" ? join3(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
15750
15889
  var AGT_HOST = process.env.AGT_HOST ?? null;
15751
15890
  var AGT_API_KEY = process.env.AGT_API_KEY ?? null;
15752
15891
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID ?? null;
@@ -15802,6 +15941,13 @@ var conversationIngestClient = createConversationIngestClient({
15802
15941
  log: (line) => process.stderr.write(`telegram-channel(${AGENT_CODE_NAME}): ${line}
15803
15942
  `)
15804
15943
  });
15944
+ var inboundContextClient = createInboundContextClient({
15945
+ agtHost: AGT_HOST,
15946
+ agtApiKey: AGT_API_KEY,
15947
+ agentId: process.env.AGT_AGENT_ID ?? null,
15948
+ log: (line) => process.stderr.write(`telegram-channel(${AGENT_CODE_NAME}): ${line}
15949
+ `)
15950
+ });
15805
15951
  var peerRateApiClient = createDefaultPeerRateApiClient({
15806
15952
  agtHost: AGT_HOST,
15807
15953
  agtApiKey: AGT_API_KEY,
@@ -15823,9 +15969,9 @@ if (!BOT_TOKEN) {
15823
15969
  var stderrLogStream = null;
15824
15970
  if (AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown") {
15825
15971
  try {
15826
- const logDir = join2(homedir2(), ".augmented", AGENT_CODE_NAME);
15827
- mkdirSync2(logDir, { recursive: true });
15828
- stderrLogStream = createWriteStream(join2(logDir, "telegram-channel-stderr.log"), {
15972
+ const logDir = join3(homedir2(), ".augmented", AGENT_CODE_NAME);
15973
+ mkdirSync3(logDir, { recursive: true });
15974
+ stderrLogStream = createWriteStream(join3(logDir, "telegram-channel-stderr.log"), {
15829
15975
  flags: "a",
15830
15976
  mode: 384
15831
15977
  });
@@ -15906,7 +16052,7 @@ async function setMessageReaction(chatId, messageId, emoji2) {
15906
16052
  );
15907
16053
  }
15908
16054
  }
15909
- var RESTART_FLAGS_DIR = join2(homedir2(), ".augmented", "restart-flags");
16055
+ var RESTART_FLAGS_DIR = join3(homedir2(), ".augmented", "restart-flags");
15910
16056
  function buildTelegramHelpMessage(codeName) {
15911
16057
  return [
15912
16058
  `\u{1F916} *Available commands for \`${codeName}\`*`,
@@ -15943,10 +16089,10 @@ async function handleHelpCommand(opts) {
15943
16089
  }
15944
16090
  async function handleRestartCommand(opts) {
15945
16091
  try {
15946
- if (!existsSync(RESTART_FLAGS_DIR)) {
15947
- mkdirSync2(RESTART_FLAGS_DIR, { recursive: true });
16092
+ if (!existsSync2(RESTART_FLAGS_DIR)) {
16093
+ mkdirSync3(RESTART_FLAGS_DIR, { recursive: true });
15948
16094
  }
15949
- const flagPath = join2(RESTART_FLAGS_DIR, `${AGENT_CODE_NAME}.flag`);
16095
+ const flagPath = join3(RESTART_FLAGS_DIR, `${AGENT_CODE_NAME}.flag`);
15950
16096
  const flag = {
15951
16097
  codeName: AGENT_CODE_NAME,
15952
16098
  source: "telegram",
@@ -15954,8 +16100,8 @@ async function handleRestartCommand(opts) {
15954
16100
  reply: { chat_id: opts.chatId, message_id: opts.messageId }
15955
16101
  };
15956
16102
  const tmpPath = `${flagPath}.${process.pid}.${randomUUID2()}.tmp`;
15957
- writeFileSync2(tmpPath, JSON.stringify(flag) + "\n", "utf8");
15958
- renameSync2(tmpPath, flagPath);
16103
+ writeFileSync3(tmpPath, JSON.stringify(flag) + "\n", "utf8");
16104
+ renameSync3(tmpPath, flagPath);
15959
16105
  process.stderr.write(
15960
16106
  `telegram-channel(${AGENT_CODE_NAME}): /restart queued from chat ${redactId(opts.chatId)}
15961
16107
  `
@@ -16062,16 +16208,16 @@ async function classifyRestartCommand(text) {
16062
16208
  if (!ours) return "verification_failed";
16063
16209
  return target === ours ? "act" : "ignore";
16064
16210
  }
16065
- var AGENT_DIR = AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown" ? join2(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
16066
- var PENDING_INBOUND_DIR = AGENT_DIR ? join2(AGENT_DIR, "telegram-pending-inbound") : null;
16067
- var RECOVERY_OUTBOX_DIR = AGENT_DIR ? join2(AGENT_DIR, "telegram-recovery-outbox") : null;
16211
+ var AGENT_DIR = AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown" ? join3(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
16212
+ var PENDING_INBOUND_DIR = AGENT_DIR ? join3(AGENT_DIR, "telegram-pending-inbound") : null;
16213
+ var RECOVERY_OUTBOX_DIR = AGENT_DIR ? join3(AGENT_DIR, "telegram-recovery-outbox") : null;
16068
16214
  function safeMarkerName(chatId, messageId) {
16069
16215
  const safe = (s) => s.replace(/[^A-Za-z0-9_-]/g, "_");
16070
16216
  return `${safe(chatId)}__${safe(messageId)}.json`;
16071
16217
  }
16072
16218
  function pendingInboundPath(chatId, messageId) {
16073
16219
  if (!PENDING_INBOUND_DIR) return null;
16074
- return join2(PENDING_INBOUND_DIR, safeMarkerName(chatId, messageId));
16220
+ return join3(PENDING_INBOUND_DIR, safeMarkerName(chatId, messageId));
16075
16221
  }
16076
16222
  function writePendingInboundMarker(chatId, messageId, chatType) {
16077
16223
  const path = pendingInboundPath(chatId, messageId);
@@ -16083,8 +16229,8 @@ function writePendingInboundMarker(chatId, messageId, chatType) {
16083
16229
  received_at: (/* @__PURE__ */ new Date()).toISOString()
16084
16230
  };
16085
16231
  try {
16086
- mkdirSync2(PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
16087
- writeFileSync2(path, JSON.stringify(marker), { mode: 384 });
16232
+ mkdirSync3(PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
16233
+ writeFileSync3(path, JSON.stringify(marker), { mode: 384 });
16088
16234
  } catch (err) {
16089
16235
  process.stderr.write(
16090
16236
  `telegram-channel(${AGENT_CODE_NAME}): pending-inbound marker write failed: ${err.message}
@@ -16096,7 +16242,7 @@ function clearPendingInboundMarker(chatId, messageId) {
16096
16242
  const path = pendingInboundPath(chatId, messageId);
16097
16243
  if (!path) return;
16098
16244
  try {
16099
- if (existsSync(path)) unlinkSync2(path);
16245
+ if (existsSync2(path)) unlinkSync3(path);
16100
16246
  } catch {
16101
16247
  }
16102
16248
  }
@@ -16115,10 +16261,10 @@ function nextRetryName(filename) {
16115
16261
  async function processRecoveryOutboxFile(filename) {
16116
16262
  if (!RECOVERY_OUTBOX_DIR) return;
16117
16263
  if (filename.endsWith(".poison.json") || filename.endsWith(".tmp")) return;
16118
- const fullPath = join2(RECOVERY_OUTBOX_DIR, filename);
16264
+ const fullPath = join3(RECOVERY_OUTBOX_DIR, filename);
16119
16265
  let payload;
16120
16266
  try {
16121
- const raw = readFileSync(fullPath, "utf-8");
16267
+ const raw = readFileSync2(fullPath, "utf-8");
16122
16268
  payload = JSON.parse(raw);
16123
16269
  } catch (err) {
16124
16270
  process.stderr.write(
@@ -16126,7 +16272,7 @@ async function processRecoveryOutboxFile(filename) {
16126
16272
  `
16127
16273
  );
16128
16274
  try {
16129
- renameSync2(fullPath, `${fullPath}.parse-error.poison`);
16275
+ renameSync3(fullPath, `${fullPath}.parse-error.poison`);
16130
16276
  } catch {
16131
16277
  }
16132
16278
  return;
@@ -16137,7 +16283,7 @@ async function processRecoveryOutboxFile(filename) {
16137
16283
  `
16138
16284
  );
16139
16285
  try {
16140
- renameSync2(fullPath, `${fullPath}.malformed.poison`);
16286
+ renameSync3(fullPath, `${fullPath}.malformed.poison`);
16141
16287
  } catch {
16142
16288
  }
16143
16289
  return;
@@ -16173,7 +16319,7 @@ async function processRecoveryOutboxFile(filename) {
16173
16319
  }
16174
16320
  if (sendSucceeded) {
16175
16321
  try {
16176
- unlinkSync2(fullPath);
16322
+ unlinkSync3(fullPath);
16177
16323
  } catch {
16178
16324
  }
16179
16325
  return;
@@ -16181,7 +16327,7 @@ async function processRecoveryOutboxFile(filename) {
16181
16327
  const next = nextRetryName(filename);
16182
16328
  if (next) {
16183
16329
  try {
16184
- renameSync2(fullPath, join2(RECOVERY_OUTBOX_DIR, next.next));
16330
+ renameSync3(fullPath, join3(RECOVERY_OUTBOX_DIR, next.next));
16185
16331
  if (next.attempt >= MAX_RECOVERY_ATTEMPTS) {
16186
16332
  process.stderr.write(
16187
16333
  `telegram-channel(${AGENT_CODE_NAME}): ghost-reply recovery exhausted retries \u2014 moved to ${next.next}
@@ -16221,7 +16367,7 @@ function scanRecoveryRetries() {
16221
16367
  if (!f.includes(".retry-") || f.endsWith(".poison.json")) continue;
16222
16368
  let mtimeMs;
16223
16369
  try {
16224
- mtimeMs = statSync(join2(RECOVERY_OUTBOX_DIR, f)).mtimeMs;
16370
+ mtimeMs = statSync(join3(RECOVERY_OUTBOX_DIR, f)).mtimeMs;
16225
16371
  } catch {
16226
16372
  continue;
16227
16373
  }
@@ -16233,7 +16379,7 @@ function scanRecoveryRetries() {
16233
16379
  function startRecoveryOutboxWatcher() {
16234
16380
  if (!RECOVERY_OUTBOX_DIR) return;
16235
16381
  try {
16236
- mkdirSync2(RECOVERY_OUTBOX_DIR, { recursive: true, mode: 448 });
16382
+ mkdirSync3(RECOVERY_OUTBOX_DIR, { recursive: true, mode: 448 });
16237
16383
  } catch (err) {
16238
16384
  process.stderr.write(
16239
16385
  `telegram-channel(${AGENT_CODE_NAME}): recovery outbox mkdir failed: ${err.message}
@@ -16251,7 +16397,7 @@ function startRecoveryOutboxWatcher() {
16251
16397
  const watcher = watch(RECOVERY_OUTBOX_DIR, (event, filename) => {
16252
16398
  if (event !== "rename" || !filename) return;
16253
16399
  if (!isFirstAttemptOutboxFile(filename)) return;
16254
- if (existsSync(join2(RECOVERY_OUTBOX_DIR, filename))) {
16400
+ if (existsSync2(join3(RECOVERY_OUTBOX_DIR, filename))) {
16255
16401
  void processRecoveryOutboxFile(filename);
16256
16402
  }
16257
16403
  });
@@ -16272,7 +16418,7 @@ function trackPendingMessage(chatId, messageId, chatType) {
16272
16418
  }
16273
16419
  function sweepTelegramStaleMarkersOnBoot() {
16274
16420
  if (!PENDING_INBOUND_DIR) return;
16275
- if (!existsSync(PENDING_INBOUND_DIR)) return;
16421
+ if (!existsSync2(PENDING_INBOUND_DIR)) return;
16276
16422
  let filenames;
16277
16423
  try {
16278
16424
  filenames = readdirSync(PENDING_INBOUND_DIR);
@@ -16288,17 +16434,17 @@ function sweepTelegramStaleMarkersOnBoot() {
16288
16434
  for (const filename of filenames) {
16289
16435
  if (!filename.endsWith(".json")) continue;
16290
16436
  if (filename.endsWith(".tmp")) continue;
16291
- const fullPath = join2(PENDING_INBOUND_DIR, filename);
16437
+ const fullPath = join3(PENDING_INBOUND_DIR, filename);
16292
16438
  let marker;
16293
16439
  try {
16294
- marker = JSON.parse(readFileSync(fullPath, "utf-8"));
16440
+ marker = JSON.parse(readFileSync2(fullPath, "utf-8"));
16295
16441
  } catch (err) {
16296
16442
  process.stderr.write(
16297
16443
  `telegram-channel(${AGENT_CODE_NAME}): stale-marker parse failed for ${redactId(filename)}: ${err.message}
16298
16444
  `
16299
16445
  );
16300
16446
  try {
16301
- unlinkSync2(fullPath);
16447
+ unlinkSync3(fullPath);
16302
16448
  } catch {
16303
16449
  }
16304
16450
  cleared++;
@@ -16307,7 +16453,7 @@ function sweepTelegramStaleMarkersOnBoot() {
16307
16453
  const { chat_id, message_id, received_at } = marker;
16308
16454
  if (!chat_id || !message_id || !received_at) {
16309
16455
  try {
16310
- unlinkSync2(fullPath);
16456
+ unlinkSync3(fullPath);
16311
16457
  } catch {
16312
16458
  }
16313
16459
  cleared++;
@@ -16316,7 +16462,7 @@ function sweepTelegramStaleMarkersOnBoot() {
16316
16462
  const receivedAtMs = Date.parse(received_at);
16317
16463
  if (!Number.isFinite(receivedAtMs) || receivedAtMs > now || now - receivedAtMs > STALE_MARKER_MS) {
16318
16464
  try {
16319
- unlinkSync2(fullPath);
16465
+ unlinkSync3(fullPath);
16320
16466
  } catch {
16321
16467
  }
16322
16468
  cleared++;
@@ -16335,7 +16481,7 @@ function clearPendingMessage(chatId, messageId) {
16335
16481
  clearPendingInboundMarker(chatId, messageId);
16336
16482
  return;
16337
16483
  }
16338
- if (!PENDING_INBOUND_DIR || !existsSync(PENDING_INBOUND_DIR)) return;
16484
+ if (!PENDING_INBOUND_DIR || !existsSync2(PENDING_INBOUND_DIR)) return;
16339
16485
  const safeChatId = chatId.replace(/[^A-Za-z0-9_-]/g, "_");
16340
16486
  const prefix = `${safeChatId}__`;
16341
16487
  let filenames;
@@ -16348,7 +16494,7 @@ function clearPendingMessage(chatId, messageId) {
16348
16494
  if (!filename.startsWith(prefix)) continue;
16349
16495
  if (!filename.endsWith(".json")) continue;
16350
16496
  try {
16351
- unlinkSync2(join2(PENDING_INBOUND_DIR, filename));
16497
+ unlinkSync3(join3(PENDING_INBOUND_DIR, filename));
16352
16498
  } catch {
16353
16499
  }
16354
16500
  }
@@ -17035,6 +17181,7 @@ var telegramHttp = {
17035
17181
  };
17036
17182
  var nextOffset = 0;
17037
17183
  var isShuttingDown = false;
17184
+ var acquiredLockPath = null;
17038
17185
  async function pollLoop() {
17039
17186
  while (!isShuttingDown) {
17040
17187
  try {
@@ -17286,6 +17433,12 @@ async function pollLoop() {
17286
17433
  is_bot: isFromBot,
17287
17434
  is_peer_agent: !!peerAgentMeta
17288
17435
  });
17436
+ if (!isFromBot && !peerAgentMeta) {
17437
+ inboundContextClient?.recordInbound({
17438
+ sourceIntegration: "telegram",
17439
+ sourceExternalId: String(chatId)
17440
+ });
17441
+ }
17289
17442
  }
17290
17443
  } catch (err) {
17291
17444
  if (isShuttingDown) return;
@@ -17307,6 +17460,10 @@ function shutdown(reason) {
17307
17460
  `telegram-channel(${AGENT_CODE_NAME}): ${reason} \u2014 exiting
17308
17461
  `
17309
17462
  );
17463
+ try {
17464
+ releaseMcpSpawnLock(acquiredLockPath);
17465
+ } catch {
17466
+ }
17310
17467
  setTimeout(() => process.exit(0), 500).unref();
17311
17468
  }
17312
17469
  process.stdin.on("close", () => shutdown("stdin closed"));
@@ -17314,6 +17471,21 @@ process.stdin.on("end", () => shutdown("stdin ended"));
17314
17471
  process.on("SIGTERM", () => shutdown("SIGTERM"));
17315
17472
  process.on("SIGINT", () => shutdown("SIGINT"));
17316
17473
  process.on("SIGHUP", () => shutdown("SIGHUP"));
17474
+ {
17475
+ const lockResult = acquireMcpSpawnLock({
17476
+ agentDir: TELEGRAM_AGENT_DIR,
17477
+ basename: "telegram-channel.lock"
17478
+ });
17479
+ if (lockResult.kind === "blocked") {
17480
+ process.stderr.write(
17481
+ `telegram-channel(${AGENT_CODE_NAME}): another instance pid=${lockResult.holder.pid} already running (since ${lockResult.holder.started_at}), exiting
17482
+ `
17483
+ );
17484
+ process.exit(0);
17485
+ } else if (lockResult.kind === "acquired") {
17486
+ acquiredLockPath = lockResult.path;
17487
+ }
17488
+ }
17317
17489
  process.stderr.write(
17318
17490
  `telegram-channel(${AGENT_CODE_NAME}): started, long-polling getUpdates
17319
17491
  `
@@ -20,8 +20,8 @@ import {
20
20
  stopPersistentSession,
21
21
  takeZombieDetection,
22
22
  writePersistentClaudeWrapper
23
- } from "./chunk-QSDDP7JN.js";
24
- import "./chunk-U3HCB23E.js";
23
+ } from "./chunk-LJZK5RL3.js";
24
+ import "./chunk-BKLEFKUZ.js";
25
25
  import "./chunk-XWVM4KPK.js";
26
26
  export {
27
27
  _internals,
@@ -46,4 +46,4 @@ export {
46
46
  takeZombieDetection,
47
47
  writePersistentClaudeWrapper
48
48
  };
49
- //# sourceMappingURL=persistent-session-K4X76LLB.js.map
49
+ //# sourceMappingURL=persistent-session-SE3E72ET.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-QSDDP7JN.js";
4
- import "./chunk-U3HCB23E.js";
3
+ } from "./chunk-LJZK5RL3.js";
4
+ import "./chunk-BKLEFKUZ.js";
5
5
  import "./chunk-XWVM4KPK.js";
6
6
 
7
7
  // src/lib/responsiveness-probe.ts
@@ -30,4 +30,4 @@ export {
30
30
  collectResponsivenessProbes,
31
31
  getResponsivenessIntervalMs
32
32
  };
33
- //# sourceMappingURL=responsiveness-probe-QBV43SJ7.js.map
33
+ //# sourceMappingURL=responsiveness-probe-MTMEIXEL.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.26.2-eng5706.1",
3
+ "version": "0.27.0",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {