@integrity-labs/agt-cli 0.27.9-test.13 → 0.27.9-test.14

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.
Files changed (35) hide show
  1. package/dist/bin/agt.js +4 -4
  2. package/dist/chunk-354FAVQR.js +173 -0
  3. package/dist/chunk-354FAVQR.js.map +1 -0
  4. package/dist/{chunk-MQJ5DMPT.js → chunk-7GKJZBTB.js} +111 -204
  5. package/dist/chunk-7GKJZBTB.js.map +1 -0
  6. package/dist/{chunk-HR5T2RQF.js → chunk-I3YS5WFV.js} +3 -1
  7. package/dist/chunk-I3YS5WFV.js.map +1 -0
  8. package/dist/{chunk-VNIHFGA2.js → chunk-R7NKCGWN.js} +341 -46
  9. package/dist/chunk-R7NKCGWN.js.map +1 -0
  10. package/dist/{chunk-I2OTQJH3.js → chunk-WOOYOAPG.js} +2644 -2142
  11. package/dist/chunk-WOOYOAPG.js.map +1 -0
  12. package/dist/{claude-pair-runtime-F6USL3EW.js → claude-pair-runtime-GIUCD7IG.js} +2 -2
  13. package/dist/{claude-scheduler-EM24LTGV.js → claude-scheduler-FATCLHDM.js} +2 -2
  14. package/dist/daily-session-PNQX5URX.js +27 -0
  15. package/dist/lib/manager-worker.js +1125 -149
  16. package/dist/lib/manager-worker.js.map +1 -1
  17. package/dist/mcp/augmented-admin.js +21335 -0
  18. package/dist/mcp/index.js +121 -4
  19. package/dist/mcp/slack-channel.js +845 -208
  20. package/dist/mcp/teams-channel.js +73 -29
  21. package/dist/mcp/telegram-channel.js +579 -157
  22. package/dist/{persistent-session-OL5EDYB4.js → persistent-session-35PWSTLO.js} +10 -3
  23. package/dist/persistent-session-35PWSTLO.js.map +1 -0
  24. package/dist/responsiveness-probe-MA4M2QM4.js +158 -0
  25. package/dist/responsiveness-probe-MA4M2QM4.js.map +1 -0
  26. package/package.json +3 -2
  27. package/dist/chunk-HR5T2RQF.js.map +0 -1
  28. package/dist/chunk-I2OTQJH3.js.map +0 -1
  29. package/dist/chunk-MQJ5DMPT.js.map +0 -1
  30. package/dist/chunk-VNIHFGA2.js.map +0 -1
  31. package/dist/responsiveness-probe-B6LJJRUD.js +0 -74
  32. package/dist/responsiveness-probe-B6LJJRUD.js.map +0 -1
  33. /package/dist/{claude-pair-runtime-F6USL3EW.js.map → claude-pair-runtime-GIUCD7IG.js.map} +0 -0
  34. /package/dist/{claude-scheduler-EM24LTGV.js.map → claude-scheduler-FATCLHDM.js.map} +0 -0
  35. /package/dist/{persistent-session-OL5EDYB4.js.map → daily-session-PNQX5URX.js.map} +0 -0
@@ -1,16 +1,22 @@
1
1
  import {
2
2
  claudeModelAlias,
3
3
  isClaudeFastMode
4
- } from "./chunk-I2OTQJH3.js";
4
+ } from "./chunk-WOOYOAPG.js";
5
+ import {
6
+ getOrCreateDailySession,
7
+ markDailySessionSpawn,
8
+ rotateDailySession,
9
+ sessionFileExists
10
+ } from "./chunk-354FAVQR.js";
5
11
  import {
6
12
  reapOrphanChannelMcps
7
13
  } from "./chunk-XWVM4KPK.js";
8
14
 
9
15
  // src/lib/persistent-session.ts
10
16
  import { spawn, execSync, execFileSync as execFileSync3 } from "child_process";
11
- import { join as join2, dirname } from "path";
12
- import { homedir as homedir2, platform, userInfo } from "os";
13
- import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, chmodSync, copyFileSync, rmSync } from "fs";
17
+ import { join, dirname } from "path";
18
+ import { homedir, platform, userInfo } from "os";
19
+ import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync, writeFileSync as writeFileSync2, appendFileSync, mkdirSync, chmodSync, copyFileSync, rmSync } from "fs";
14
20
  import { fileURLToPath } from "url";
15
21
 
16
22
  // src/lib/mcp-sanitize.ts
@@ -108,6 +114,20 @@ function findMissingSubstitutionVars(mcpConfig, env) {
108
114
  function formatMissingVar(f) {
109
115
  return `[mcp-env-substitution] missing var=${f.varName} server=${f.server} state=${f.state}`;
110
116
  }
117
+ function expandTemplateVars(value, env) {
118
+ const unresolved = /* @__PURE__ */ new Set();
119
+ const expanded = value.replace(TEMPLATE_VAR_RE, (literal, name) => {
120
+ if (LATE_BOUND_VARS.has(name)) {
121
+ unresolved.add(name);
122
+ return literal;
123
+ }
124
+ const resolved = env[name];
125
+ if (resolved !== void 0 && resolved.trim() !== "") return resolved;
126
+ unresolved.add(name);
127
+ return literal;
128
+ });
129
+ return { value: expanded, unresolved: [...unresolved] };
130
+ }
111
131
  function parseEnvIntegrations(content) {
112
132
  const out = {};
113
133
  for (const line of content.split("\n")) {
@@ -139,156 +159,7 @@ function probeMcpEnvSubstitution(args) {
139
159
  }
140
160
 
141
161
  // src/lib/persistent-session.ts
142
- import { randomUUID as randomUUID2 } from "crypto";
143
-
144
- // src/lib/daily-session.ts
145
162
  import { randomUUID } from "crypto";
146
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3, renameSync, statSync, writeFileSync as writeFileSync2 } from "fs";
147
- import { homedir } from "os";
148
- import { join } from "path";
149
- var HISTORY_DAYS = 7;
150
- function profileDir(codeName) {
151
- return join(homedir(), ".augmented", codeName);
152
- }
153
- function dailySessionPath(codeName) {
154
- return join(profileDir(codeName), "daily-session.json");
155
- }
156
- function todayLocalIso(now = /* @__PURE__ */ new Date(), timezone) {
157
- if (timezone) {
158
- try {
159
- const fmt = new Intl.DateTimeFormat("en-CA", {
160
- timeZone: timezone,
161
- year: "numeric",
162
- month: "2-digit",
163
- day: "2-digit"
164
- });
165
- return fmt.format(now);
166
- } catch {
167
- }
168
- }
169
- const y = now.getFullYear();
170
- const m = String(now.getMonth() + 1).padStart(2, "0");
171
- const d = String(now.getDate()).padStart(2, "0");
172
- return `${y}-${m}-${d}`;
173
- }
174
- function readFile(codeName) {
175
- const path = dailySessionPath(codeName);
176
- if (!existsSync2(path)) return { current: null, history: [] };
177
- try {
178
- const raw = readFileSync3(path, "utf-8");
179
- const parsed = JSON.parse(raw);
180
- return {
181
- current: parsed.current ?? null,
182
- history: Array.isArray(parsed.history) ? parsed.history : []
183
- };
184
- } catch {
185
- return { current: null, history: [] };
186
- }
187
- }
188
- function writeFile(codeName, data) {
189
- const dir = profileDir(codeName);
190
- mkdirSync(dir, { recursive: true });
191
- const finalPath = dailySessionPath(codeName);
192
- const tmpPath = `${finalPath}.${process.pid}.${randomUUID()}.tmp`;
193
- writeFileSync2(tmpPath, JSON.stringify(data, null, 2), "utf-8");
194
- renameSync(tmpPath, finalPath);
195
- }
196
- function trimHistory(history, now, timezone) {
197
- const cutoff = new Date(now);
198
- cutoff.setDate(cutoff.getDate() - HISTORY_DAYS);
199
- const cutoffIso = todayLocalIso(cutoff, timezone);
200
- return history.filter((h) => h.date >= cutoffIso).slice(0, HISTORY_DAYS);
201
- }
202
- function getOrCreateDailySession(codeName, now = /* @__PURE__ */ new Date(), timezone) {
203
- const today = todayLocalIso(now, timezone);
204
- const file = readFile(codeName);
205
- if (file.current && file.current.date === today) {
206
- return { sessionId: file.current.sessionId, isNew: false };
207
- }
208
- const next = {
209
- date: today,
210
- sessionId: randomUUID(),
211
- startedAt: now.toISOString()
212
- };
213
- const history = trimHistory(
214
- [...file.current ? [file.current] : [], ...file.history],
215
- now,
216
- timezone
217
- );
218
- writeFile(codeName, { current: next, history });
219
- return { sessionId: next.sessionId, isNew: true };
220
- }
221
- function markDailySessionSpawn(codeName, sessionId, now = /* @__PURE__ */ new Date(), timezone) {
222
- const today = todayLocalIso(now, timezone);
223
- const file = readFile(codeName);
224
- if (file.current && file.current.date === today && file.current.sessionId === sessionId) {
225
- return;
226
- }
227
- const next = {
228
- date: today,
229
- sessionId,
230
- startedAt: now.toISOString()
231
- };
232
- const history = trimHistory(
233
- [...file.current ? [file.current] : [], ...file.history],
234
- now,
235
- timezone
236
- );
237
- writeFile(codeName, { current: next, history });
238
- }
239
- function rotateDailySession(codeName, now = /* @__PURE__ */ new Date(), timezone) {
240
- const today = todayLocalIso(now, timezone);
241
- const file = readFile(codeName);
242
- const next = {
243
- date: today,
244
- sessionId: randomUUID(),
245
- startedAt: now.toISOString()
246
- };
247
- const history = trimHistory(
248
- [...file.current ? [file.current] : [], ...file.history],
249
- now,
250
- timezone
251
- );
252
- writeFile(codeName, { current: next, history });
253
- return next.sessionId;
254
- }
255
- function encodeProjectPath(projectDir) {
256
- return "-" + projectDir.replace(/^\//, "").replace(/[/.]/g, "-");
257
- }
258
- function sessionFileExists(projectDir, sessionId) {
259
- const path = join(
260
- homedir(),
261
- ".claude",
262
- "projects",
263
- encodeProjectPath(projectDir),
264
- `${sessionId}.jsonl`
265
- );
266
- return existsSync2(path);
267
- }
268
- function sessionTranscriptDir(projectDir) {
269
- return join(homedir(), ".claude", "projects", encodeProjectPath(projectDir));
270
- }
271
- function sessionFilePath(projectDir, sessionId) {
272
- return join(sessionTranscriptDir(projectDir), `${sessionId}.jsonl`);
273
- }
274
- function isAgentIdle(projectDir, sessionId, idleSeconds = 60, now = /* @__PURE__ */ new Date()) {
275
- const path = sessionFilePath(projectDir, sessionId);
276
- if (!existsSync2(path)) return true;
277
- try {
278
- const mtimeMs = statSync(path).mtimeMs;
279
- return now.getTime() - mtimeMs >= idleSeconds * 1e3;
280
- } catch {
281
- return false;
282
- }
283
- }
284
- function isStaleForToday(codeName, now = /* @__PURE__ */ new Date(), timezone) {
285
- const file = readFile(codeName);
286
- if (!file.current) return false;
287
- return file.current.date !== todayLocalIso(now, timezone);
288
- }
289
- function peekCurrentSession(codeName) {
290
- return readFile(codeName).current;
291
- }
292
163
 
293
164
  // ../../packages/core/dist/runtime/session-probe.js
294
165
  import { execFileSync } from "child_process";
@@ -570,7 +441,7 @@ function syncClaudeCredsToRoot() {
570
441
  if (platform() !== "linux") return true;
571
442
  if (typeof process.getuid !== "function" || process.getuid() !== 0) return true;
572
443
  for (const filename of [".credentials.json", "credentials.json"]) {
573
- if (existsSync3(join2("/root/.claude", filename))) return true;
444
+ if (existsSync2(join("/root/.claude", filename))) return true;
574
445
  }
575
446
  let sourcePath = null;
576
447
  try {
@@ -578,8 +449,8 @@ function syncClaudeCredsToRoot() {
578
449
  outer: for (const entry of entries) {
579
450
  if (!entry.isDirectory()) continue;
580
451
  for (const filename of [".credentials.json", "credentials.json"]) {
581
- const candidate = join2("/home", entry.name, ".claude", filename);
582
- if (existsSync3(candidate)) {
452
+ const candidate = join("/home", entry.name, ".claude", filename);
453
+ if (existsSync2(candidate)) {
583
454
  sourcePath = candidate;
584
455
  break outer;
585
456
  }
@@ -590,9 +461,9 @@ function syncClaudeCredsToRoot() {
590
461
  if (!sourcePath) return false;
591
462
  const targetDir = "/root/.claude";
592
463
  const sourceFilename = sourcePath.endsWith("credentials.json") && !sourcePath.endsWith(".credentials.json") ? "credentials.json" : ".credentials.json";
593
- const targetPath = join2(targetDir, sourceFilename);
464
+ const targetPath = join(targetDir, sourceFilename);
594
465
  try {
595
- if (!existsSync3(targetDir)) mkdirSync2(targetDir, { recursive: true, mode: 448 });
466
+ if (!existsSync2(targetDir)) mkdirSync(targetDir, { recursive: true, mode: 448 });
596
467
  copyFileSync(sourcePath, targetPath);
597
468
  chmodSync(targetPath, 384);
598
469
  return true;
@@ -604,13 +475,13 @@ var cachedClaudePath = null;
604
475
  function resolveClaudeBinary() {
605
476
  if (cachedClaudePath) return cachedClaudePath;
606
477
  const override = process.env.CLAUDE_PATH;
607
- if (override && existsSync3(override)) {
478
+ if (override && existsSync2(override)) {
608
479
  cachedClaudePath = override;
609
480
  return override;
610
481
  }
611
482
  try {
612
483
  const out = execSync("which claude 2>/dev/null", { encoding: "utf-8" }).trim();
613
- if (out && existsSync3(out)) {
484
+ if (out && existsSync2(out)) {
614
485
  cachedClaudePath = out;
615
486
  return out;
616
487
  }
@@ -622,7 +493,7 @@ function resolveClaudeBinary() {
622
493
  "/usr/local/bin/claude"
623
494
  ];
624
495
  for (const p of candidates) {
625
- if (existsSync3(p)) {
496
+ if (existsSync2(p)) {
626
497
  cachedClaudePath = p;
627
498
  return p;
628
499
  }
@@ -631,8 +502,8 @@ function resolveClaudeBinary() {
631
502
  }
632
503
  function writePersistentClaudeWrapper(args) {
633
504
  const { projectDir, claudeBin, initPrompt, claudeArgsJoined } = args;
634
- const envIntegrationsPath = join2(projectDir, ".env.integrations");
635
- const wrapperPath = join2(projectDir, ".claude", "persistent-claude.sh");
505
+ const envIntegrationsPath = join(projectDir, ".env.integrations");
506
+ const wrapperPath = join(projectDir, ".claude", "persistent-claude.sh");
636
507
  const wrapperLines = [
637
508
  "#!/usr/bin/env bash",
638
509
  "set -e",
@@ -640,7 +511,7 @@ function writePersistentClaudeWrapper(args) {
640
511
  // --dangerously-skip-permissions on dedicated EC2 hosts.
641
512
  "export IS_SANDBOX=1"
642
513
  ];
643
- if (existsSync3(envIntegrationsPath)) {
514
+ if (existsSync2(envIntegrationsPath)) {
644
515
  wrapperLines.push(
645
516
  "set -a",
646
517
  `source ${JSON.stringify(envIntegrationsPath)}`,
@@ -651,15 +522,15 @@ function writePersistentClaudeWrapper(args) {
651
522
  wrapperLines.push(
652
523
  `exec ${JSON.stringify(claudeBin)} ${initPromptArg}${claudeArgsJoined}`
653
524
  );
654
- mkdirSync2(join2(projectDir, ".claude"), { recursive: true });
655
- writeFileSync3(wrapperPath, wrapperLines.join("\n") + "\n", { mode: 448 });
525
+ mkdirSync(join(projectDir, ".claude"), { recursive: true });
526
+ writeFileSync2(wrapperPath, wrapperLines.join("\n") + "\n", { mode: 448 });
656
527
  chmodSync(wrapperPath, 448);
657
528
  return wrapperPath;
658
529
  }
659
530
  function collectMcpServerNames(mcpConfigPath) {
660
- if (!existsSync3(mcpConfigPath)) return [];
531
+ if (!existsSync2(mcpConfigPath)) return [];
661
532
  try {
662
- const data = JSON.parse(readFileSync4(mcpConfigPath, "utf-8"));
533
+ const data = JSON.parse(readFileSync3(mcpConfigPath, "utf-8"));
663
534
  const servers = data.mcpServers;
664
535
  return servers ? Object.keys(servers) : [];
665
536
  } catch {
@@ -672,8 +543,8 @@ function getAcpxBin() {
672
543
  const moduleDir = dirname(fileURLToPath(import.meta.url));
673
544
  let dir = moduleDir;
674
545
  for (let i = 0; i < 6; i++) {
675
- const candidate = join2(dir, "node_modules", ".bin", "acpx");
676
- if (existsSync3(candidate)) {
546
+ const candidate = join(dir, "node_modules", ".bin", "acpx");
547
+ if (existsSync2(candidate)) {
677
548
  _acpxBin = candidate;
678
549
  return _acpxBin;
679
550
  }
@@ -703,6 +574,16 @@ function defaultAcpxSessionProbe(acpxBin, projectDir) {
703
574
  }
704
575
  var acpxSessionProbe = defaultAcpxSessionProbe;
705
576
  var acpxSessionAvailableCache = /* @__PURE__ */ new Map();
577
+ var acpxExecFailureCounts = /* @__PURE__ */ new Map();
578
+ function takeAcpxExecFailureCount(codeName) {
579
+ const count = acpxExecFailureCounts.get(codeName) ?? 0;
580
+ acpxExecFailureCounts.delete(codeName);
581
+ return count;
582
+ }
583
+ function creditAcpxExecFailureCount(codeName, count) {
584
+ if (count <= 0) return;
585
+ acpxExecFailureCounts.set(codeName, (acpxExecFailureCounts.get(codeName) ?? 0) + count);
586
+ }
706
587
  function hasAcpxSession(acpxBin, projectDir, codeName) {
707
588
  const cached = acpxSessionAvailableCache.get(codeName);
708
589
  if (cached !== void 0) return cached;
@@ -711,15 +592,15 @@ function hasAcpxSession(acpxBin, projectDir, codeName) {
711
592
  return available;
712
593
  }
713
594
  var sessions = /* @__PURE__ */ new Map();
714
- var PANE_LOG_DIR = join2(homedir2(), ".augmented");
595
+ var PANE_LOG_DIR = join(homedir(), ".augmented");
715
596
  var PANE_TAIL_LINES = 20;
716
597
  function paneLogPath(codeName) {
717
- return join2(PANE_LOG_DIR, codeName, "pane.log");
598
+ return join(PANE_LOG_DIR, codeName, "pane.log");
718
599
  }
719
600
  function setupPaneLog(tmuxSession, codeName, log) {
720
601
  const logPath = paneLogPath(codeName);
721
602
  try {
722
- mkdirSync2(dirname(logPath), { recursive: true });
603
+ mkdirSync(dirname(logPath), { recursive: true });
723
604
  appendFileSync(
724
605
  logPath,
725
606
  `
@@ -737,9 +618,9 @@ function setupPaneLog(tmuxSession, codeName, log) {
737
618
  }
738
619
  function readPaneLogTail(codeName, lines = PANE_TAIL_LINES) {
739
620
  const logPath = paneLogPath(codeName);
740
- if (!existsSync3(logPath)) return null;
621
+ if (!existsSync2(logPath)) return null;
741
622
  try {
742
- const raw = readFileSync4(logPath, "utf-8");
623
+ const raw = readFileSync3(logPath, "utf-8");
743
624
  if (!raw) return null;
744
625
  const stripped = raw.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "");
745
626
  const all = stripped.split("\n").filter((l) => l.length > 0);
@@ -770,6 +651,15 @@ function prepareForRespawn(codeName) {
770
651
  }
771
652
  return null;
772
653
  }
654
+ function rotateSessionForWedge(codeName, now = /* @__PURE__ */ new Date()) {
655
+ const session = sessions.get(codeName);
656
+ const newId = rotateDailySession(codeName, now, session?.agentTimezone ?? void 0);
657
+ if (session) {
658
+ session.consecutiveSameUuidFailures = 0;
659
+ session.lastFailureSessionId = null;
660
+ }
661
+ return newId;
662
+ }
773
663
  function getLastFailureContext(codeName) {
774
664
  const session = sessions.get(codeName);
775
665
  return {
@@ -785,7 +675,7 @@ function resolveSessionSpawnDecision(args) {
785
675
  const disableFlag = process.env["AGT_DISABLE_SESSION_RESUME"];
786
676
  const resumeDisabled = disableFlag === "1" || disableFlag?.toLowerCase() === "true";
787
677
  if (resumeDisabled) {
788
- return { flag: "--session-id", sessionId: randomUUID2(), reason: "resume-disabled" };
678
+ return { flag: "--session-id", sessionId: randomUUID(), reason: "resume-disabled" };
789
679
  }
790
680
  const daily = getOrCreateDailySession(codeName, now, agentTimezone);
791
681
  if (!daily.isNew && sessionFileExists(projectDir, daily.sessionId)) {
@@ -845,10 +735,10 @@ function spawnSession(config, session) {
845
735
  log(`[persistent-session] No Claude Code credentials found under /root/.claude or /home/*. Pair via browser from the host page, or run 'claude /login' on the host.`);
846
736
  }
847
737
  } else {
848
- const claudeDir = join2(homedir2(), ".claude");
738
+ const claudeDir = join(homedir(), ".claude");
849
739
  for (const filename of [".credentials.json", "credentials.json"]) {
850
- const p = join2(claudeDir, filename);
851
- if (existsSync3(p)) {
740
+ const p = join(claudeDir, filename);
741
+ if (existsSync2(p)) {
852
742
  try {
853
743
  rmSync(p, { force: true });
854
744
  log(`[persistent-session] Removed ${p} (api_key mode active \u2014 preventing OAuth fallback)`);
@@ -882,7 +772,7 @@ function spawnSession(config, session) {
882
772
  if (channels.length > 0) args.push("--channels", ...channels);
883
773
  if (devChannels.length > 0) args.push("--dangerously-load-development-channels", ...devChannels);
884
774
  args.push("--mcp-config", mcpConfigPath);
885
- if (existsSync3(claudeMdPath)) args.push("--system-prompt-file", claudeMdPath);
775
+ if (existsSync2(claudeMdPath)) args.push("--system-prompt-file", claudeMdPath);
886
776
  const modelAlias = claudeModelAlias(config.primaryModel);
887
777
  if (modelAlias) args.push("--model", modelAlias);
888
778
  args.push("--allow-dangerously-skip-permissions");
@@ -910,7 +800,7 @@ function spawnSession(config, session) {
910
800
  // Treat empty-string as missing too — `HOME=""` makes ~ resolve
911
801
  // to cwd, which is the same broken outcome as no HOME, just
912
802
  // better hidden.
913
- HOME: process.env.HOME?.trim() || homedir2(),
803
+ HOME: process.env.HOME?.trim() || homedir(),
914
804
  USER: process.env.USER?.trim() || userInfo().username
915
805
  };
916
806
  if (config.runId) {
@@ -918,7 +808,7 @@ function spawnSession(config, session) {
918
808
  }
919
809
  for (const f of probeMcpEnvSubstitution({
920
810
  mcpConfigPath,
921
- envIntegrationsPath: join2(projectDir, ".env.integrations"),
811
+ envIntegrationsPath: join(projectDir, ".env.integrations"),
922
812
  baseEnv: {
923
813
  ...tmuxEnv,
924
814
  ...claudeAuthMode === "api_key" && config.anthropicApiKey ? { ANTHROPIC_API_KEY: config.anthropicApiKey } : {}
@@ -1234,10 +1124,10 @@ async function injectMessageWithStatus(codeName, type, content, meta, log) {
1234
1124
  const acpx = getAcpxBin();
1235
1125
  if (acpx && hasAcpxSession(acpx, projectDir, codeName)) {
1236
1126
  try {
1237
- const tmpDir = join2(projectDir, ".claude");
1238
- mkdirSync2(tmpDir, { recursive: true });
1239
- const tmpFile = join2(tmpDir, ".agt-inject-prompt.txt");
1240
- writeFileSync3(tmpFile, text);
1127
+ const tmpDir = join(projectDir, ".claude");
1128
+ mkdirSync(tmpDir, { recursive: true });
1129
+ const tmpFile = join(tmpDir, ".agt-inject-prompt.txt");
1130
+ writeFileSync2(tmpFile, text);
1241
1131
  _log(`[inject] acpx exec (fire-and-forget): cwd=${projectDir}, file=${tmpFile}`);
1242
1132
  const child = spawn(acpx, ["claude", "exec", "-f", tmpFile], {
1243
1133
  cwd: projectDir,
@@ -1246,10 +1136,15 @@ async function injectMessageWithStatus(codeName, type, content, meta, log) {
1246
1136
  });
1247
1137
  child.on("error", (err) => {
1248
1138
  _log(`[inject] acpx spawn error for '${codeName}': ${err.message}`);
1139
+ acpxExecFailureCounts.set(codeName, (acpxExecFailureCounts.get(codeName) ?? 0) + 1);
1249
1140
  });
1250
1141
  child.on("exit", (code) => {
1251
1142
  if (code && code !== 0) {
1252
- _log(`[inject] acpx exec exited ${code} for '${codeName}' \u2014 message may not have been delivered`);
1143
+ const exit4Detail = code === 4 ? " (no acpx session)" : "";
1144
+ _log(
1145
+ `[inject] acpx exec exited ${code}${exit4Detail} for '${codeName}' \u2014 type=${type} input_hash=${simpleTextHash(text)} len=${text.length} \u2014 message may not have been delivered`
1146
+ );
1147
+ acpxExecFailureCounts.set(codeName, (acpxExecFailureCounts.get(codeName) ?? 0) + 1);
1253
1148
  acpxSessionAvailableCache.delete(codeName);
1254
1149
  }
1255
1150
  });
@@ -1279,8 +1174,15 @@ function stopPersistentSession(codeName, log) {
1279
1174
  log(`[persistent-session] Stopping session for '${codeName}'`);
1280
1175
  session.status = "stopped";
1281
1176
  try {
1282
- execSync(`tmux kill-session -t agt-${codeName} 2>/dev/null`, { stdio: "ignore" });
1283
- } catch {
1177
+ execFileSync3("tmux", ["kill-session", "-t", `agt-${codeName}`], { stdio: ["ignore", "ignore", "pipe"] });
1178
+ } catch (err) {
1179
+ const stderr = (err.stderr ?? "").toString().trim();
1180
+ const alreadyGone = /can't find session|no server running/i.test(stderr);
1181
+ if (!alreadyGone) {
1182
+ log(
1183
+ `[persistent-session] WARN tmux kill-session for '${codeName}' failed unexpectedly: ${stderr || err.message} \u2014 the session may still be running (ENG-6174)`
1184
+ );
1185
+ }
1284
1186
  }
1285
1187
  try {
1286
1188
  const acpx = getAcpxBin();
@@ -1288,10 +1190,15 @@ function stopPersistentSession(codeName, log) {
1288
1190
  execFileSync3(acpx, ["claude", "sessions", "close", `agt-${codeName}`], {
1289
1191
  cwd: getProjectDir(codeName),
1290
1192
  timeout: 5e3,
1291
- stdio: "ignore"
1193
+ stdio: ["ignore", "ignore", "pipe"]
1292
1194
  });
1293
1195
  }
1294
- } catch {
1196
+ } catch (err) {
1197
+ const stderr = (err.stderr ?? "").toString().trim();
1198
+ const benign = /not found|no such session|unknown session/i.test(stderr);
1199
+ if (stderr && !benign) {
1200
+ log(`[persistent-session] acpx sessions close for '${codeName}' failed: ${stderr} (ENG-6174)`);
1201
+ }
1295
1202
  }
1296
1203
  sessions.delete(codeName);
1297
1204
  acpxSessionAvailableCache.delete(codeName);
@@ -1470,7 +1377,7 @@ async function stopAllSessionsAndWait(log, opts) {
1470
1377
  await new Promise((resolve) => setTimeout(resolve, Math.min(opts.timeoutMs, 2e3)));
1471
1378
  }
1472
1379
  function getProjectDir(codeName) {
1473
- return join2(homedir2(), ".augmented", codeName, "project");
1380
+ return join(homedir(), ".augmented", codeName, "project");
1474
1381
  }
1475
1382
  function writeAcpxConfig(config) {
1476
1383
  const {
@@ -1486,7 +1393,7 @@ function writeAcpxConfig(config) {
1486
1393
  if (channels.length > 0) claudeArgs.push("--channels", ...channels);
1487
1394
  if (devChannels.length > 0) claudeArgs.push("--dangerously-load-development-channels", ...devChannels);
1488
1395
  claudeArgs.push("--mcp-config", mcpConfigPath);
1489
- if (existsSync3(claudeMdPath)) claudeArgs.push("--system-prompt-file", claudeMdPath);
1396
+ if (existsSync2(claudeMdPath)) claudeArgs.push("--system-prompt-file", claudeMdPath);
1490
1397
  const acpModelAlias = claudeModelAlias(config.primaryModel);
1491
1398
  if (acpModelAlias) claudeArgs.push("--model", acpModelAlias);
1492
1399
  claudeArgs.push("--allow-dangerously-skip-permissions");
@@ -1495,18 +1402,18 @@ function writeAcpxConfig(config) {
1495
1402
  const mcpServerNames2 = collectMcpServerNames(mcpConfigPath);
1496
1403
  claudeArgs.push("--allowedTools", buildAllowedTools(mcpServerNames2));
1497
1404
  const acpCmd = `npx -y @agentclientprotocol/claude-agent-acp ${claudeArgs.map((a) => a.includes(" ") || a.includes("*") ? JSON.stringify(a) : a).join(" ")}`;
1498
- const envIntegrationsPath = join2(projectDir, ".env.integrations");
1499
- const wrapperPath = join2(projectDir, ".claude", "acpx-agent.sh");
1405
+ const envIntegrationsPath = join(projectDir, ".env.integrations");
1406
+ const wrapperPath = join(projectDir, ".claude", "acpx-agent.sh");
1500
1407
  const wrapperLines = ["#!/usr/bin/env bash"];
1501
- if (existsSync3(envIntegrationsPath)) {
1408
+ if (existsSync2(envIntegrationsPath)) {
1502
1409
  wrapperLines.push(`set -a`, `source ${JSON.stringify(envIntegrationsPath)}`, `set +a`);
1503
1410
  }
1504
1411
  if (claudeAuthMode === "api_key" && anthropicApiKey) {
1505
1412
  wrapperLines.push(`export ANTHROPIC_API_KEY=${JSON.stringify(anthropicApiKey)}`);
1506
1413
  }
1507
1414
  wrapperLines.push(`exec ${acpCmd}`);
1508
- mkdirSync2(join2(projectDir, ".claude"), { recursive: true });
1509
- writeFileSync3(wrapperPath, wrapperLines.join("\n") + "\n", { mode: 493 });
1415
+ mkdirSync(join(projectDir, ".claude"), { recursive: true });
1416
+ writeFileSync2(wrapperPath, wrapperLines.join("\n") + "\n", { mode: 493 });
1510
1417
  chmodSync(wrapperPath, 493);
1511
1418
  const acpxConfig = {
1512
1419
  defaultAgent: "claude",
@@ -1517,27 +1424,27 @@ function writeAcpxConfig(config) {
1517
1424
  }
1518
1425
  }
1519
1426
  };
1520
- writeFileSync3(join2(projectDir, ".acpxrc.json"), JSON.stringify(acpxConfig, null, 2));
1427
+ writeFileSync2(join(projectDir, ".acpxrc.json"), JSON.stringify(acpxConfig, null, 2));
1521
1428
  }
1522
1429
 
1523
1430
  export {
1524
1431
  formatMissingVar,
1432
+ expandTemplateVars,
1525
1433
  parseEnvIntegrations,
1526
1434
  probeMcpEnvSubstitution,
1527
1435
  sanitizeMcpJson,
1528
1436
  buildAllowedTools,
1529
- sessionTranscriptDir,
1530
- isAgentIdle,
1531
- isStaleForToday,
1532
- peekCurrentSession,
1533
1437
  checkChannelInputs,
1534
1438
  takeWatchdogGiveUpCount,
1535
1439
  creditWatchdogGiveUpCount,
1536
1440
  resolveClaudeBinary,
1537
1441
  writePersistentClaudeWrapper,
1442
+ takeAcpxExecFailureCount,
1443
+ creditAcpxExecFailureCount,
1538
1444
  paneLogPath,
1539
1445
  readPaneLogTail,
1540
1446
  prepareForRespawn,
1447
+ rotateSessionForWedge,
1541
1448
  getLastFailureContext,
1542
1449
  resolveSessionSpawnDecision,
1543
1450
  startPersistentSession,
@@ -1557,4 +1464,4 @@ export {
1557
1464
  stopAllSessionsAndWait,
1558
1465
  getProjectDir
1559
1466
  };
1560
- //# sourceMappingURL=chunk-MQJ5DMPT.js.map
1467
+ //# sourceMappingURL=chunk-7GKJZBTB.js.map