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

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.
@@ -14299,10 +14299,82 @@ function isMode(value) {
14299
14299
  return value === "thinking" || value === "working" || value === "waiting";
14300
14300
  }
14301
14301
 
14302
+ // src/mcp-spawn-lock.ts
14303
+ import {
14304
+ existsSync,
14305
+ mkdirSync,
14306
+ readFileSync,
14307
+ renameSync,
14308
+ unlinkSync,
14309
+ writeFileSync
14310
+ } from "fs";
14311
+ import { join } from "path";
14312
+ function defaultIsPidAlive(pid) {
14313
+ if (!Number.isFinite(pid) || pid <= 0) return false;
14314
+ try {
14315
+ process.kill(pid, 0);
14316
+ return true;
14317
+ } catch (err) {
14318
+ const code = err.code;
14319
+ if (code === "ESRCH") return false;
14320
+ return true;
14321
+ }
14322
+ }
14323
+ function acquireMcpSpawnLock(args) {
14324
+ const { agentDir, basename, options = {} } = args;
14325
+ if (!agentDir) return { kind: "no-agent-dir" };
14326
+ const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
14327
+ const selfPid = options.selfPid ?? process.pid;
14328
+ const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
14329
+ const path = join(agentDir, basename);
14330
+ const existing = readLockHolder(path);
14331
+ if (existing) {
14332
+ if (existing.pid === selfPid) {
14333
+ return { kind: "acquired", path };
14334
+ }
14335
+ if (isPidAlive(existing.pid)) {
14336
+ return { kind: "blocked", path, holder: existing };
14337
+ }
14338
+ }
14339
+ mkdirSync(agentDir, { recursive: true, mode: 448 });
14340
+ const tmpPath = `${path}.${selfPid}.tmp`;
14341
+ const payload = { pid: selfPid, started_at: now() };
14342
+ writeFileSync(tmpPath, JSON.stringify(payload), { mode: 384 });
14343
+ renameSync(tmpPath, path);
14344
+ return { kind: "acquired", path };
14345
+ }
14346
+ function releaseMcpSpawnLock(lockPath, opts = {}) {
14347
+ if (!lockPath) return;
14348
+ const selfPid = opts.selfPid ?? process.pid;
14349
+ const existing = readLockHolder(lockPath);
14350
+ if (!existing) return;
14351
+ if (existing.pid !== selfPid) return;
14352
+ try {
14353
+ unlinkSync(lockPath);
14354
+ } catch {
14355
+ }
14356
+ }
14357
+ function readLockHolder(path) {
14358
+ if (!existsSync(path)) return null;
14359
+ try {
14360
+ const raw = readFileSync(path, "utf8");
14361
+ const parsed = JSON.parse(raw);
14362
+ const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
14363
+ if (!Number.isFinite(pid) || pid <= 0) return null;
14364
+ const startedAt = typeof parsed.started_at === "string" ? parsed.started_at : "";
14365
+ return { pid, started_at: startedAt };
14366
+ } catch {
14367
+ return null;
14368
+ }
14369
+ }
14370
+
14302
14371
  // src/direct-chat-channel.ts
14372
+ import { homedir } from "os";
14373
+ import { join as join2 } from "path";
14303
14374
  var AGT_HOST = process.env.AGT_HOST;
14304
14375
  var AGT_API_KEY = process.env.AGT_API_KEY;
14305
14376
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
14377
+ var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join2(homedir(), ".augmented", AGT_AGENT_ID) : null;
14306
14378
  if (!AGT_HOST || !AGT_API_KEY || !AGT_AGENT_ID) {
14307
14379
  process.stderr.write(
14308
14380
  "direct-chat-channel: Missing AGT_HOST, AGT_API_KEY, or AGT_AGENT_ID. Cannot start.\n"
@@ -14488,6 +14560,22 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
14488
14560
  throw new Error(`Unknown tool: ${name}`);
14489
14561
  });
14490
14562
  await mcp.connect(new StdioServerTransport());
