@integrity-labs/agt-cli 0.28.322 → 0.28.324
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +4 -4
- package/dist/{chunk-LJT3U3GQ.js → chunk-BSTFCC62.js} +11 -3
- package/dist/{chunk-LJT3U3GQ.js.map → chunk-BSTFCC62.js.map} +1 -1
- package/dist/{chunk-FG7ELAP4.js → chunk-KHSPRKK2.js} +3 -3
- package/dist/{claude-pair-runtime-ZL2U2NZJ.js → claude-pair-runtime-BOFTEAQC.js} +2 -2
- package/dist/lib/manager-worker.js +259 -173
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-L6S6HABH.js → persistent-session-BICDYHOC.js} +2 -2
- package/dist/{responsiveness-probe-X2WATO46.js → responsiveness-probe-FEAFPNUF.js} +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-FG7ELAP4.js.map → chunk-KHSPRKK2.js.map} +0 -0
- /package/dist/{claude-pair-runtime-ZL2U2NZJ.js.map → claude-pair-runtime-BOFTEAQC.js.map} +0 -0
- /package/dist/{persistent-session-L6S6HABH.js.map → persistent-session-BICDYHOC.js.map} +0 -0
- /package/dist/{responsiveness-probe-X2WATO46.js.map → responsiveness-probe-FEAFPNUF.js.map} +0 -0
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
requireHost,
|
|
44
44
|
safeWriteJsonAtomic,
|
|
45
45
|
setConfigHash
|
|
46
|
-
} from "../chunk-
|
|
46
|
+
} from "../chunk-KHSPRKK2.js";
|
|
47
47
|
import {
|
|
48
48
|
getProjectDir as getProjectDir2,
|
|
49
49
|
getReadyTasks,
|
|
@@ -132,16 +132,16 @@ import {
|
|
|
132
132
|
takeZombieDetection,
|
|
133
133
|
transcriptActivityAgeSeconds,
|
|
134
134
|
writeEgressAllowlist
|
|
135
|
-
} from "../chunk-
|
|
135
|
+
} from "../chunk-BSTFCC62.js";
|
|
136
136
|
import {
|
|
137
137
|
reapOrphanChannelMcps
|
|
138
138
|
} from "../chunk-XWVM4KPK.js";
|
|
139
139
|
|
|
140
140
|
// src/lib/manager-worker.ts
|
|
141
141
|
import { createHash as createHash12 } from "crypto";
|
|
142
|
-
import { readFileSync as
|
|
142
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync12, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
|
|
143
143
|
import { execFileSync as syncExecFile } from "child_process";
|
|
144
|
-
import { join as
|
|
144
|
+
import { join as join21, dirname as dirname6 } from "path";
|
|
145
145
|
import { homedir as homedir11 } from "os";
|
|
146
146
|
import { fileURLToPath } from "url";
|
|
147
147
|
|
|
@@ -4122,10 +4122,14 @@ function isHybridActionable(item) {
|
|
|
4122
4122
|
function kanbanActionableSignature(allowed) {
|
|
4123
4123
|
return allowed.map((i) => `${i.id}:${i.status}`).sort().join("|");
|
|
4124
4124
|
}
|
|
4125
|
-
function
|
|
4125
|
+
function nudgeIntervalForCount(nudgeCount, fullCadenceMs, maxCadenceMs) {
|
|
4126
|
+
const exponent = Math.max(0, Math.min(nudgeCount - 1, 8));
|
|
4127
|
+
return Math.min(fullCadenceMs * 3 ** exponent, Math.max(maxCadenceMs, fullCadenceMs));
|
|
4128
|
+
}
|
|
4129
|
+
function shouldNudgeUnchangedBoard(signature, state7, now, fullCadenceMs, maxCadenceMs = fullCadenceMs) {
|
|
4126
4130
|
if (!state7) return true;
|
|
4127
4131
|
if (state7.signature !== signature) return true;
|
|
4128
|
-
return now - state7.nudgedAt >= fullCadenceMs;
|
|
4132
|
+
return now - state7.nudgedAt >= nudgeIntervalForCount(state7.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
|
|
4129
4133
|
}
|
|
4130
4134
|
function isSlashCommand(command) {
|
|
4131
4135
|
return command.trimStart().startsWith("/");
|
|
@@ -4373,6 +4377,49 @@ function formatBoardForPrompt(items, template) {
|
|
|
4373
4377
|
return lines.join("\n");
|
|
4374
4378
|
}
|
|
4375
4379
|
|
|
4380
|
+
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
4381
|
+
import { existsSync as existsSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "fs";
|
|
4382
|
+
import { join as join16 } from "path";
|
|
4383
|
+
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
4384
|
+
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
4385
|
+
function getKanbanNudgeStateFile(configDir) {
|
|
4386
|
+
return join16(configDir, CACHE_FILENAME2);
|
|
4387
|
+
}
|
|
4388
|
+
function loadKanbanNudgeState(target, configDir) {
|
|
4389
|
+
const path = getKanbanNudgeStateFile(configDir);
|
|
4390
|
+
if (!existsSync9(path)) return;
|
|
4391
|
+
let parsed;
|
|
4392
|
+
try {
|
|
4393
|
+
parsed = JSON.parse(readFileSync15(path, "utf-8"));
|
|
4394
|
+
} catch {
|
|
4395
|
+
return;
|
|
4396
|
+
}
|
|
4397
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
|
|
4398
|
+
const obj = parsed;
|
|
4399
|
+
if (obj.version !== KANBAN_NUDGE_STATE_VERSION) return;
|
|
4400
|
+
const entries = obj.agents;
|
|
4401
|
+
if (!entries || typeof entries !== "object" || Array.isArray(entries)) return;
|
|
4402
|
+
for (const [codeName, value] of Object.entries(entries)) {
|
|
4403
|
+
if (!value || typeof value !== "object") continue;
|
|
4404
|
+
const v = value;
|
|
4405
|
+
if (typeof v.signature !== "string" || typeof v.nudgedAt !== "number" || !Number.isFinite(v.nudgedAt)) continue;
|
|
4406
|
+
target.set(codeName, {
|
|
4407
|
+
signature: v.signature,
|
|
4408
|
+
nudgedAt: v.nudgedAt,
|
|
4409
|
+
nudgeCount: typeof v.nudgeCount === "number" && Number.isFinite(v.nudgeCount) && v.nudgeCount >= 1 ? Math.floor(v.nudgeCount) : 1
|
|
4410
|
+
});
|
|
4411
|
+
}
|
|
4412
|
+
}
|
|
4413
|
+
function saveKanbanNudgeState(source, configDir) {
|
|
4414
|
+
const path = getKanbanNudgeStateFile(configDir);
|
|
4415
|
+
const agents = {};
|
|
4416
|
+
for (const [codeName, state7] of source) agents[codeName] = state7;
|
|
4417
|
+
try {
|
|
4418
|
+
writeFileSync6(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
4419
|
+
} catch {
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4376
4423
|
// src/lib/manager/kanban/notify.ts
|
|
4377
4424
|
import { createHash as createHash7 } from "crypto";
|
|
4378
4425
|
async function enqueueKanbanNotice(opts) {
|
|
@@ -4594,6 +4641,9 @@ async function maybeSendTelegramFollowUpHint(agentCodeName, botToken, chatId) {
|
|
|
4594
4641
|
}
|
|
4595
4642
|
|
|
4596
4643
|
// src/lib/manager/delivery/state.ts
|
|
4644
|
+
function toPreferredChannel(raw) {
|
|
4645
|
+
return raw === "slack" || raw === "telegram" ? raw : null;
|
|
4646
|
+
}
|
|
4597
4647
|
var agentInfoForDelivery = /* @__PURE__ */ new Map();
|
|
4598
4648
|
function cacheAgentDeliveryMetadata(codeName, refreshData) {
|
|
4599
4649
|
const agentRow = refreshData["agent"] ?? {};
|
|
@@ -4625,7 +4675,8 @@ function cacheAgentDeliveryMetadata(codeName, refreshData) {
|
|
|
4625
4675
|
person_id: reportsToPersonId,
|
|
4626
4676
|
display_name: agentRow["reports_to_name"] ?? "Reports-To",
|
|
4627
4677
|
slack_user_id: agentRow["reports_to_slack_user_id"] ?? null,
|
|
4628
|
-
telegram_chat_id: agentRow["reports_to_telegram_chat_id"] ?? null
|
|
4678
|
+
telegram_chat_id: agentRow["reports_to_telegram_chat_id"] ?? null,
|
|
4679
|
+
preferred_channel: toPreferredChannel(agentRow["reports_to_approval_notify_channel"])
|
|
4629
4680
|
});
|
|
4630
4681
|
}
|
|
4631
4682
|
const people = refreshData["people"] ?? [];
|
|
@@ -4637,7 +4688,8 @@ function cacheAgentDeliveryMetadata(codeName, refreshData) {
|
|
|
4637
4688
|
person_id: personId,
|
|
4638
4689
|
display_name: p["display_name"] ?? "person",
|
|
4639
4690
|
slack_user_id: contactPrefs["slack_user_id"] ?? null,
|
|
4640
|
-
telegram_chat_id: contactPrefs["telegram_chat_id"] ?? null
|
|
4691
|
+
telegram_chat_id: contactPrefs["telegram_chat_id"] ?? null,
|
|
4692
|
+
preferred_channel: toPreferredChannel(contactPrefs["approval_notify_channel"])
|
|
4641
4693
|
});
|
|
4642
4694
|
}
|
|
4643
4695
|
agentInfoForDelivery.set(codeName, {
|
|
@@ -4904,9 +4956,9 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
4904
4956
|
|
|
4905
4957
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
4906
4958
|
import { createHash as createHash9 } from "crypto";
|
|
4907
|
-
import { writeFileSync as
|
|
4959
|
+
import { writeFileSync as writeFileSync7, renameSync } from "fs";
|
|
4908
4960
|
import { homedir as homedir7 } from "os";
|
|
4909
|
-
import { join as
|
|
4961
|
+
import { join as join17 } from "path";
|
|
4910
4962
|
|
|
4911
4963
|
// src/lib/manager/delivery/scheduled-output.ts
|
|
4912
4964
|
async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, body, taskId) {
|
|
@@ -5210,10 +5262,10 @@ function resolveScheduledSlackTarget(task) {
|
|
|
5210
5262
|
}
|
|
5211
5263
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
5212
5264
|
try {
|
|
5213
|
-
const file =
|
|
5265
|
+
const file = join17(homedir7(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5214
5266
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
5215
5267
|
const tmp = `${file}.tmp`;
|
|
5216
|
-
|
|
5268
|
+
writeFileSync7(tmp, JSON.stringify(marker), "utf8");
|
|
5217
5269
|
renameSync(tmp, file);
|
|
5218
5270
|
} catch (err) {
|
|
5219
5271
|
log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
|
|
@@ -5397,9 +5449,9 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5397
5449
|
// src/lib/manager/scheduler/execution.ts
|
|
5398
5450
|
import { createHash as createHash10 } from "crypto";
|
|
5399
5451
|
import { homedir as homedir8 } from "os";
|
|
5400
|
-
import { join as
|
|
5452
|
+
import { join as join18 } from "path";
|
|
5401
5453
|
function claudePidFilePath() {
|
|
5402
|
-
return
|
|
5454
|
+
return join18(homedir8(), ".augmented", "manager-claude-pids.json");
|
|
5403
5455
|
}
|
|
5404
5456
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
5405
5457
|
function registerClaudeSpawn(record) {
|
|
@@ -5463,9 +5515,9 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5463
5515
|
import { spawn, execSync } from "child_process";
|
|
5464
5516
|
import { createServer } from "net";
|
|
5465
5517
|
import { randomBytes } from "crypto";
|
|
5466
|
-
import { existsSync as
|
|
5518
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync16 } from "fs";
|
|
5467
5519
|
import { homedir as homedir9, userInfo } from "os";
|
|
5468
|
-
import { join as
|
|
5520
|
+
import { join as join19 } from "path";
|
|
5469
5521
|
var OPENCODE_BIN = process.env["AGT_OPENCODE_BIN"]?.trim() || "opencode";
|
|
5470
5522
|
var sessions = /* @__PURE__ */ new Map();
|
|
5471
5523
|
var bridges = /* @__PURE__ */ new Map();
|
|
@@ -5473,7 +5525,7 @@ function opencodeTmuxSession(codeName) {
|
|
|
5473
5525
|
return `agt-oc-${codeName}`;
|
|
5474
5526
|
}
|
|
5475
5527
|
function opencodePaneLogPath(codeName) {
|
|
5476
|
-
return
|
|
5528
|
+
return join19(homedir9(), ".augmented", codeName, "opencode-serve.log");
|
|
5477
5529
|
}
|
|
5478
5530
|
function baseUrlFor(port) {
|
|
5479
5531
|
return `http://127.0.0.1:${port}`;
|
|
@@ -5540,7 +5592,7 @@ async function startOpencodeSession(config2) {
|
|
|
5540
5592
|
}
|
|
5541
5593
|
async function spawnServe(config2, session) {
|
|
5542
5594
|
const { codeName, projectDir, log: log2 } = config2;
|
|
5543
|
-
if (!
|
|
5595
|
+
if (!existsSync10(join19(projectDir, "opencode.json"))) {
|
|
5544
5596
|
log2(`[opencode-session] warning: no opencode.json in ${projectDir} for '${codeName}' (provisioning may not have run)`);
|
|
5545
5597
|
}
|
|
5546
5598
|
const tmuxSession = opencodeTmuxSession(codeName);
|
|
@@ -5550,7 +5602,7 @@ async function spawnServe(config2, session) {
|
|
|
5550
5602
|
execSync(`tmux kill-session -t ${tmuxSession} 2>/dev/null`, { stdio: "ignore" });
|
|
5551
5603
|
} catch {
|
|
5552
5604
|
}
|
|
5553
|
-
mkdirSync6(
|
|
5605
|
+
mkdirSync6(join19(homedir9(), ".augmented", codeName), { recursive: true });
|
|
5554
5606
|
const serveEnv = {
|
|
5555
5607
|
...process.env,
|
|
5556
5608
|
...stripUndefined(config2.serveEnv ?? {}),
|
|
@@ -5601,9 +5653,9 @@ function setupPaneLog(tmuxSession, codeName, log2) {
|
|
|
5601
5653
|
}
|
|
5602
5654
|
function readOpencodePaneLogTail(codeName, lines = 40) {
|
|
5603
5655
|
const logPath = opencodePaneLogPath(codeName);
|
|
5604
|
-
if (!
|
|
5656
|
+
if (!existsSync10(logPath)) return null;
|
|
5605
5657
|
try {
|
|
5606
|
-
const all =
|
|
5658
|
+
const all = readFileSync16(logPath, "utf8").split("\n");
|
|
5607
5659
|
return all.slice(-lines).join("\n");
|
|
5608
5660
|
} catch {
|
|
5609
5661
|
return null;
|
|
@@ -6696,24 +6748,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
6696
6748
|
}
|
|
6697
6749
|
|
|
6698
6750
|
// src/lib/restart-flags.ts
|
|
6699
|
-
import { existsSync as
|
|
6751
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readdirSync as readdirSync4, readFileSync as readFileSync17, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
6700
6752
|
import { homedir as homedir10 } from "os";
|
|
6701
|
-
import { join as
|
|
6753
|
+
import { join as join20 } from "path";
|
|
6702
6754
|
import { randomUUID } from "crypto";
|
|
6703
6755
|
function restartFlagsDir() {
|
|
6704
|
-
return
|
|
6756
|
+
return join20(homedir10(), ".augmented", "restart-flags");
|
|
6705
6757
|
}
|
|
6706
6758
|
function flagPath(codeName) {
|
|
6707
|
-
return
|
|
6759
|
+
return join20(restartFlagsDir(), `${codeName}.flag`);
|
|
6708
6760
|
}
|
|
6709
6761
|
function readRestartFlags() {
|
|
6710
6762
|
const dir = restartFlagsDir();
|
|
6711
|
-
if (!
|
|
6763
|
+
if (!existsSync11(dir)) return [];
|
|
6712
6764
|
const out = [];
|
|
6713
6765
|
for (const entry of readdirSync4(dir)) {
|
|
6714
6766
|
if (!entry.endsWith(".flag")) continue;
|
|
6715
6767
|
try {
|
|
6716
|
-
const raw =
|
|
6768
|
+
const raw = readFileSync17(join20(dir, entry), "utf8");
|
|
6717
6769
|
const parsed = JSON.parse(raw);
|
|
6718
6770
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
6719
6771
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -6731,7 +6783,7 @@ function readRestartFlags() {
|
|
|
6731
6783
|
}
|
|
6732
6784
|
function deleteRestartFlag(codeName) {
|
|
6733
6785
|
const path = flagPath(codeName);
|
|
6734
|
-
if (
|
|
6786
|
+
if (existsSync11(path)) {
|
|
6735
6787
|
rmSync3(path, { force: true });
|
|
6736
6788
|
}
|
|
6737
6789
|
}
|
|
@@ -7965,7 +8017,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
7965
8017
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
7966
8018
|
function projectMcpHash(_codeName, projectDir) {
|
|
7967
8019
|
try {
|
|
7968
|
-
const raw =
|
|
8020
|
+
const raw = readFileSync18(join21(projectDir, ".mcp.json"), "utf-8");
|
|
7969
8021
|
return createHash12("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
7970
8022
|
} catch {
|
|
7971
8023
|
return null;
|
|
@@ -7973,7 +8025,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
7973
8025
|
}
|
|
7974
8026
|
function projectMcpKeys(_codeName, projectDir) {
|
|
7975
8027
|
try {
|
|
7976
|
-
const raw =
|
|
8028
|
+
const raw = readFileSync18(join21(projectDir, ".mcp.json"), "utf-8");
|
|
7977
8029
|
const parsed = JSON.parse(raw);
|
|
7978
8030
|
const servers = parsed.mcpServers;
|
|
7979
8031
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -7991,7 +8043,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
7991
8043
|
else runningMcpServerKeys.delete(codeName);
|
|
7992
8044
|
let launchStructure = null;
|
|
7993
8045
|
try {
|
|
7994
|
-
const raw =
|
|
8046
|
+
const raw = readFileSync18(join21(projectDir, ".mcp.json"), "utf-8");
|
|
7995
8047
|
launchStructure = managedMcpStructureHashFromFile(
|
|
7996
8048
|
JSON.parse(raw),
|
|
7997
8049
|
isManagedMcpServerKey
|
|
@@ -8091,7 +8143,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
8091
8143
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
8092
8144
|
let mcpJsonForRebind = null;
|
|
8093
8145
|
try {
|
|
8094
|
-
mcpJsonForRebind = JSON.parse(
|
|
8146
|
+
mcpJsonForRebind = JSON.parse(readFileSync18(join21(projectDir, ".mcp.json"), "utf-8"));
|
|
8095
8147
|
} catch {
|
|
8096
8148
|
mcpJsonForRebind = null;
|
|
8097
8149
|
}
|
|
@@ -8220,7 +8272,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
8220
8272
|
function projectChannelSecretHash(projectDir) {
|
|
8221
8273
|
try {
|
|
8222
8274
|
const entries = parseEnvIntegrations(
|
|
8223
|
-
|
|
8275
|
+
readFileSync18(join21(projectDir, ".env.integrations"), "utf-8")
|
|
8224
8276
|
);
|
|
8225
8277
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
8226
8278
|
} catch {
|
|
@@ -8285,6 +8337,7 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
8285
8337
|
stopOpencodeSlackIngest(codeName, log);
|
|
8286
8338
|
agentFrameworkCache.delete(codeName);
|
|
8287
8339
|
kanbanBoardCache.delete(codeName);
|
|
8340
|
+
clearKanbanNudgeState(codeName);
|
|
8288
8341
|
notifyBoardCache.delete(codeName);
|
|
8289
8342
|
notifiedWaitingHumanIds.delete(codeName);
|
|
8290
8343
|
lastHarvestAt.delete(codeName);
|
|
@@ -8309,7 +8362,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
8309
8362
|
var lastVersionCheckAt = 0;
|
|
8310
8363
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
8311
8364
|
var lastResponsivenessProbeAt = 0;
|
|
8312
|
-
var agtCliVersion = true ? "0.28.
|
|
8365
|
+
var agtCliVersion = true ? "0.28.324" : "dev";
|
|
8313
8366
|
function resolveBrewPath(execFileSync2) {
|
|
8314
8367
|
try {
|
|
8315
8368
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -8322,7 +8375,7 @@ function resolveBrewPath(execFileSync2) {
|
|
|
8322
8375
|
"/usr/local/bin/brew"
|
|
8323
8376
|
];
|
|
8324
8377
|
for (const path of fallbacks) {
|
|
8325
|
-
if (
|
|
8378
|
+
if (existsSync12(path)) return path;
|
|
8326
8379
|
}
|
|
8327
8380
|
return null;
|
|
8328
8381
|
}
|
|
@@ -8332,7 +8385,7 @@ function claudeBinaryInstalled(execFileSync2) {
|
|
|
8332
8385
|
"/opt/homebrew/bin/claude",
|
|
8333
8386
|
"/usr/local/bin/claude"
|
|
8334
8387
|
];
|
|
8335
|
-
if (canonical.some((path) =>
|
|
8388
|
+
if (canonical.some((path) => existsSync12(path))) return true;
|
|
8336
8389
|
try {
|
|
8337
8390
|
execFileSync2("which", ["claude"], { timeout: 5e3 });
|
|
8338
8391
|
return true;
|
|
@@ -8487,8 +8540,8 @@ function claudeManagedSettingsPath() {
|
|
|
8487
8540
|
function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
8488
8541
|
try {
|
|
8489
8542
|
let settings = {};
|
|
8490
|
-
if (
|
|
8491
|
-
const raw =
|
|
8543
|
+
if (existsSync12(path)) {
|
|
8544
|
+
const raw = readFileSync18(path, "utf-8").trim();
|
|
8492
8545
|
if (raw) {
|
|
8493
8546
|
let parsed;
|
|
8494
8547
|
try {
|
|
@@ -8505,7 +8558,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
8505
8558
|
if (settings.channelsEnabled === true) return "ok";
|
|
8506
8559
|
settings.channelsEnabled = true;
|
|
8507
8560
|
mkdirSync8(dirname6(path), { recursive: true });
|
|
8508
|
-
|
|
8561
|
+
writeFileSync9(path, `${JSON.stringify(settings, null, 2)}
|
|
8509
8562
|
`);
|
|
8510
8563
|
log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
|
|
8511
8564
|
return "ok";
|
|
@@ -8550,7 +8603,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
8550
8603
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
8551
8604
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
8552
8605
|
}
|
|
8553
|
-
if (
|
|
8606
|
+
if (existsSync12("/home/linuxbrew/.linuxbrew/bin/claude")) {
|
|
8554
8607
|
log("Claude Code installed successfully");
|
|
8555
8608
|
} else {
|
|
8556
8609
|
log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
|
|
@@ -8606,7 +8659,7 @@ ${r.stderr}`;
|
|
|
8606
8659
|
}
|
|
8607
8660
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
8608
8661
|
function selfUpdateAppliedMarkerPath() {
|
|
8609
|
-
return
|
|
8662
|
+
return join21(homedir11(), ".augmented", ".last-self-update-applied");
|
|
8610
8663
|
}
|
|
8611
8664
|
var selfUpdateUpToDateLogged = false;
|
|
8612
8665
|
var restartAfterUpgrade = false;
|
|
@@ -8630,7 +8683,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
8630
8683
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
8631
8684
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
8632
8685
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
8633
|
-
const markerPath =
|
|
8686
|
+
const markerPath = join21(homedir11(), ".augmented", ".last-update-check");
|
|
8634
8687
|
if (!force) {
|
|
8635
8688
|
try {
|
|
8636
8689
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -8908,14 +8961,14 @@ async function checkClaudeAuth() {
|
|
|
8908
8961
|
}
|
|
8909
8962
|
var evalEmptyMcpConfigPath = null;
|
|
8910
8963
|
function ensureEvalEmptyMcpConfig() {
|
|
8911
|
-
if (evalEmptyMcpConfigPath &&
|
|
8912
|
-
const dir =
|
|
8964
|
+
if (evalEmptyMcpConfigPath && existsSync12(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
8965
|
+
const dir = join21(homedir11(), ".augmented");
|
|
8913
8966
|
try {
|
|
8914
8967
|
mkdirSync8(dir, { recursive: true });
|
|
8915
8968
|
} catch {
|
|
8916
8969
|
}
|
|
8917
|
-
const p =
|
|
8918
|
-
|
|
8970
|
+
const p = join21(dir, ".eval-empty-mcp.json");
|
|
8971
|
+
writeFileSync9(p, JSON.stringify({ mcpServers: {} }));
|
|
8919
8972
|
evalEmptyMcpConfigPath = p;
|
|
8920
8973
|
return p;
|
|
8921
8974
|
}
|
|
@@ -9006,10 +9059,10 @@ function resolveConversationEvalBackend() {
|
|
|
9006
9059
|
return conversationEvalBackend;
|
|
9007
9060
|
}
|
|
9008
9061
|
function getStateFile() {
|
|
9009
|
-
return
|
|
9062
|
+
return join21(config?.configDir ?? join21(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
9010
9063
|
}
|
|
9011
9064
|
function channelHashCacheDir() {
|
|
9012
|
-
return config?.configDir ??
|
|
9065
|
+
return config?.configDir ?? join21(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
9013
9066
|
}
|
|
9014
9067
|
function loadChannelHashCache2() {
|
|
9015
9068
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -9061,7 +9114,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
9061
9114
|
var _channelQuarantineStore = null;
|
|
9062
9115
|
function channelQuarantineStore() {
|
|
9063
9116
|
if (!_channelQuarantineStore) {
|
|
9064
|
-
const dir = config?.configDir ??
|
|
9117
|
+
const dir = config?.configDir ?? join21(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
9065
9118
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
9066
9119
|
}
|
|
9067
9120
|
return _channelQuarantineStore;
|
|
@@ -9069,7 +9122,7 @@ function channelQuarantineStore() {
|
|
|
9069
9122
|
var _hostFlagStore = null;
|
|
9070
9123
|
function hostFlagStore() {
|
|
9071
9124
|
if (!_hostFlagStore) {
|
|
9072
|
-
const dir = config?.configDir ??
|
|
9125
|
+
const dir = config?.configDir ?? join21(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
9073
9126
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
9074
9127
|
}
|
|
9075
9128
|
return _hostFlagStore;
|
|
@@ -9136,13 +9189,13 @@ function parseSkillFrontmatter(content) {
|
|
|
9136
9189
|
return out;
|
|
9137
9190
|
}
|
|
9138
9191
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
9139
|
-
const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync:
|
|
9140
|
-
const skillsDir =
|
|
9141
|
-
const claudeMdPath =
|
|
9192
|
+
const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync10 } = await import("fs");
|
|
9193
|
+
const skillsDir = join21(configDir, codeName, "project", ".claude", "skills");
|
|
9194
|
+
const claudeMdPath = join21(configDir, codeName, "project", "CLAUDE.md");
|
|
9142
9195
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
9143
9196
|
const entries = [];
|
|
9144
9197
|
for (const dir of readdirSync6(skillsDir).sort()) {
|
|
9145
|
-
const skillFile =
|
|
9198
|
+
const skillFile = join21(skillsDir, dir, "SKILL.md");
|
|
9146
9199
|
if (!ex(skillFile)) continue;
|
|
9147
9200
|
try {
|
|
9148
9201
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -9184,7 +9237,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
9184
9237
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
9185
9238
|
}
|
|
9186
9239
|
if (next !== current) {
|
|
9187
|
-
|
|
9240
|
+
writeFileSync10(claudeMdPath, next, "utf-8");
|
|
9188
9241
|
log2(`Refreshed skills index in CLAUDE.md for '${codeName}' (${entries.length} skills)`);
|
|
9189
9242
|
}
|
|
9190
9243
|
}
|
|
@@ -9205,7 +9258,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
9205
9258
|
if (codeNames.length === 0) return;
|
|
9206
9259
|
void (async () => {
|
|
9207
9260
|
try {
|
|
9208
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
9261
|
+
const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
|
|
9209
9262
|
await api.post("/host/heartbeat", {
|
|
9210
9263
|
host_id: hostId,
|
|
9211
9264
|
agent_diagnostics: collectDiagnostics(codeNames)
|
|
@@ -9304,7 +9357,7 @@ async function pollCycle() {
|
|
|
9304
9357
|
}
|
|
9305
9358
|
try {
|
|
9306
9359
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
9307
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
9360
|
+
const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
|
|
9308
9361
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
9309
9362
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
9310
9363
|
let tailscaleHostname;
|
|
@@ -9453,7 +9506,7 @@ async function pollCycle() {
|
|
|
9453
9506
|
const {
|
|
9454
9507
|
collectResponsivenessProbes,
|
|
9455
9508
|
getResponsivenessIntervalMs
|
|
9456
|
-
} = await import("../responsiveness-probe-
|
|
9509
|
+
} = await import("../responsiveness-probe-FEAFPNUF.js");
|
|
9457
9510
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
9458
9511
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
9459
9512
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -9485,7 +9538,7 @@ async function pollCycle() {
|
|
|
9485
9538
|
collectResponsivenessProbes,
|
|
9486
9539
|
livePendingInboundOldestAgeSeconds,
|
|
9487
9540
|
parkPendingInbound
|
|
9488
|
-
} = await import("../responsiveness-probe-
|
|
9541
|
+
} = await import("../responsiveness-probe-FEAFPNUF.js");
|
|
9489
9542
|
const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
9490
9543
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
9491
9544
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -9574,13 +9627,13 @@ async function pollCycle() {
|
|
|
9574
9627
|
);
|
|
9575
9628
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
9576
9629
|
try {
|
|
9577
|
-
const paneTail =
|
|
9630
|
+
const paneTail = readFileSync18(paneLogPath(codeName), "utf8").slice(-65536);
|
|
9578
9631
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
9579
9632
|
if (transient) {
|
|
9580
|
-
const wedgeHome =
|
|
9581
|
-
if (
|
|
9633
|
+
const wedgeHome = join21(homedir11(), ".augmented", codeName);
|
|
9634
|
+
if (existsSync12(wedgeHome)) {
|
|
9582
9635
|
atomicWriteFileSync(
|
|
9583
|
-
|
|
9636
|
+
join21(wedgeHome, "watchdog-give-up.json"),
|
|
9584
9637
|
JSON.stringify({
|
|
9585
9638
|
gave_up_at: wedgeNow.toISOString(),
|
|
9586
9639
|
reason: "transient_overload"
|
|
@@ -9829,7 +9882,7 @@ async function pollCycle() {
|
|
|
9829
9882
|
} catch {
|
|
9830
9883
|
}
|
|
9831
9884
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
9832
|
-
const agentDir =
|
|
9885
|
+
const agentDir = join21(adapter.getAgentDir(prev.codeName), "provision");
|
|
9833
9886
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
9834
9887
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
9835
9888
|
}
|
|
@@ -9916,10 +9969,10 @@ async function pollCycle() {
|
|
|
9916
9969
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
9917
9970
|
// the watchdog, never fails the poll cycle.
|
|
9918
9971
|
signalGiveUp: (codeName) => {
|
|
9919
|
-
const dir =
|
|
9920
|
-
if (!
|
|
9972
|
+
const dir = join21(homedir11(), ".augmented", codeName);
|
|
9973
|
+
if (!existsSync12(dir)) return;
|
|
9921
9974
|
atomicWriteFileSync(
|
|
9922
|
-
|
|
9975
|
+
join21(dir, "watchdog-give-up.json"),
|
|
9923
9976
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
9924
9977
|
);
|
|
9925
9978
|
}
|
|
@@ -10049,7 +10102,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10049
10102
|
}
|
|
10050
10103
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10051
10104
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
10052
|
-
let agentDir =
|
|
10105
|
+
let agentDir = join21(adapter.getAgentDir(agent.code_name), "provision");
|
|
10053
10106
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
10054
10107
|
if (previousKnownStatus !== agent.status) {
|
|
10055
10108
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -10095,7 +10148,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10095
10148
|
const residuals = {
|
|
10096
10149
|
gatewayRunning: false,
|
|
10097
10150
|
portAllocated: false,
|
|
10098
|
-
provisionDirExists:
|
|
10151
|
+
provisionDirExists: existsSync12(agentDir)
|
|
10099
10152
|
};
|
|
10100
10153
|
if (!hasRevokedResiduals(residuals)) {
|
|
10101
10154
|
agentStates.push({
|
|
@@ -10233,7 +10286,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10233
10286
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
10234
10287
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
10235
10288
|
const frameworkAdapter = getFramework(frameworkId);
|
|
10236
|
-
agentDir =
|
|
10289
|
+
agentDir = join21(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
10237
10290
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
10238
10291
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
10239
10292
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -10280,7 +10333,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10280
10333
|
const changedFiles = [];
|
|
10281
10334
|
mkdirSync8(agentDir, { recursive: true });
|
|
10282
10335
|
for (const artifact of artifacts) {
|
|
10283
|
-
const filePath =
|
|
10336
|
+
const filePath = join21(agentDir, artifact.relativePath);
|
|
10284
10337
|
let existingHash;
|
|
10285
10338
|
let newHash;
|
|
10286
10339
|
let writeContent = artifact.content;
|
|
@@ -10299,8 +10352,8 @@ async function processAgent(agent, agentStates) {
|
|
|
10299
10352
|
};
|
|
10300
10353
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
10301
10354
|
try {
|
|
10302
|
-
const projectClaudeMd =
|
|
10303
|
-
const existing =
|
|
10355
|
+
const projectClaudeMd = join21(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
10356
|
+
const existing = readFileSync18(projectClaudeMd, "utf-8");
|
|
10304
10357
|
existingHash = sha256(stripDynamicSections(existing));
|
|
10305
10358
|
} catch {
|
|
10306
10359
|
existingHash = null;
|
|
@@ -10318,7 +10371,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10318
10371
|
const generatorKeys = Object.keys(generatorServers);
|
|
10319
10372
|
let existingRaw = "";
|
|
10320
10373
|
try {
|
|
10321
|
-
existingRaw =
|
|
10374
|
+
existingRaw = readFileSync18(filePath, "utf-8");
|
|
10322
10375
|
} catch {
|
|
10323
10376
|
}
|
|
10324
10377
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -10340,26 +10393,26 @@ async function processAgent(agent, agentStates) {
|
|
|
10340
10393
|
}
|
|
10341
10394
|
}
|
|
10342
10395
|
if (changedFiles.length > 0) {
|
|
10343
|
-
const isFirst = !
|
|
10396
|
+
const isFirst = !existsSync12(join21(agentDir, "CHARTER.md"));
|
|
10344
10397
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
10345
10398
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
10346
10399
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
10347
10400
|
for (const file of changedFiles) {
|
|
10348
|
-
const filePath =
|
|
10401
|
+
const filePath = join21(agentDir, file.relativePath);
|
|
10349
10402
|
mkdirSync8(dirname6(filePath), { recursive: true });
|
|
10350
10403
|
if (file.relativePath === ".mcp.json") {
|
|
10351
10404
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
10352
10405
|
} else {
|
|
10353
|
-
|
|
10406
|
+
writeFileSync9(filePath, file.content);
|
|
10354
10407
|
}
|
|
10355
10408
|
}
|
|
10356
10409
|
try {
|
|
10357
|
-
const provSkillsDir =
|
|
10358
|
-
if (
|
|
10410
|
+
const provSkillsDir = join21(agentDir, ".claude", "skills");
|
|
10411
|
+
if (existsSync12(provSkillsDir)) {
|
|
10359
10412
|
for (const folder of readdirSync5(provSkillsDir)) {
|
|
10360
10413
|
if (folder.startsWith("knowledge-")) {
|
|
10361
10414
|
try {
|
|
10362
|
-
rmSync4(
|
|
10415
|
+
rmSync4(join21(provSkillsDir, folder), { recursive: true });
|
|
10363
10416
|
} catch {
|
|
10364
10417
|
}
|
|
10365
10418
|
}
|
|
@@ -10372,7 +10425,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10372
10425
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
10373
10426
|
const hashes = /* @__PURE__ */ new Map();
|
|
10374
10427
|
for (const file of trackedFiles2) {
|
|
10375
|
-
const h = hashFile(
|
|
10428
|
+
const h = hashFile(join21(agentDir, file));
|
|
10376
10429
|
if (h) hashes.set(file, h);
|
|
10377
10430
|
}
|
|
10378
10431
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -10390,14 +10443,14 @@ async function processAgent(agent, agentStates) {
|
|
|
10390
10443
|
}
|
|
10391
10444
|
if (Array.isArray(refreshData.workflows)) {
|
|
10392
10445
|
try {
|
|
10393
|
-
const provWorkflowsDir =
|
|
10394
|
-
if (
|
|
10446
|
+
const provWorkflowsDir = join21(agentDir, ".claude", "workflows");
|
|
10447
|
+
if (existsSync12(provWorkflowsDir)) {
|
|
10395
10448
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
10396
10449
|
for (const file of readdirSync5(provWorkflowsDir)) {
|
|
10397
10450
|
if (!file.endsWith(".js")) continue;
|
|
10398
10451
|
if (expected.has(file)) continue;
|
|
10399
10452
|
try {
|
|
10400
|
-
rmSync4(
|
|
10453
|
+
rmSync4(join21(provWorkflowsDir, file));
|
|
10401
10454
|
} catch {
|
|
10402
10455
|
}
|
|
10403
10456
|
}
|
|
@@ -10454,10 +10507,10 @@ async function processAgent(agent, agentStates) {
|
|
|
10454
10507
|
}
|
|
10455
10508
|
let lastDriftCheckAt = now;
|
|
10456
10509
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
10457
|
-
if (written &&
|
|
10510
|
+
if (written && existsSync12(agentDir)) {
|
|
10458
10511
|
const driftedFiles = [];
|
|
10459
10512
|
for (const [file, expectedHash] of written) {
|
|
10460
|
-
const localHash = hashFile(
|
|
10513
|
+
const localHash = hashFile(join21(agentDir, file));
|
|
10461
10514
|
if (localHash && localHash !== expectedHash) {
|
|
10462
10515
|
driftedFiles.push(file);
|
|
10463
10516
|
}
|
|
@@ -10468,7 +10521,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10468
10521
|
try {
|
|
10469
10522
|
const localHashes = {};
|
|
10470
10523
|
for (const file of driftedFiles) {
|
|
10471
|
-
localHashes[file] = hashFile(
|
|
10524
|
+
localHashes[file] = hashFile(join21(agentDir, file));
|
|
10472
10525
|
}
|
|
10473
10526
|
await api.post("/host/drift", {
|
|
10474
10527
|
agent_id: agent.agent_id,
|
|
@@ -10655,7 +10708,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10655
10708
|
const addedChannels = [...restartDecision.added];
|
|
10656
10709
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
10657
10710
|
try {
|
|
10658
|
-
const agentAugmentedDir =
|
|
10711
|
+
const agentAugmentedDir = join21(homedir11(), ".augmented", agent.code_name);
|
|
10659
10712
|
mkdirSync8(agentAugmentedDir, { recursive: true });
|
|
10660
10713
|
const markerJson = JSON.stringify({
|
|
10661
10714
|
version: 1,
|
|
@@ -10663,7 +10716,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10663
10716
|
added: addedChannels
|
|
10664
10717
|
});
|
|
10665
10718
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
10666
|
-
atomicWriteFileSync(
|
|
10719
|
+
atomicWriteFileSync(join21(agentAugmentedDir, file), markerJson);
|
|
10667
10720
|
}
|
|
10668
10721
|
} catch (err) {
|
|
10669
10722
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -10852,24 +10905,24 @@ async function processAgent(agent, agentStates) {
|
|
|
10852
10905
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
10853
10906
|
try {
|
|
10854
10907
|
const agentProvisionDir = agentDir;
|
|
10855
|
-
const projectDir =
|
|
10908
|
+
const projectDir = join21(homedir11(), ".augmented", agent.code_name, "project");
|
|
10856
10909
|
mkdirSync8(agentProvisionDir, { recursive: true });
|
|
10857
10910
|
mkdirSync8(projectDir, { recursive: true });
|
|
10858
|
-
const provisionMcpPath =
|
|
10859
|
-
const projectMcpPath =
|
|
10911
|
+
const provisionMcpPath = join21(agentProvisionDir, ".mcp.json");
|
|
10912
|
+
const projectMcpPath = join21(projectDir, ".mcp.json");
|
|
10860
10913
|
let mcpConfig = { mcpServers: {} };
|
|
10861
10914
|
try {
|
|
10862
|
-
mcpConfig = JSON.parse(
|
|
10915
|
+
mcpConfig = JSON.parse(readFileSync18(provisionMcpPath, "utf-8"));
|
|
10863
10916
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
10864
10917
|
} catch {
|
|
10865
10918
|
}
|
|
10866
|
-
const localDirectChatChannel =
|
|
10919
|
+
const localDirectChatChannel = join21(homedir11(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
10867
10920
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
10868
10921
|
const directChatTz = (() => {
|
|
10869
10922
|
const tz = directChatTeamSettings?.["timezone"];
|
|
10870
10923
|
return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
|
|
10871
10924
|
})();
|
|
10872
|
-
if (
|
|
10925
|
+
if (existsSync12(localDirectChatChannel)) {
|
|
10873
10926
|
const directChatEnv = {
|
|
10874
10927
|
AGT_HOST: requireHost(),
|
|
10875
10928
|
// ENG-5901 Track D: templated — the manager exports the real
|
|
@@ -10889,7 +10942,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10889
10942
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
10890
10943
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
10891
10944
|
// so it byte-matches the broker readers' path.
|
|
10892
|
-
AGT_TURN_INITIATOR_FILE:
|
|
10945
|
+
AGT_TURN_INITIATOR_FILE: join21(
|
|
10893
10946
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
10894
10947
|
".current-turn-initiator.json"
|
|
10895
10948
|
)
|
|
@@ -10909,8 +10962,8 @@ async function processAgent(agent, agentStates) {
|
|
|
10909
10962
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
10910
10963
|
}
|
|
10911
10964
|
}
|
|
10912
|
-
const staleChannelsPath =
|
|
10913
|
-
if (
|
|
10965
|
+
const staleChannelsPath = join21(projectDir, ".mcp-channels.json");
|
|
10966
|
+
if (existsSync12(staleChannelsPath)) {
|
|
10914
10967
|
try {
|
|
10915
10968
|
rmSync4(staleChannelsPath, { force: true });
|
|
10916
10969
|
} catch {
|
|
@@ -10999,7 +11052,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10999
11052
|
}
|
|
11000
11053
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
11001
11054
|
try {
|
|
11002
|
-
const probeProjectDir =
|
|
11055
|
+
const probeProjectDir = join21(homedir11(), ".augmented", agent.code_name, "project");
|
|
11003
11056
|
await runAgentConnectivityProbes(agent, integrations, probeProjectDir);
|
|
11004
11057
|
} catch (err) {
|
|
11005
11058
|
log(`Connectivity probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -11010,7 +11063,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11010
11063
|
const forceDue = attemptsLeft > 0;
|
|
11011
11064
|
let probeRan = false;
|
|
11012
11065
|
try {
|
|
11013
|
-
const probeProjectDir =
|
|
11066
|
+
const probeProjectDir = join21(homedir11(), ".augmented", agent.code_name, "project");
|
|
11014
11067
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
11015
11068
|
} catch (err) {
|
|
11016
11069
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -11023,9 +11076,9 @@ async function processAgent(agent, agentStates) {
|
|
|
11023
11076
|
}
|
|
11024
11077
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
|
|
11025
11078
|
const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
|
|
11026
|
-
if (mcpPath &&
|
|
11079
|
+
if (mcpPath && existsSync12(mcpPath)) {
|
|
11027
11080
|
try {
|
|
11028
|
-
const cfg = JSON.parse(
|
|
11081
|
+
const cfg = JSON.parse(readFileSync18(mcpPath, "utf-8"));
|
|
11029
11082
|
const expectedRemoteKeys = new Set(
|
|
11030
11083
|
integrations.map((i) => i.definition_id)
|
|
11031
11084
|
);
|
|
@@ -11050,11 +11103,11 @@ async function processAgent(agent, agentStates) {
|
|
|
11050
11103
|
recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
|
|
11051
11104
|
}
|
|
11052
11105
|
if (intHash !== prevIntHash) {
|
|
11053
|
-
const projectDir =
|
|
11054
|
-
const envIntPath =
|
|
11106
|
+
const projectDir = join21(homedir11(), ".augmented", agent.code_name, "project");
|
|
11107
|
+
const envIntPath = join21(projectDir, ".env.integrations");
|
|
11055
11108
|
let preWriteEnv;
|
|
11056
11109
|
try {
|
|
11057
|
-
preWriteEnv =
|
|
11110
|
+
preWriteEnv = readFileSync18(envIntPath, "utf-8");
|
|
11058
11111
|
} catch {
|
|
11059
11112
|
preWriteEnv = void 0;
|
|
11060
11113
|
}
|
|
@@ -11066,9 +11119,9 @@ async function processAgent(agent, agentStates) {
|
|
|
11066
11119
|
let rotationHandled = true;
|
|
11067
11120
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
11068
11121
|
try {
|
|
11069
|
-
const projectMcpPath =
|
|
11070
|
-
const postWriteEnv =
|
|
11071
|
-
const mcpContent =
|
|
11122
|
+
const projectMcpPath = join21(projectDir, ".mcp.json");
|
|
11123
|
+
const postWriteEnv = readFileSync18(envIntPath, "utf-8");
|
|
11124
|
+
const mcpContent = readFileSync18(projectMcpPath, "utf-8");
|
|
11072
11125
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
11073
11126
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
11074
11127
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -11170,8 +11223,8 @@ async function processAgent(agent, agentStates) {
|
|
|
11170
11223
|
const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
|
|
11171
11224
|
if (mcpPath) {
|
|
11172
11225
|
try {
|
|
11173
|
-
const { readFileSync:
|
|
11174
|
-
const mcpConfig = JSON.parse(
|
|
11226
|
+
const { readFileSync: readFileSync19 } = await import("fs");
|
|
11227
|
+
const mcpConfig = JSON.parse(readFileSync19(mcpPath, "utf-8"));
|
|
11175
11228
|
if (mcpConfig.mcpServers) {
|
|
11176
11229
|
for (const key of Object.keys(mcpConfig.mcpServers)) {
|
|
11177
11230
|
if (isManagedMcpServerKey(key) && !expectedServerIds.has(key)) {
|
|
@@ -11318,14 +11371,14 @@ async function processAgent(agent, agentStates) {
|
|
|
11318
11371
|
const frameworkId2 = frameworkAdapter.id;
|
|
11319
11372
|
const candidateSkillDirs = [
|
|
11320
11373
|
// Claude Code — framework runtime tree
|
|
11321
|
-
|
|
11374
|
+
join21(homedir12(), ".augmented", agent.code_name, "skills"),
|
|
11322
11375
|
// Claude Code — project tree
|
|
11323
|
-
|
|
11376
|
+
join21(homedir12(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
11324
11377
|
// Defensive: legacy provision-side path, not currently an
|
|
11325
11378
|
// install target but cheap to sweep.
|
|
11326
|
-
|
|
11379
|
+
join21(agentDir, ".claude", "skills")
|
|
11327
11380
|
];
|
|
11328
|
-
const existingDirs = candidateSkillDirs.filter((d) =>
|
|
11381
|
+
const existingDirs = candidateSkillDirs.filter((d) => existsSync12(d));
|
|
11329
11382
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
11330
11383
|
for (const dir of existingDirs) {
|
|
11331
11384
|
try {
|
|
@@ -11339,8 +11392,8 @@ async function processAgent(agent, agentStates) {
|
|
|
11339
11392
|
}
|
|
11340
11393
|
const removeSkillFolder = (entry, reason) => {
|
|
11341
11394
|
for (const dir of existingDirs) {
|
|
11342
|
-
const p =
|
|
11343
|
-
if (
|
|
11395
|
+
const p = join21(dir, entry);
|
|
11396
|
+
if (existsSync12(p)) {
|
|
11344
11397
|
rmSync5(p, { recursive: true, force: true });
|
|
11345
11398
|
}
|
|
11346
11399
|
}
|
|
@@ -11359,7 +11412,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11359
11412
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
11360
11413
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
11361
11414
|
const manifestPath = managedSkillManifestPath(
|
|
11362
|
-
|
|
11415
|
+
join21(homedir11(), ".augmented", agent.code_name)
|
|
11363
11416
|
);
|
|
11364
11417
|
const prevIds = /* @__PURE__ */ new Set([
|
|
11365
11418
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -11379,15 +11432,15 @@ async function processAgent(agent, agentStates) {
|
|
|
11379
11432
|
}
|
|
11380
11433
|
if (plan.removes.length) {
|
|
11381
11434
|
const globalSkillDirs = [
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11435
|
+
join21(homedir11(), ".augmented", agent.code_name, "skills"),
|
|
11436
|
+
join21(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
11437
|
+
join21(agentDir, ".claude", "skills")
|
|
11385
11438
|
];
|
|
11386
11439
|
for (const id of plan.removes) {
|
|
11387
11440
|
let prunedAny = false;
|
|
11388
11441
|
for (const dir of globalSkillDirs) {
|
|
11389
|
-
const p =
|
|
11390
|
-
if (
|
|
11442
|
+
const p = join21(dir, id);
|
|
11443
|
+
if (existsSync12(p) && existsSync12(join21(p, "SKILL.md"))) {
|
|
11391
11444
|
rmSync4(p, { recursive: true, force: true });
|
|
11392
11445
|
prunedAny = true;
|
|
11393
11446
|
}
|
|
@@ -11534,11 +11587,13 @@ async function processAgent(agent, agentStates) {
|
|
|
11534
11587
|
"completed",
|
|
11535
11588
|
"kanban inject suppressed \u2014 suspected poison card(s) (ENG-6171)"
|
|
11536
11589
|
);
|
|
11537
|
-
} else
|
|
11538
|
-
|
|
11539
|
-
openInjectedRunByCode.
|
|
11540
|
-
|
|
11541
|
-
|
|
11590
|
+
} else {
|
|
11591
|
+
clearKanbanNudgeState(agent.code_name);
|
|
11592
|
+
if (openInjectedRunByCode.has(agent.code_name)) {
|
|
11593
|
+
const openRunId = openInjectedRunByCode.get(agent.code_name);
|
|
11594
|
+
openInjectedRunByCode.delete(agent.code_name);
|
|
11595
|
+
void cancelKanbanNoticeOnDrain(agent.code_name, agent.agent_id, openRunId);
|
|
11596
|
+
}
|
|
11542
11597
|
}
|
|
11543
11598
|
}
|
|
11544
11599
|
}
|
|
@@ -11590,8 +11645,8 @@ async function processAgent(agent, agentStates) {
|
|
|
11590
11645
|
const sess = getSessionState(agent.code_name);
|
|
11591
11646
|
let mcpJsonParsed = null;
|
|
11592
11647
|
try {
|
|
11593
|
-
const mcpPath =
|
|
11594
|
-
mcpJsonParsed = JSON.parse(
|
|
11648
|
+
const mcpPath = join21(getProjectDir(agent.code_name), ".mcp.json");
|
|
11649
|
+
mcpJsonParsed = JSON.parse(readFileSync18(mcpPath, "utf-8"));
|
|
11595
11650
|
} catch {
|
|
11596
11651
|
}
|
|
11597
11652
|
reapMissingMcpSessions({
|
|
@@ -11916,10 +11971,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
11916
11971
|
}
|
|
11917
11972
|
}
|
|
11918
11973
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
11919
|
-
if (trackedFiles.length > 0 &&
|
|
11974
|
+
if (trackedFiles.length > 0 && existsSync12(agentDir)) {
|
|
11920
11975
|
const hashes = /* @__PURE__ */ new Map();
|
|
11921
11976
|
for (const file of trackedFiles) {
|
|
11922
|
-
const h = hashFile(
|
|
11977
|
+
const h = hashFile(join21(agentDir, file));
|
|
11923
11978
|
if (h) hashes.set(file, h);
|
|
11924
11979
|
}
|
|
11925
11980
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -11934,7 +11989,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
11934
11989
|
refreshData.agent.onboarding_state
|
|
11935
11990
|
);
|
|
11936
11991
|
const obStep = obState.step;
|
|
11937
|
-
const markerPath =
|
|
11992
|
+
const markerPath = join21(homedir11(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
11938
11993
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
11939
11994
|
const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
|
|
11940
11995
|
if (decision.clearMarker) {
|
|
@@ -12002,7 +12057,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
12002
12057
|
return { decision: "healthy", spawnAttempted: false, sessionHealthyAfter: true };
|
|
12003
12058
|
}
|
|
12004
12059
|
stopOpencodeSlackIngest(codeName, log);
|
|
12005
|
-
const opencodeProjectDir =
|
|
12060
|
+
const opencodeProjectDir = join21(getFramework("opencode").getAgentDir(codeName), "project");
|
|
12006
12061
|
const openRouterRaw = refreshData.openrouter ?? null;
|
|
12007
12062
|
const serveEnv = {
|
|
12008
12063
|
AGT_HOST: requireHost(),
|
|
@@ -12042,8 +12097,8 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
12042
12097
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
12043
12098
|
const codeName = agent.code_name;
|
|
12044
12099
|
const projectDir = getProjectDir(codeName);
|
|
12045
|
-
const mcpConfigPath =
|
|
12046
|
-
const claudeMdPath =
|
|
12100
|
+
const mcpConfigPath = join21(projectDir, ".mcp.json");
|
|
12101
|
+
const claudeMdPath = join21(projectDir, "CLAUDE.md");
|
|
12047
12102
|
if (restartBreaker.isTripped(codeName)) {
|
|
12048
12103
|
const trip = restartBreaker.getTrip(codeName);
|
|
12049
12104
|
return {
|
|
@@ -12581,7 +12636,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
12581
12636
|
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}`));
|
|
12582
12637
|
void (async () => {
|
|
12583
12638
|
try {
|
|
12584
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
12639
|
+
const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
|
|
12585
12640
|
await api.post("/host/heartbeat", {
|
|
12586
12641
|
host_id: hostId,
|
|
12587
12642
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -12631,7 +12686,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
12631
12686
|
}
|
|
12632
12687
|
try {
|
|
12633
12688
|
const hostId = await getHostId();
|
|
12634
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
12689
|
+
const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
|
|
12635
12690
|
await api.post("/host/heartbeat", {
|
|
12636
12691
|
host_id: hostId,
|
|
12637
12692
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -12918,7 +12973,7 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
12918
12973
|
try {
|
|
12919
12974
|
const doorbell = directChatDoorbellPath(agent.agentId, homedir11());
|
|
12920
12975
|
mkdirSync8(dirname6(doorbell), { recursive: true });
|
|
12921
|
-
|
|
12976
|
+
writeFileSync9(doorbell, String(Date.now()));
|
|
12922
12977
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
12923
12978
|
return;
|
|
12924
12979
|
} catch (err) {
|
|
@@ -12950,6 +13005,21 @@ ${escapeXml(msg.content)}
|
|
|
12950
13005
|
}
|
|
12951
13006
|
var lastKanbanInjectAt = /* @__PURE__ */ new Map();
|
|
12952
13007
|
var kanbanNudgeStateByCode = /* @__PURE__ */ new Map();
|
|
13008
|
+
function loadKanbanNudgeStateFromDisk() {
|
|
13009
|
+
loadKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
13010
|
+
}
|
|
13011
|
+
function setKanbanNudgeState(codeName, state7) {
|
|
13012
|
+
kanbanNudgeStateByCode.set(codeName, state7);
|
|
13013
|
+
saveKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
13014
|
+
}
|
|
13015
|
+
function clearKanbanNudgeState(codeName) {
|
|
13016
|
+
if (!kanbanNudgeStateByCode.delete(codeName)) return;
|
|
13017
|
+
saveKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
13018
|
+
}
|
|
13019
|
+
function nextKanbanNudgeCount(codeName, signature) {
|
|
13020
|
+
const prev = kanbanNudgeStateByCode.get(codeName);
|
|
13021
|
+
return prev && prev.signature === signature ? (prev.nudgeCount ?? 1) + 1 : 1;
|
|
13022
|
+
}
|
|
12953
13023
|
var openInjectedRunByCode = /* @__PURE__ */ new Map();
|
|
12954
13024
|
function closeInjectedRunIfOpen(codeName, outcome, outcomeMessage) {
|
|
12955
13025
|
const runId = openInjectedRunByCode.get(codeName);
|
|
@@ -12982,6 +13052,12 @@ var KANBAN_HYBRID_FULL_CADENCE_MS = (() => {
|
|
|
12982
13052
|
if (Number.isFinite(parsed) && parsed > 0) return Math.max(parsed * 1e3, KANBAN_HYBRID_DEBOUNCE_MS);
|
|
12983
13053
|
return Math.max(5 * 6e4, KANBAN_HYBRID_DEBOUNCE_MS);
|
|
12984
13054
|
})();
|
|
13055
|
+
var KANBAN_HYBRID_MAX_CADENCE_MS = (() => {
|
|
13056
|
+
const raw = process.env["AGT_KANBAN_HYBRID_MAX_CADENCE_SECONDS"];
|
|
13057
|
+
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
13058
|
+
if (Number.isFinite(parsed) && parsed > 0) return Math.max(parsed * 1e3, KANBAN_HYBRID_FULL_CADENCE_MS);
|
|
13059
|
+
return Math.max(60 * 6e4, KANBAN_HYBRID_FULL_CADENCE_MS);
|
|
13060
|
+
})();
|
|
12985
13061
|
async function injectKanbanCheckViaDirectChat(codeName, agentId, actionableCount) {
|
|
12986
13062
|
if (isKanbanHybridDryRun()) {
|
|
12987
13063
|
log(
|
|
@@ -13007,7 +13083,7 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
13007
13083
|
try {
|
|
13008
13084
|
const doorbell = directChatDoorbellPath(agentId, homedir11());
|
|
13009
13085
|
mkdirSync8(dirname6(doorbell), { recursive: true });
|
|
13010
|
-
|
|
13086
|
+
writeFileSync9(doorbell, String(Date.now()));
|
|
13011
13087
|
} catch (err) {
|
|
13012
13088
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
13013
13089
|
}
|
|
@@ -13021,7 +13097,8 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
|
|
|
13021
13097
|
signature,
|
|
13022
13098
|
kanbanNudgeStateByCode.get(codeName),
|
|
13023
13099
|
Date.now(),
|
|
13024
|
-
KANBAN_HYBRID_FULL_CADENCE_MS
|
|
13100
|
+
KANBAN_HYBRID_FULL_CADENCE_MS,
|
|
13101
|
+
KANBAN_HYBRID_MAX_CADENCE_MS
|
|
13025
13102
|
)) {
|
|
13026
13103
|
return;
|
|
13027
13104
|
}
|
|
@@ -13033,7 +13110,11 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
|
|
|
13033
13110
|
if (hostFlagStore().getBoolean("kanban-doorbell")) {
|
|
13034
13111
|
const ok = await injectKanbanCheckViaDirectChat(codeName, agentId, actionableCount);
|
|
13035
13112
|
if (ok) {
|
|
13036
|
-
|
|
13113
|
+
setKanbanNudgeState(codeName, {
|
|
13114
|
+
signature,
|
|
13115
|
+
nudgedAt: Date.now(),
|
|
13116
|
+
nudgeCount: nextKanbanNudgeCount(codeName, signature)
|
|
13117
|
+
});
|
|
13037
13118
|
return;
|
|
13038
13119
|
}
|
|
13039
13120
|
log(`[manager-worker] kanban direct-chat enqueue failed for '${codeName}' \u2014 falling back to send-keys`);
|
|
@@ -13067,7 +13148,11 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
13067
13148
|
}
|
|
13068
13149
|
if (delivered) {
|
|
13069
13150
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
13070
|
-
|
|
13151
|
+
setKanbanNudgeState(codeName, {
|
|
13152
|
+
signature,
|
|
13153
|
+
nudgedAt: Date.now(),
|
|
13154
|
+
nudgeCount: nextKanbanNudgeCount(codeName, signature)
|
|
13155
|
+
});
|
|
13071
13156
|
log(
|
|
13072
13157
|
`[manager-worker] Injected kanban check for '${codeName}' (${actionableCount} actionable items)${run_id ? ` run_id=${run_id}` : ""}`
|
|
13073
13158
|
);
|
|
@@ -13099,7 +13184,7 @@ async function processClaudePairSessions(agents) {
|
|
|
13099
13184
|
killPairSession,
|
|
13100
13185
|
pairTmuxSession,
|
|
13101
13186
|
finalizeClaudePairOnboarding
|
|
13102
|
-
} = await import("../claude-pair-runtime-
|
|
13187
|
+
} = await import("../claude-pair-runtime-BOFTEAQC.js");
|
|
13103
13188
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
13104
13189
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
13105
13190
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -13342,8 +13427,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
13342
13427
|
};
|
|
13343
13428
|
}
|
|
13344
13429
|
async function syncMemories(agent, configDir, log2) {
|
|
13345
|
-
const projectDir =
|
|
13346
|
-
const memoryDir =
|
|
13430
|
+
const projectDir = join21(configDir, agent.code_name, "project");
|
|
13431
|
+
const memoryDir = join21(projectDir, "memory");
|
|
13347
13432
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
13348
13433
|
if (isFreshSync) {
|
|
13349
13434
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -13354,14 +13439,14 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
13354
13439
|
}
|
|
13355
13440
|
pendingFreshMemorySync.delete(agent.agent_id);
|
|
13356
13441
|
}
|
|
13357
|
-
if (
|
|
13442
|
+
if (existsSync12(memoryDir)) {
|
|
13358
13443
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
13359
13444
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
13360
13445
|
const changedMemories = [];
|
|
13361
13446
|
for (const file of readdirSync5(memoryDir)) {
|
|
13362
13447
|
if (!file.endsWith(".md")) continue;
|
|
13363
13448
|
try {
|
|
13364
|
-
const raw =
|
|
13449
|
+
const raw = readFileSync18(join21(memoryDir, file), "utf-8");
|
|
13365
13450
|
const fileHash = createHash12("sha256").update(raw).digest("hex").slice(0, 16);
|
|
13366
13451
|
currentHashes.set(file, fileHash);
|
|
13367
13452
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -13386,7 +13471,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
13386
13471
|
} catch (err) {
|
|
13387
13472
|
for (const mem of changedMemories) {
|
|
13388
13473
|
for (const [file] of currentHashes) {
|
|
13389
|
-
const parsed = parseMemoryFile(
|
|
13474
|
+
const parsed = parseMemoryFile(readFileSync18(join21(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
13390
13475
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
13391
13476
|
}
|
|
13392
13477
|
}
|
|
@@ -13399,7 +13484,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
13399
13484
|
}
|
|
13400
13485
|
}
|
|
13401
13486
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
13402
|
-
const localFiles =
|
|
13487
|
+
const localFiles = existsSync12(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
13403
13488
|
const localListHash = createHash12("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
13404
13489
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
13405
13490
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
@@ -13421,7 +13506,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
|
13421
13506
|
const mem = dbMemories.memories[i];
|
|
13422
13507
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
13423
13508
|
const slug = rawSlug || `memory-${i}`;
|
|
13424
|
-
const filePath =
|
|
13509
|
+
const filePath = join21(memoryDir, `${slug}.md`);
|
|
13425
13510
|
const desired = `---
|
|
13426
13511
|
name: ${JSON.stringify(mem.name)}
|
|
13427
13512
|
type: ${mem.type}
|
|
@@ -13430,17 +13515,17 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
|
|
|
13430
13515
|
|
|
13431
13516
|
${mem.content}
|
|
13432
13517
|
`;
|
|
13433
|
-
if (
|
|
13518
|
+
if (existsSync12(filePath)) {
|
|
13434
13519
|
let existing = "";
|
|
13435
13520
|
try {
|
|
13436
|
-
existing =
|
|
13521
|
+
existing = readFileSync18(filePath, "utf-8");
|
|
13437
13522
|
} catch {
|
|
13438
13523
|
}
|
|
13439
13524
|
if (existing === desired) continue;
|
|
13440
|
-
|
|
13525
|
+
writeFileSync9(filePath, desired);
|
|
13441
13526
|
overwritten++;
|
|
13442
13527
|
} else {
|
|
13443
|
-
|
|
13528
|
+
writeFileSync9(filePath, desired);
|
|
13444
13529
|
written++;
|
|
13445
13530
|
}
|
|
13446
13531
|
}
|
|
@@ -13457,7 +13542,7 @@ ${mem.content}
|
|
|
13457
13542
|
}
|
|
13458
13543
|
}
|
|
13459
13544
|
async function cleanupAgentFiles(codeName, agentDir) {
|
|
13460
|
-
if (
|
|
13545
|
+
if (existsSync12(agentDir)) {
|
|
13461
13546
|
try {
|
|
13462
13547
|
rmSync4(agentDir, { recursive: true, force: true });
|
|
13463
13548
|
log(`Removed provision directory for '${codeName}'`);
|
|
@@ -13567,6 +13652,7 @@ function startPolling() {
|
|
|
13567
13652
|
void startCaffeinate();
|
|
13568
13653
|
loadChannelHashCache2();
|
|
13569
13654
|
loadSenderPolicyBaseline2();
|
|
13655
|
+
loadKanbanNudgeStateFromDisk();
|
|
13570
13656
|
hostFlagStore().init();
|
|
13571
13657
|
log(`Starting poll loop (interval=${config.intervalMs}ms, configDir=${config.configDir})`);
|
|
13572
13658
|
void killAllAgtTmuxSessions().catch(() => {
|
|
@@ -13692,8 +13778,8 @@ function startManager(opts) {
|
|
|
13692
13778
|
config = opts;
|
|
13693
13779
|
try {
|
|
13694
13780
|
const stateFile = getStateFile();
|
|
13695
|
-
if (
|
|
13696
|
-
const raw =
|
|
13781
|
+
if (existsSync12(stateFile)) {
|
|
13782
|
+
const raw = readFileSync18(stateFile, "utf-8");
|
|
13697
13783
|
const parsed = JSON.parse(raw);
|
|
13698
13784
|
if (Array.isArray(parsed.agents)) {
|
|
13699
13785
|
state6.agents = parsed.agents;
|
|
@@ -13720,7 +13806,7 @@ function startManager(opts) {
|
|
|
13720
13806
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
13721
13807
|
}
|
|
13722
13808
|
log(
|
|
13723
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
13809
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join21(homedir11(), ".augmented", "manager.log")}`
|
|
13724
13810
|
);
|
|
13725
13811
|
deployMcpAssets();
|
|
13726
13812
|
reapOrphanChannelMcps({ log });
|
|
@@ -13741,7 +13827,7 @@ async function reapOrphanedClaudePids() {
|
|
|
13741
13827
|
const looksLikeClaude = (pid) => {
|
|
13742
13828
|
if (process.platform !== "linux") return true;
|
|
13743
13829
|
try {
|
|
13744
|
-
const comm =
|
|
13830
|
+
const comm = readFileSync18(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
13745
13831
|
return comm.includes("claude");
|
|
13746
13832
|
} catch {
|
|
13747
13833
|
return false;
|
|
@@ -13838,14 +13924,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
13838
13924
|
}
|
|
13839
13925
|
}
|
|
13840
13926
|
function deployMcpAssets() {
|
|
13841
|
-
const targetDir =
|
|
13927
|
+
const targetDir = join21(homedir11(), ".augmented", "_mcp");
|
|
13842
13928
|
mkdirSync8(targetDir, { recursive: true });
|
|
13843
13929
|
const moduleDir = dirname6(fileURLToPath(import.meta.url));
|
|
13844
13930
|
let mcpSourceDir = "";
|
|
13845
13931
|
let dir = moduleDir;
|
|
13846
13932
|
for (let i = 0; i < 6; i++) {
|
|
13847
|
-
const candidate =
|
|
13848
|
-
if (
|
|
13933
|
+
const candidate = join21(dir, "dist", "mcp");
|
|
13934
|
+
if (existsSync12(join21(candidate, "index.js"))) {
|
|
13849
13935
|
mcpSourceDir = candidate;
|
|
13850
13936
|
break;
|
|
13851
13937
|
}
|
|
@@ -13860,8 +13946,8 @@ function deployMcpAssets() {
|
|
|
13860
13946
|
const changedBasenames = [];
|
|
13861
13947
|
const fileHash = (p) => {
|
|
13862
13948
|
try {
|
|
13863
|
-
if (!
|
|
13864
|
-
return createHash12("sha256").update(
|
|
13949
|
+
if (!existsSync12(p)) return null;
|
|
13950
|
+
return createHash12("sha256").update(readFileSync18(p)).digest("hex");
|
|
13865
13951
|
} catch {
|
|
13866
13952
|
return null;
|
|
13867
13953
|
}
|
|
@@ -13925,9 +14011,9 @@ function deployMcpAssets() {
|
|
|
13925
14011
|
// needs restarting to pick up a token rotation.
|
|
13926
14012
|
"xero.js"
|
|
13927
14013
|
]) {
|
|
13928
|
-
const src =
|
|
13929
|
-
const dst =
|
|
13930
|
-
if (!
|
|
14014
|
+
const src = join21(mcpSourceDir, file);
|
|
14015
|
+
const dst = join21(targetDir, file);
|
|
14016
|
+
if (!existsSync12(src)) continue;
|
|
13931
14017
|
const before = fileHash(dst);
|
|
13932
14018
|
try {
|
|
13933
14019
|
copyFileSync(src, dst);
|
|
@@ -13944,23 +14030,23 @@ function deployMcpAssets() {
|
|
|
13944
14030
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
13945
14031
|
restartRunningChannelMcps(changedBasenames);
|
|
13946
14032
|
}
|
|
13947
|
-
const localMcpPath =
|
|
14033
|
+
const localMcpPath = join21(targetDir, "index.js");
|
|
13948
14034
|
try {
|
|
13949
|
-
const agentsDir =
|
|
13950
|
-
if (
|
|
14035
|
+
const agentsDir = join21(homedir11(), ".augmented", "agents");
|
|
14036
|
+
if (existsSync12(agentsDir)) {
|
|
13951
14037
|
for (const entry of readdirSync5(agentsDir, { withFileTypes: true })) {
|
|
13952
14038
|
if (!entry.isDirectory()) continue;
|
|
13953
14039
|
for (const subdir of ["provision", "project"]) {
|
|
13954
|
-
const mcpJsonPath =
|
|
14040
|
+
const mcpJsonPath = join21(agentsDir, entry.name, subdir, ".mcp.json");
|
|
13955
14041
|
try {
|
|
13956
|
-
const raw =
|
|
14042
|
+
const raw = readFileSync18(mcpJsonPath, "utf-8");
|
|
13957
14043
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
13958
14044
|
const mcpConfig = JSON.parse(raw);
|
|
13959
14045
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
13960
14046
|
if (!augServer) continue;
|
|
13961
14047
|
augServer.command = "node";
|
|
13962
14048
|
augServer.args = [localMcpPath];
|
|
13963
|
-
|
|
14049
|
+
writeFileSync9(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
13964
14050
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
13965
14051
|
} catch {
|
|
13966
14052
|
}
|