14563
+ var acquiredLockPath = null;
14564
+ {
14565
+ const lockResult = acquireMcpSpawnLock({
14566
+ agentDir: DIRECT_CHAT_AGENT_DIR,
14567
+ basename: "direct-chat-channel.lock"
14568
+ });
14569
+ if (lockResult.kind === "blocked") {
14570
+ process.stderr.write(
14571
+ `direct-chat-channel: another instance pid=${lockResult.holder.pid} already running (since ${lockResult.holder.started_at}), exiting
14572
+ `
14573
+ );
14574
+ process.exit(0);
14575
+ } else if (lockResult.kind === "acquired") {
14576
+ acquiredLockPath = lockResult.path;
14577
+ }
14578
+ }
14491
14579
  process.stderr.write(
14492
14580
  `direct-chat-channel: Started (agent=${AGT_AGENT_ID}, polling=disabled \u2014 using Realtime)
14493
14581
  `
@@ -14498,6 +14586,10 @@ function shutdown(reason) {
14498
14586
  isShuttingDown = true;
14499
14587
  process.stderr.write(`direct-chat-channel: ${reason} \u2014 exiting
14500
14588
  `);
14589
+ try {
14590
+ releaseMcpSpawnLock(acquiredLockPath);
14591
+ } catch {
14592
+ }
14501
14593
  setTimeout(() => process.exit(0), 100).unref();
14502
14594
  }
14503
14595
  process.stdin.on("close", () => shutdown("stdin closed"));
@@ -15607,7 +15607,7 @@ function createSlackBotUserIdClient(args) {
15607
15607
  };
15608
15608
  }
15609
15609
 
15610
- // src/slack-spawn-lock.ts
15610
+ // src/mcp-spawn-lock.ts
15611
15611
  import {
15612
15612
  existsSync,
15613
15613
  mkdirSync as mkdirSync2,
@@ -15617,7 +15617,6 @@ import {
15617
15617
  writeFileSync as writeFileSync2
15618
15618
  } from "fs";
15619
15619
  import { join as join2 } from "path";
15620
- var DEFAULT_LOCK_BASENAME = "slack-channel.lock";
15621
15620
  function defaultIsPidAlive(pid) {
15622
15621
  if (!Number.isFinite(pid) || pid <= 0) return false;
15623
15622
  try {
@@ -15629,12 +15628,13 @@ function defaultIsPidAlive(pid) {
15629
15628
  return true;
15630
15629
  }
15631
15630
  }
15632
- function acquireSlackSpawnLock(slackAgentDir, opts = {}) {
15633
- if (!slackAgentDir) return { kind: "no-agent-dir" };
15634
- const isPidAlive = opts.isPidAlive ?? defaultIsPidAlive;
15635
- const selfPid = opts.selfPid ?? process.pid;
15636
- const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
15637
- const path = join2(slackAgentDir, DEFAULT_LOCK_BASENAME);
15631
+ function acquireMcpSpawnLock(args) {
15632
+ const { agentDir, basename: basename2, options = {} } = args;
15633
+ if (!agentDir) return { kind: "no-agent-dir" };
15634
+ const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
15635
+ const selfPid = options.selfPid ?? process.pid;
15636
+ const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
15637
+ const path = join2(agentDir, basename2);
15638
15638
  const existing = readLockHolder(path);
15639
15639
  if (existing) {
15640
15640
  if (existing.pid === selfPid) {
@@ -15644,14 +15644,14 @@ function acquireSlackSpawnLock(slackAgentDir, opts = {}) {
15644
15644
  return { kind: "blocked", path, holder: existing };
15645
15645
  }
15646
15646
  }
15647
- mkdirSync2(slackAgentDir, { recursive: true, mode: 448 });
15647
+ mkdirSync2(agentDir, { recursive: true, mode: 448 });
15648
15648
  const tmpPath = `${path}.${selfPid}.tmp`;
15649
15649
  const payload = { pid: selfPid, started_at: now() };
15650
15650
  writeFileSync2(tmpPath, JSON.stringify(payload), { mode: 384 });
15651
15651
  renameSync(tmpPath, path);
15652
15652
  return { kind: "acquired", path };
15653
15653
  }
15654
- function releaseSlackSpawnLock(lockPath, opts = {}) {
15654
+ function releaseMcpSpawnLock(lockPath, opts = {}) {
15655
15655
  if (!lockPath) return;
15656
15656
  const selfPid = opts.selfPid ?? process.pid;
15657
15657
  const existing = readLockHolder(lockPath);
@@ -18133,7 +18133,7 @@ function shutdown(reason, exitCode = 0) {
18133
18133
  } catch {
18134
18134
  }
18135
18135
  try {
18136
- releaseSlackSpawnLock(acquiredLockPath);
18136
+ releaseMcpSpawnLock(acquiredLockPath);
18137
18137
  } catch {
18138
18138
  }
18139
18139
  setTimeout(() => process.exit(exitCode), 500).unref();
@@ -18149,7 +18149,10 @@ process.on("unhandledRejection", (reason) => {
18149
18149
  `);
18150
18150
  });
18151
18151
  {
18152
- const lockResult = acquireSlackSpawnLock(SLACK_AGENT_DIR);
18152
+ const lockResult = acquireMcpSpawnLock({
18153
+ agentDir: SLACK_AGENT_DIR,
18154
+ basename: "slack-channel.lock"
18155
+ });
18153
18156
  if (lockResult.kind === "blocked") {
18154
18157
  process.stderr.write(
18155
18158
  `slack-channel: another instance pid=${lockResult.holder.pid} already running (since ${lockResult.holder.started_at}), exiting
@@ -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";
@@ -15741,12 +15741,82 @@ function createTelegramProgressFlush(opts) {
15741
15741
  };
15742
15742
  }
15743
15743
 
15744
+ // src/mcp-spawn-lock.ts
15745
+ import {
15746
+ existsSync,
15747
+ mkdirSync as mkdirSync2,
15748
+ readFileSync,
15749
+ renameSync as renameSync2,
15750
+ unlinkSync as unlinkSync2,
15751
+ writeFileSync as writeFileSync2
15752
+ } from "fs";
15753
+ import { join as join2 } from "path";
15754
+ function defaultIsPidAlive(pid) {
15755
+ if (!Number.isFinite(pid) || pid <= 0) return false;
15756
+ try {
15757
+ process.kill(pid, 0);
15758
+ return true;
15759
+ } catch (err) {
15760
+ const code = err.code;
15761
+ if (code === "ESRCH") return false;
15762
+ return true;
15763
+ }
15764
+ }
15765
+ function acquireMcpSpawnLock(args) {
15766
+ const { agentDir, basename, options = {} } = args;
15767
+ if (!agentDir) return { kind: "no-agent-dir" };
15768
+ const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
15769
+ const selfPid = options.selfPid ?? process.pid;
15770
+ const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
15771
+ const path = join2(agentDir, basename);
15772
+ const existing = readLockHolder(path);
15773
+ if (existing) {
15774
+ if (existing.pid === selfPid) {
15775
+ return { kind: "acquired", path };
15776
+ }
15777
+ if (isPidAlive(existing.pid)) {
15778
+ return { kind: "blocked", path, holder: existing };
15779
+ }
15780
+ }
15781
+ mkdirSync2(agentDir, { recursive: true, mode: 448 });
15782
+ const tmpPath = `${path}.${selfPid}.tmp`;
15783
+ const payload = { pid: selfPid, started_at: now() };
15784
+ writeFileSync2(tmpPath, JSON.stringify(payload), { mode: 384 });
15785
+ renameSync2(tmpPath, path);
15786
+ return { kind: "acquired", path };
15787
+ }
15788
+ function releaseMcpSpawnLock(lockPath, opts = {}) {
15789
+ if (!lockPath) return;
15790
+ const selfPid = opts.selfPid ?? process.pid;
15791
+ const existing = readLockHolder(lockPath);
15792
+ if (!existing) return;
15793
+ if (existing.pid !== selfPid) return;
15794
+ try {
15795
+ unlinkSync2(lockPath);
15796
+ } catch {
15797
+ }
15798
+ }
15799
+ function readLockHolder(path) {
15800
+ if (!existsSync(path)) return null;
15801
+ try {
15802
+ const raw = readFileSync(path, "utf8");
15803
+ const parsed = JSON.parse(raw);
15804
+ const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
15805
+ if (!Number.isFinite(pid) || pid <= 0) return null;
15806
+ const startedAt = typeof parsed.started_at === "string" ? parsed.started_at : "";
15807
+ return { pid, started_at: startedAt };
15808
+ } catch {
15809
+ return null;
15810
+ }
15811
+ }
15812
+
15744
15813
  // src/telegram-channel.ts
15745
15814
  function redactId(id) {
15746
15815
  return createHash("sha256").update(String(id)).digest("hex").slice(0, 8);
15747
15816
  }
15748
15817
  var BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
15749
15818
  var AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
15819
+ var TELEGRAM_AGENT_DIR = AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown" ? join3(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
15750
15820
  var AGT_HOST = process.env.AGT_HOST ?? null;
15751
15821
  var AGT_API_KEY = process.env.AGT_API_KEY ?? null;
15752
15822
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID ?? null;
@@ -15823,9 +15893,9 @@ if (!BOT_TOKEN) {
15823
15893
  var stderrLogStream = null;
15824
15894
  if (AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown") {
15825
15895
  try {
15826
- const logDir = join2(homedir2(), ".augmented", AGENT_CODE_NAME);
15827
- mkdirSync2(logDir, { recursive: true });
15828
- stderrLogStream = createWriteStream(join2(logDir, "telegram-channel-stderr.log"), {
15896
+ const logDir = join3(homedir2(), ".augmented", AGENT_CODE_NAME);
15897
+ mkdirSync3(logDir, { recursive: true });
15898
+ stderrLogStream = createWriteStream(join3(logDir, "telegram-channel-stderr.log"), {
15829
15899
  flags: "a",
15830
15900
  mode: 384
15831
15901
  });
@@ -15906,7 +15976,7 @@ async function setMessageReaction(chatId, messageId, emoji2) {
15906
15976
  );
15907
15977
  }
15908
15978
  }
15909
- var RESTART_FLAGS_DIR = join2(homedir2(), ".augmented", "restart-flags");
15979
+ var RESTART_FLAGS_DIR = join3(homedir2(), ".augmented", "restart-flags");
15910
15980
  function buildTelegramHelpMessage(codeName) {
15911
15981
  return [
15912
15982
  `\u{1F916} *Available commands for \`${codeName}\`*`,
@@ -15943,10 +16013,10 @@ async function handleHelpCommand(opts) {
15943
16013
  }
15944
16014
  async function handleRestartCommand(opts) {
15945
16015
  try {
15946
- if (!existsSync(RESTART_FLAGS_DIR)) {
15947
- mkdirSync2(RESTART_FLAGS_DIR, { recursive: true });
16016
+ if (!existsSync2(RESTART_FLAGS_DIR)) {
16017
+ mkdirSync3(RESTART_FLAGS_DIR, { recursive: true });
15948
16018
  }
15949
- const flagPath = join2(RESTART_FLAGS_DIR, `${AGENT_CODE_NAME}.flag`);
16019
+ const flagPath = join3(RESTART_FLAGS_DIR, `${AGENT_CODE_NAME}.flag`);
15950
16020
  const flag = {
15951
16021
  codeName: AGENT_CODE_NAME,
15952
16022
  source: "telegram",
@@ -15954,8 +16024,8 @@ async function handleRestartCommand(opts) {
15954
16024
  reply: { chat_id: opts.chatId, message_id: opts.messageId }
15955
16025
  };
15956
16026
  const tmpPath = `${flagPath}.${process.pid}.${randomUUID2()}.tmp`;
15957
- writeFileSync2(tmpPath, JSON.stringify(flag) + "\n", "utf8");
15958
- renameSync2(tmpPath, flagPath);
16027
+ writeFileSync3(tmpPath, JSON.stringify(flag) + "\n", "utf8");
16028
+ renameSync3(tmpPath, flagPath);
15959
16029
  process.stderr.write(
15960
16030
  `telegram-channel(${AGENT_CODE_NAME}): /restart queued from chat ${redactId(opts.chatId)}
15961
16031
  `
@@ -16062,16 +16132,16 @@ async function classifyRestartCommand(text) {
16062
16132
  if (!ours) return "verification_failed";
16063
16133
  return target === ours ? "act" : "ignore";
16064
16134
  }
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;
16135
+ var AGENT_DIR = AGENT_CODE_NAME && AGENT_CODE_NAME !== "unknown" ? join3(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
16136
+ var PENDING_INBOUND_DIR = AGENT_DIR ? join3(AGENT_DIR, "telegram-pending-inbound") : null;
16137
+ var RECOVERY_OUTBOX_DIR = AGENT_DIR ? join3(AGENT_DIR, "telegram-recovery-outbox") : null;
16068
16138
  function safeMarkerName(chatId, messageId) {
16069
16139
  const safe = (s) => s.replace(/[^A-Za-z0-9_-]/g, "_");
16070
16140
  return `${safe(chatId)}__${safe(messageId)}.json`;
16071
16141
  }
16072
16142
  function pendingInboundPath(chatId, messageId) {
16073
16143
  if (!PENDING_INBOUND_DIR) return null;
16074
- return join2(PENDING_INBOUND_DIR, safeMarkerName(chatId, messageId));
16144
+ return join3(PENDING_INBOUND_DIR, safeMarkerName(chatId, messageId));
16075
16145
  }
16076
16146
  function writePendingInboundMarker(chatId, messageId, chatType) {
16077
16147
  const path = pendingInboundPath(chatId, messageId);
@@ -16083,8 +16153,8 @@ function writePendingInboundMarker(chatId, messageId, chatType) {
16083
16153
  received_at: (/* @__PURE__ */ new Date()).toISOString()
16084
16154
  };
16085
16155
  try {
16086
- mkdirSync2(PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
16087
- writeFileSync2(path, JSON.stringify(marker), { mode: 384 });
16156
+ mkdirSync3(PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
16157
+ writeFileSync3(path, JSON.stringify(marker), { mode: 384 });
16088
16158
  } catch (err) {
16089
16159
  process.stderr.write(
16090
16160
  `telegram-channel(${AGENT_CODE_NAME}): pending-inbound marker write failed: ${err.message}
@@ -16096,7 +16166,7 @@ function clearPendingInboundMarker(chatId, messageId) {
16096
16166
  const path = pendingInboundPath(chatId, messageId);
16097
16167
  if (!path) return;
16098
16168
  try {
16099
- if (existsSync(path)) unlinkSync2(path);
16169
+ if (existsSync2(path)) unlinkSync3(path);
16100
16170
  } catch {
16101
16171
  }
16102
16172
  }
@@ -16115,10 +16185,10 @@ function nextRetryName(filename) {
16115
16185
  async function processRecoveryOutboxFile(filename) {
16116
16186
  if (!RECOVERY_OUTBOX_DIR) return;
16117
16187
  if (filename.endsWith(".poison.json") || filename.endsWith(".tmp")) return;
16118
- const fullPath = join2(RECOVERY_OUTBOX_DIR, filename);
16188
+ const fullPath = join3(RECOVERY_OUTBOX_DIR, filename);
16119
16189
  let payload;
16120
16190
  try {
16121
- const raw = readFileSync(fullPath, "utf-8");
16191
+ const raw = readFileSync2(fullPath, "utf-8");
16122
16192
  payload = JSON.parse(raw);
16123
16193
  } catch (err) {
16124
16194
  process.stderr.write(
@@ -16126,7 +16196,7 @@ async function processRecoveryOutboxFile(filename) {
16126
16196
  `
16127
16197
  );
16128
16198
  try {
16129
- renameSync2(fullPath, `${fullPath}.parse-error.poison`);
16199
+ renameSync3(fullPath, `${fullPath}.parse-error.poison`);
16130
16200
  } catch {
16131
16201
  }
16132
16202
  return;
@@ -16137,7 +16207,7 @@ async function processRecoveryOutboxFile(filename) {
16137
16207
  `
16138
16208
  );
16139
16209
  try {
16140
- renameSync2(fullPath, `${fullPath}.malformed.poison`);
16210
+ renameSync3(fullPath, `${fullPath}.malformed.poison`);
16141
16211
  } catch {
16142
16212
  }
16143
16213
  return;
@@ -16173,7 +16243,7 @@ async function processRecoveryOutboxFile(filename) {
16173
16243
  }
16174
16244
  if (sendSucceeded) {
16175
16245
  try {
16176
- unlinkSync2(fullPath);
16246
+ unlinkSync3(fullPath);
16177
16247
  } catch {
16178
16248
  }
16179
16249
  return;
@@ -16181,7 +16251,7 @@ async function processRecoveryOutboxFile(filename) {
16181
16251
  const next = nextRetryName(filename);
16182
16252
  if (next) {
16183
16253
  try {
16184
- renameSync2(fullPath, join2(RECOVERY_OUTBOX_DIR, next.next));
16254
+ renameSync3(fullPath, join3(RECOVERY_OUTBOX_DIR, next.next));
16185
16255
  if (next.attempt >= MAX_RECOVERY_ATTEMPTS) {
16186
16256
  process.stderr.write(
16187
16257
  `telegram-channel(${AGENT_CODE_NAME}): ghost-reply recovery exhausted retries \u2014 moved to ${next.next}
@@ -16221,7 +16291,7 @@ function scanRecoveryRetries() {
16221
16291
  if (!f.includes(".retry-") || f.endsWith(".poison.json")) continue;
16222
16292
  let mtimeMs;
16223
16293
  try {
16224
- mtimeMs = statSync(join2(RECOVERY_OUTBOX_DIR, f)).mtimeMs;
16294
+ mtimeMs = statSync(join3(RECOVERY_OUTBOX_DIR, f)).mtimeMs;
16225
16295
  } catch {
16226
16296
  continue;
16227
16297
  }
@@ -16233,7 +16303,7 @@ function scanRecoveryRetries() {
16233
16303
  function startRecoveryOutboxWatcher() {
16234
16304
  if (!RECOVERY_OUTBOX_DIR) return;
16235
16305
  try {
16236
- mkdirSync2(RECOVERY_OUTBOX_DIR, { recursive: true, mode: 448 });
16306
+ mkdirSync3(RECOVERY_OUTBOX_DIR, { recursive: true, mode: 448 });
16237
16307
  } catch (err) {
16238
16308
  process.stderr.write(
16239
16309
  `telegram-channel(${AGENT_CODE_NAME}): recovery outbox mkdir failed: ${err.message}
@@ -16251,7 +16321,7 @@ function startRecoveryOutboxWatcher() {
16251
16321
  const watcher = watch(RECOVERY_OUTBOX_DIR, (event, filename) => {
16252
16322
  if (event !== "rename" || !filename) return;
16253
16323
  if (!isFirstAttemptOutboxFile(filename)) return;
16254
- if (existsSync(join2(RECOVERY_OUTBOX_DIR, filename))) {
16324
+ if (existsSync2(join3(RECOVERY_OUTBOX_DIR, filename))) {
16255
16325
  void processRecoveryOutboxFile(filename);
16256
16326
  }
16257
16327
  });
@@ -16272,7 +16342,7 @@ function trackPendingMessage(chatId, messageId, chatType) {
16272
16342
  }
16273
16343
  function sweepTelegramStaleMarkersOnBoot() {
16274
16344
  if (!PENDING_INBOUND_DIR) return;
16275
- if (!existsSync(PENDING_INBOUND_DIR)) return;
16345
+ if (!existsSync2(PENDING_INBOUND_DIR)) return;
16276
16346
  let filenames;
16277
16347
  try {
16278
16348
  filenames = readdirSync(PENDING_INBOUND_DIR);
@@ -16288,17 +16358,17 @@ function sweepTelegramStaleMarkersOnBoot() {
16288
16358
  for (const filename of filenames) {
16289
16359
  if (!filename.endsWith(".json")) continue;
16290
16360
  if (filename.endsWith(".tmp")) continue;
16291
- const fullPath = join2(PENDING_INBOUND_DIR, filename);
16361
+ const fullPath = join3(PENDING_INBOUND_DIR, filename);
16292
16362
  let marker;
16293
16363
  try {
16294
- marker = JSON.parse(readFileSync(fullPath, "utf-8"));
16364
+ marker = JSON.parse(readFileSync2(fullPath, "utf-8"));
16295
16365
  } catch (err) {
16296
16366
  process.stderr.write(
16297
16367
  `telegram-channel(${AGENT_CODE_NAME}): stale-marker parse failed for ${redactId(filename)}: ${err.message}
16298
16368
  `
16299
16369
  );
16300
16370
  try {
16301
- unlinkSync2(fullPath);
16371
+ unlinkSync3(fullPath);
16302
16372
  } catch {
16303
16373
  }
16304
16374
  cleared++;
@@ -16307,7 +16377,7 @@ function sweepTelegramStaleMarkersOnBoot() {
16307
16377
  const { chat_id, message_id, received_at } = marker;
16308
16378
  if (!chat_id || !message_id || !received_at) {
16309
16379
  try {
16310
- unlinkSync2(fullPath);
16380
+ unlinkSync3(fullPath);
16311
16381
  } catch {
16312
16382
  }
16313
16383
  cleared++;
@@ -16316,7 +16386,7 @@ function sweepTelegramStaleMarkersOnBoot() {
16316
16386
  const receivedAtMs = Date.parse(received_at);
16317
16387
  if (!Number.isFinite(receivedAtMs) || receivedAtMs > now || now - receivedAtMs > STALE_MARKER_MS) {
16318
16388
  try {
16319
- unlinkSync2(fullPath);
16389
+ unlinkSync3(fullPath);
16320
16390
  } catch {
16321
16391
  }
16322
16392
  cleared++;
@@ -16335,7 +16405,7 @@ function clearPendingMessage(chatId, messageId) {
16335
16405
  clearPendingInboundMarker(chatId, messageId);
16336
16406
  return;
16337
16407
  }
16338
- if (!PENDING_INBOUND_DIR || !existsSync(PENDING_INBOUND_DIR)) return;
16408
+ if (!PENDING_INBOUND_DIR || !existsSync2(PENDING_INBOUND_DIR)) return;
16339
16409
  const safeChatId = chatId.replace(/[^A-Za-z0-9_-]/g, "_");
16340
16410
  const prefix = `${safeChatId}__`;
16341
16411
  let filenames;
@@ -16348,7 +16418,7 @@ function clearPendingMessage(chatId, messageId) {
16348
16418
  if (!filename.startsWith(prefix)) continue;
16349
16419
  if (!filename.endsWith(".json")) continue;
16350
16420
  try {
16351
- unlinkSync2(join2(PENDING_INBOUND_DIR, filename));
16421
+ unlinkSync3(join3(PENDING_INBOUND_DIR, filename));
16352
16422
  } catch {
16353
16423
  }
16354
16424
  }
@@ -17035,6 +17105,7 @@ var telegramHttp = {
17035
17105
  };
17036
17106
  var nextOffset = 0;
17037
17107
  var isShuttingDown = false;
17108
+ var acquiredLockPath = null;
17038
17109
  async function pollLoop() {
17039
17110
  while (!isShuttingDown) {
17040
17111
  try {
@@ -17307,6 +17378,10 @@ function shutdown(reason) {
17307
17378
  `telegram-channel(${AGENT_CODE_NAME}): ${reason} \u2014 exiting
17308
17379
  `
17309
17380
  );
17381
+ try {
17382
+ releaseMcpSpawnLock(acquiredLockPath);
17383
+ } catch {
17384
+ }
17310
17385
  setTimeout(() => process.exit(0), 500).unref();
17311
17386
  }
17312
17387
  process.stdin.on("close", () => shutdown("stdin closed"));
@@ -17314,6 +17389,21 @@ process.stdin.on("end", () => shutdown("stdin ended"));
17314
17389
  process.on("SIGTERM", () => shutdown("SIGTERM"));
17315
17390
  process.on("SIGINT", () => shutdown("SIGINT"));
17316
17391
  process.on("SIGHUP", () => shutdown("SIGHUP"));
17392
+ {
17393
+ const lockResult = acquireMcpSpawnLock({
17394
+ agentDir: TELEGRAM_AGENT_DIR,
17395
+ basename: "telegram-channel.lock"
17396
+ });
17397
+ if (lockResult.kind === "blocked") {
17398
+ process.stderr.write(
17399
+ `telegram-channel(${AGENT_CODE_NAME}): another instance pid=${lockResult.holder.pid} already running (since ${lockResult.holder.started_at}), exiting
17400
+ `
17401
+ );
17402
+ process.exit(0);
17403
+ } else if (lockResult.kind === "acquired") {
17404
+ acquiredLockPath = lockResult.path;
17405
+ }
17406
+ }
17317
17407
  process.stderr.write(
17318
17408
  `telegram-channel(${AGENT_CODE_NAME}): started, long-polling getUpdates
17319
17409
  `
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.26.2",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {