@integrity-labs/agt-cli 0.28.13-canary.18 → 0.28.13
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 +3 -3
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-BBTTZRCH.js → chunk-4YCCLGVU.js} +1 -1
- package/dist/lib/manager-worker.js +374 -369
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-BBTTZRCH.js.map → chunk-4YCCLGVU.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
provisionStopHook,
|
|
23
23
|
requireHost,
|
|
24
24
|
safeWriteJsonAtomic
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-4YCCLGVU.js";
|
|
26
26
|
import {
|
|
27
27
|
getProjectDir as getProjectDir2,
|
|
28
28
|
getReadyTasks,
|
|
@@ -103,12 +103,12 @@ import {
|
|
|
103
103
|
} from "../chunk-XWVM4KPK.js";
|
|
104
104
|
|
|
105
105
|
// src/lib/manager-worker.ts
|
|
106
|
-
import { createHash as
|
|
107
|
-
import { readFileSync as
|
|
106
|
+
import { createHash as createHash4 } from "crypto";
|
|
107
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync6, rmSync as rmSync2, readdirSync as readdirSync5, statSync as statSync4, unlinkSync, copyFileSync } from "fs";
|
|
108
108
|
import https from "https";
|
|
109
109
|
import { execFileSync as syncExecFile } from "child_process";
|
|
110
|
-
import { join as
|
|
111
|
-
import { homedir as
|
|
110
|
+
import { join as join12, dirname as dirname3 } from "path";
|
|
111
|
+
import { homedir as homedir6 } from "os";
|
|
112
112
|
import { fileURLToPath } from "url";
|
|
113
113
|
|
|
114
114
|
// src/lib/mcp-config-drift.ts
|
|
@@ -3674,6 +3674,134 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash) {
|
|
|
3674
3674
|
return { installs, removes, currentIds };
|
|
3675
3675
|
}
|
|
3676
3676
|
|
|
3677
|
+
// src/lib/manager/runtime.ts
|
|
3678
|
+
import { createHash as createHash3 } from "crypto";
|
|
3679
|
+
import { readFileSync as readFileSync9, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync4 } from "fs";
|
|
3680
|
+
import { join as join10, dirname as dirname2 } from "path";
|
|
3681
|
+
import { homedir as homedir4 } from "os";
|
|
3682
|
+
function redactForDiskLog(value) {
|
|
3683
|
+
try {
|
|
3684
|
+
return value.replace(/\b(Bearer\s+)[A-Za-z0-9._-]+\b/gi, "$1[REDACTED]").replace(/\bxox[baprs]-[A-Za-z0-9-]+\b/g, "[REDACTED-SLACK]").replace(/\btlk_[A-Za-z0-9._-]+\b/g, "[REDACTED-HOST]").replace(/\bsk-ant-[A-Za-z0-9_-]+\b/g, "[REDACTED-ANTHROPIC]").replace(/\b\d{8,12}:[A-Za-z0-9_-]{30,}\b/g, "[REDACTED-TELEGRAM]").replace(
|
|
3685
|
+
/\b([A-Z0-9_]*(?:TOKEN|SECRET|API[_-]?KEY|PASSWORD)[A-Z0-9_]*)=(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s\r\n]+)/gi,
|
|
3686
|
+
"$1=[REDACTED]"
|
|
3687
|
+
);
|
|
3688
|
+
} catch {
|
|
3689
|
+
return "[REDACTED]";
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
var managerLogPath = null;
|
|
3693
|
+
var managerLogWritable = true;
|
|
3694
|
+
function log(msg) {
|
|
3695
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
3696
|
+
const safeMsg = redactForDiskLog(msg);
|
|
3697
|
+
const line = `[manager-worker ${ts}] ${safeMsg}
|
|
3698
|
+
`;
|
|
3699
|
+
if (!managerLogPath) {
|
|
3700
|
+
try {
|
|
3701
|
+
managerLogPath = join10(homedir4(), ".augmented", "manager.log");
|
|
3702
|
+
mkdirSync2(dirname2(managerLogPath), { recursive: true });
|
|
3703
|
+
if (existsSync4(managerLogPath)) {
|
|
3704
|
+
chmodSync(managerLogPath, 384);
|
|
3705
|
+
}
|
|
3706
|
+
} catch {
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
let appendedToFile = false;
|
|
3710
|
+
if (managerLogPath && managerLogWritable) {
|
|
3711
|
+
try {
|
|
3712
|
+
appendFileSync(managerLogPath, line, { encoding: "utf-8", mode: 384 });
|
|
3713
|
+
appendedToFile = true;
|
|
3714
|
+
} catch (err) {
|
|
3715
|
+
managerLogWritable = false;
|
|
3716
|
+
process.stderr.write(
|
|
3717
|
+
`[manager-worker ${ts}] [log] manager.log append failed; falling back to stderr-only: ${err.message}
|
|
3718
|
+
`
|
|
3719
|
+
);
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
if (!appendedToFile || process.stderr.isTTY === true) {
|
|
3723
|
+
process.stderr.write(line);
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3726
|
+
function sha256(content) {
|
|
3727
|
+
return createHash3("sha256").update(content, "utf8").digest("hex");
|
|
3728
|
+
}
|
|
3729
|
+
function hashFile(filePath) {
|
|
3730
|
+
try {
|
|
3731
|
+
const content = readFileSync9(filePath, "utf-8");
|
|
3732
|
+
return sha256(content);
|
|
3733
|
+
} catch {
|
|
3734
|
+
return null;
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
async function execFilePromise(cmd, args) {
|
|
3738
|
+
const { execFile: ef } = await import("child_process");
|
|
3739
|
+
return new Promise((resolve, reject) => {
|
|
3740
|
+
ef(cmd, args, { timeout: 15e3 }, (err, stdout, stderr) => {
|
|
3741
|
+
if (err) reject(err);
|
|
3742
|
+
else resolve({ stdout, stderr });
|
|
3743
|
+
});
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
var ChildProcessError = class extends Error {
|
|
3747
|
+
code;
|
|
3748
|
+
stdout;
|
|
3749
|
+
stderr;
|
|
3750
|
+
constructor(code, stdout, stderr) {
|
|
3751
|
+
const stderrSnippet = stderr.trim().slice(0, 500);
|
|
3752
|
+
const stdoutSnippet = stdout.trim().slice(0, 500);
|
|
3753
|
+
const detail = stderrSnippet || stdoutSnippet || "(no output)";
|
|
3754
|
+
super(`Exit code ${code}: ${detail}`);
|
|
3755
|
+
this.name = "ChildProcessError";
|
|
3756
|
+
this.code = code;
|
|
3757
|
+
this.stdout = stdout;
|
|
3758
|
+
this.stderr = stderr;
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
async function execFilePromiseLong(cmd, args, opts) {
|
|
3762
|
+
const { spawn: sp } = await import("child_process");
|
|
3763
|
+
return new Promise((resolve, reject) => {
|
|
3764
|
+
const child = sp(cmd, args, {
|
|
3765
|
+
cwd: opts?.cwd,
|
|
3766
|
+
stdio: [opts?.stdin === "ignore" ? "ignore" : "pipe", "pipe", "pipe"],
|
|
3767
|
+
...opts?.env ? { env: opts.env } : {}
|
|
3768
|
+
});
|
|
3769
|
+
if (opts?.onSpawn && typeof child.pid === "number") {
|
|
3770
|
+
try {
|
|
3771
|
+
opts.onSpawn(child.pid);
|
|
3772
|
+
} catch {
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
let stdout = "";
|
|
3776
|
+
let stderr = "";
|
|
3777
|
+
child.stdout?.on("data", (d) => {
|
|
3778
|
+
stdout += d.toString();
|
|
3779
|
+
});
|
|
3780
|
+
child.stderr?.on("data", (d) => {
|
|
3781
|
+
stderr += d.toString();
|
|
3782
|
+
});
|
|
3783
|
+
const timer = setTimeout(() => {
|
|
3784
|
+
child.kill();
|
|
3785
|
+
reject(new Error(`Timed out after ${opts?.timeout ?? 12e4}ms`));
|
|
3786
|
+
}, opts?.timeout ?? 12e4);
|
|
3787
|
+
child.on("close", (code) => {
|
|
3788
|
+
clearTimeout(timer);
|
|
3789
|
+
if (opts?.onExit && typeof child.pid === "number") {
|
|
3790
|
+
try {
|
|
3791
|
+
opts.onExit(child.pid);
|
|
3792
|
+
} catch {
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
if (code !== 0) reject(new ChildProcessError(code, stdout, stderr));
|
|
3796
|
+
else resolve({ stdout, stderr });
|
|
3797
|
+
});
|
|
3798
|
+
child.on("error", (err) => {
|
|
3799
|
+
clearTimeout(timer);
|
|
3800
|
+
reject(err);
|
|
3801
|
+
});
|
|
3802
|
+
});
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3677
3805
|
// src/lib/wedge-detection.ts
|
|
3678
3806
|
var DEFAULTS = {
|
|
3679
3807
|
inboundWaitSeconds: 120,
|
|
@@ -3813,24 +3941,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
3813
3941
|
}
|
|
3814
3942
|
|
|
3815
3943
|
// src/lib/restart-flags.ts
|
|
3816
|
-
import { existsSync as
|
|
3817
|
-
import { homedir as
|
|
3818
|
-
import { join as
|
|
3944
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync10, renameSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
3945
|
+
import { homedir as homedir5 } from "os";
|
|
3946
|
+
import { join as join11 } from "path";
|
|
3819
3947
|
import { randomUUID } from "crypto";
|
|
3820
3948
|
function restartFlagsDir() {
|
|
3821
|
-
return
|
|
3949
|
+
return join11(homedir5(), ".augmented", "restart-flags");
|
|
3822
3950
|
}
|
|
3823
3951
|
function flagPath(codeName) {
|
|
3824
|
-
return
|
|
3952
|
+
return join11(restartFlagsDir(), `${codeName}.flag`);
|
|
3825
3953
|
}
|
|
3826
3954
|
function readRestartFlags() {
|
|
3827
3955
|
const dir = restartFlagsDir();
|
|
3828
|
-
if (!
|
|
3956
|
+
if (!existsSync5(dir)) return [];
|
|
3829
3957
|
const out = [];
|
|
3830
3958
|
for (const entry of readdirSync4(dir)) {
|
|
3831
3959
|
if (!entry.endsWith(".flag")) continue;
|
|
3832
3960
|
try {
|
|
3833
|
-
const raw =
|
|
3961
|
+
const raw = readFileSync10(join11(dir, entry), "utf8");
|
|
3834
3962
|
const parsed = JSON.parse(raw);
|
|
3835
3963
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
3836
3964
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -3848,7 +3976,7 @@ function readRestartFlags() {
|
|
|
3848
3976
|
}
|
|
3849
3977
|
function deleteRestartFlag(codeName) {
|
|
3850
3978
|
const path = flagPath(codeName);
|
|
3851
|
-
if (
|
|
3979
|
+
if (existsSync5(path)) {
|
|
3852
3980
|
rmSync(path, { force: true });
|
|
3853
3981
|
}
|
|
3854
3982
|
}
|
|
@@ -4378,8 +4506,8 @@ function applyRestartAcks(args) {
|
|
|
4378
4506
|
var GATEWAY_PORT_BASE = 18800;
|
|
4379
4507
|
var GATEWAY_PORT_STEP = 10;
|
|
4380
4508
|
var GATEWAY_PORT_MAX = 18899;
|
|
4381
|
-
var AUGMENTED_DIR =
|
|
4382
|
-
var GATEWAY_PORTS_FILE =
|
|
4509
|
+
var AUGMENTED_DIR = join12(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
4510
|
+
var GATEWAY_PORTS_FILE = join12(AUGMENTED_DIR, "gateway-ports.json");
|
|
4383
4511
|
var CHANNEL_SWEEP_INTERVAL_MS = (() => {
|
|
4384
4512
|
const raw = parseInt(process.env["AGT_CHANNEL_SWEEP_INTERVAL_MS"] ?? "", 10);
|
|
4385
4513
|
if (!Number.isFinite(raw)) return 5 * 60 * 1e3;
|
|
@@ -4754,15 +4882,15 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
|
|
|
4754
4882
|
var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
4755
4883
|
function projectMcpHash(_codeName, projectDir) {
|
|
4756
4884
|
try {
|
|
4757
|
-
const raw =
|
|
4758
|
-
return
|
|
4885
|
+
const raw = readFileSync11(join12(projectDir, ".mcp.json"), "utf-8");
|
|
4886
|
+
return createHash4("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
4759
4887
|
} catch {
|
|
4760
4888
|
return null;
|
|
4761
4889
|
}
|
|
4762
4890
|
}
|
|
4763
4891
|
function projectMcpKeys(_codeName, projectDir) {
|
|
4764
4892
|
try {
|
|
4765
|
-
const raw =
|
|
4893
|
+
const raw = readFileSync11(join12(projectDir, ".mcp.json"), "utf-8");
|
|
4766
4894
|
const parsed = JSON.parse(raw);
|
|
4767
4895
|
const servers = parsed.mcpServers;
|
|
4768
4896
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -4773,7 +4901,7 @@ function projectMcpKeys(_codeName, projectDir) {
|
|
|
4773
4901
|
}
|
|
4774
4902
|
function readMcpHttpServerConfig(projectDir, serverKey, env) {
|
|
4775
4903
|
try {
|
|
4776
|
-
const raw =
|
|
4904
|
+
const raw = readFileSync11(join12(projectDir, ".mcp.json"), "utf-8");
|
|
4777
4905
|
const servers = JSON.parse(raw).mcpServers ?? {};
|
|
4778
4906
|
const entry = servers[serverKey];
|
|
4779
4907
|
if (entry && typeof entry.url === "string" && (entry.type === "http" || entry.type === void 0)) {
|
|
@@ -4801,9 +4929,9 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
|
|
|
4801
4929
|
if (integrations.length === 0) return;
|
|
4802
4930
|
const probeEnv = { ...process.env };
|
|
4803
4931
|
try {
|
|
4804
|
-
const envIntPath =
|
|
4805
|
-
if (
|
|
4806
|
-
Object.assign(probeEnv, parseEnvIntegrations(
|
|
4932
|
+
const envIntPath = join12(projectDir, ".env.integrations");
|
|
4933
|
+
if (existsSync6(envIntPath)) {
|
|
4934
|
+
Object.assign(probeEnv, parseEnvIntegrations(readFileSync11(envIntPath, "utf-8")));
|
|
4807
4935
|
}
|
|
4808
4936
|
} catch {
|
|
4809
4937
|
}
|
|
@@ -4991,7 +5119,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
4991
5119
|
function projectChannelSecretHash(projectDir) {
|
|
4992
5120
|
try {
|
|
4993
5121
|
const entries = parseEnvIntegrations(
|
|
4994
|
-
|
|
5122
|
+
readFileSync11(join12(projectDir, ".env.integrations"), "utf-8")
|
|
4995
5123
|
);
|
|
4996
5124
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
4997
5125
|
} catch {
|
|
@@ -5083,7 +5211,7 @@ var cachedMaintenanceWindow = null;
|
|
|
5083
5211
|
var lastVersionCheckAt = 0;
|
|
5084
5212
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
5085
5213
|
var lastResponsivenessProbeAt = 0;
|
|
5086
|
-
var agtCliVersion = true ? "0.28.13
|
|
5214
|
+
var agtCliVersion = true ? "0.28.13" : "dev";
|
|
5087
5215
|
function resolveBrewPath(execFileSync4) {
|
|
5088
5216
|
try {
|
|
5089
5217
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -5096,7 +5224,7 @@ function resolveBrewPath(execFileSync4) {
|
|
|
5096
5224
|
"/usr/local/bin/brew"
|
|
5097
5225
|
];
|
|
5098
5226
|
for (const path of fallbacks) {
|
|
5099
|
-
if (
|
|
5227
|
+
if (existsSync6(path)) return path;
|
|
5100
5228
|
}
|
|
5101
5229
|
return null;
|
|
5102
5230
|
}
|
|
@@ -5106,7 +5234,7 @@ function claudeBinaryInstalled(execFileSync4) {
|
|
|
5106
5234
|
"/opt/homebrew/bin/claude",
|
|
5107
5235
|
"/usr/local/bin/claude"
|
|
5108
5236
|
];
|
|
5109
|
-
if (canonical.some((path) =>
|
|
5237
|
+
if (canonical.some((path) => existsSync6(path))) return true;
|
|
5110
5238
|
try {
|
|
5111
5239
|
execFileSync4("which", ["claude"], { timeout: 5e3 });
|
|
5112
5240
|
return true;
|
|
@@ -5178,7 +5306,7 @@ async function ensureToolkitCli(toolkitSlug) {
|
|
|
5178
5306
|
toolkitCliEnsured.add(toolkitSlug);
|
|
5179
5307
|
return;
|
|
5180
5308
|
}
|
|
5181
|
-
brewBinDir =
|
|
5309
|
+
brewBinDir = dirname3(brewPath);
|
|
5182
5310
|
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
5183
5311
|
log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
|
|
5184
5312
|
if (isRoot) {
|
|
@@ -5259,8 +5387,8 @@ function claudeManagedSettingsPath() {
|
|
|
5259
5387
|
function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
5260
5388
|
try {
|
|
5261
5389
|
let settings = {};
|
|
5262
|
-
if (
|
|
5263
|
-
const raw =
|
|
5390
|
+
if (existsSync6(path)) {
|
|
5391
|
+
const raw = readFileSync11(path, "utf-8").trim();
|
|
5264
5392
|
if (raw) {
|
|
5265
5393
|
let parsed;
|
|
5266
5394
|
try {
|
|
@@ -5276,7 +5404,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
5276
5404
|
}
|
|
5277
5405
|
if (settings.channelsEnabled === true) return "ok";
|
|
5278
5406
|
settings.channelsEnabled = true;
|
|
5279
|
-
|
|
5407
|
+
mkdirSync4(dirname3(path), { recursive: true });
|
|
5280
5408
|
writeFileSync4(path, `${JSON.stringify(settings, null, 2)}
|
|
5281
5409
|
`);
|
|
5282
5410
|
log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
|
|
@@ -5318,11 +5446,11 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
5318
5446
|
log(`Claude Code install failed: ${err.message}`);
|
|
5319
5447
|
return;
|
|
5320
5448
|
}
|
|
5321
|
-
const brewBinDir =
|
|
5449
|
+
const brewBinDir = dirname3(brewPath);
|
|
5322
5450
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
5323
5451
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
5324
5452
|
}
|
|
5325
|
-
if (
|
|
5453
|
+
if (existsSync6("/home/linuxbrew/.linuxbrew/bin/claude")) {
|
|
5326
5454
|
log("Claude Code installed successfully");
|
|
5327
5455
|
} else {
|
|
5328
5456
|
log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
|
|
@@ -5334,7 +5462,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
5334
5462
|
var CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
5335
5463
|
var claudeCodeUpgradeInFlight = false;
|
|
5336
5464
|
function claudeCodeUpgradeMarkerPath() {
|
|
5337
|
-
return
|
|
5465
|
+
return join12(homedir6(), ".augmented", ".last-claude-code-upgrade-check");
|
|
5338
5466
|
}
|
|
5339
5467
|
function stampClaudeCodeUpgradeMarker() {
|
|
5340
5468
|
try {
|
|
@@ -5344,7 +5472,7 @@ function stampClaudeCodeUpgradeMarker() {
|
|
|
5344
5472
|
}
|
|
5345
5473
|
function claudeCodeUpgradeThrottled() {
|
|
5346
5474
|
try {
|
|
5347
|
-
const lastCheck = parseInt(
|
|
5475
|
+
const lastCheck = parseInt(readFileSync11(claudeCodeUpgradeMarkerPath(), "utf-8").trim(), 10);
|
|
5348
5476
|
if (!Number.isFinite(lastCheck)) return false;
|
|
5349
5477
|
return Date.now() - lastCheck < CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS;
|
|
5350
5478
|
} catch {
|
|
@@ -5397,7 +5525,7 @@ ${r.stderr}`;
|
|
|
5397
5525
|
}
|
|
5398
5526
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
5399
5527
|
function selfUpdateAppliedMarkerPath() {
|
|
5400
|
-
return
|
|
5528
|
+
return join12(homedir6(), ".augmented", ".last-self-update-applied");
|
|
5401
5529
|
}
|
|
5402
5530
|
var selfUpdateUpToDateLogged = false;
|
|
5403
5531
|
var restartAfterUpgrade = false;
|
|
@@ -5420,7 +5548,7 @@ async function checkAndUpdateCli() {
|
|
|
5420
5548
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
5421
5549
|
if (!isBrewFormula && !isNpmGlobal) return;
|
|
5422
5550
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
5423
|
-
const markerPath =
|
|
5551
|
+
const markerPath = join12(homedir6(), ".augmented", ".last-update-check");
|
|
5424
5552
|
try {
|
|
5425
5553
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
5426
5554
|
if (Date.now() - lastCheck < UPDATE_CHECK_INTERVAL_MS) return;
|
|
@@ -5686,10 +5814,10 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
5686
5814
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
5687
5815
|
}
|
|
5688
5816
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
5689
|
-
const claudeDir =
|
|
5817
|
+
const claudeDir = join12(homedir6(), ".claude");
|
|
5690
5818
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
5691
|
-
const p =
|
|
5692
|
-
if (
|
|
5819
|
+
const p = join12(claudeDir, filename);
|
|
5820
|
+
if (existsSync6(p)) {
|
|
5693
5821
|
try {
|
|
5694
5822
|
rmSync2(p, { force: true });
|
|
5695
5823
|
log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
|
|
@@ -5703,13 +5831,13 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
5703
5831
|
}
|
|
5704
5832
|
var evalEmptyMcpConfigPath = null;
|
|
5705
5833
|
function ensureEvalEmptyMcpConfig() {
|
|
5706
|
-
if (evalEmptyMcpConfigPath &&
|
|
5707
|
-
const dir =
|
|
5834
|
+
if (evalEmptyMcpConfigPath && existsSync6(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
5835
|
+
const dir = join12(homedir6(), ".augmented");
|
|
5708
5836
|
try {
|
|
5709
|
-
|
|
5837
|
+
mkdirSync4(dir, { recursive: true });
|
|
5710
5838
|
} catch {
|
|
5711
5839
|
}
|
|
5712
|
-
const p =
|
|
5840
|
+
const p = join12(dir, ".eval-empty-mcp.json");
|
|
5713
5841
|
writeFileSync4(p, JSON.stringify({ mcpServers: {} }));
|
|
5714
5842
|
evalEmptyMcpConfigPath = p;
|
|
5715
5843
|
return p;
|
|
@@ -5735,7 +5863,7 @@ async function runEvalClaude(prompt, model) {
|
|
|
5735
5863
|
""
|
|
5736
5864
|
];
|
|
5737
5865
|
const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
|
|
5738
|
-
cwd:
|
|
5866
|
+
cwd: homedir6(),
|
|
5739
5867
|
timeout: 12e4,
|
|
5740
5868
|
stdin: "ignore",
|
|
5741
5869
|
env: childEnv,
|
|
@@ -5784,13 +5912,13 @@ function resolveConversationEvalBackend() {
|
|
|
5784
5912
|
}
|
|
5785
5913
|
function loadGatewayPorts() {
|
|
5786
5914
|
try {
|
|
5787
|
-
return JSON.parse(
|
|
5915
|
+
return JSON.parse(readFileSync11(GATEWAY_PORTS_FILE, "utf-8"));
|
|
5788
5916
|
} catch {
|
|
5789
5917
|
return {};
|
|
5790
5918
|
}
|
|
5791
5919
|
}
|
|
5792
5920
|
function saveGatewayPorts(ports) {
|
|
5793
|
-
|
|
5921
|
+
mkdirSync4(AUGMENTED_DIR, { recursive: true });
|
|
5794
5922
|
writeFileSync4(GATEWAY_PORTS_FILE, JSON.stringify(ports, null, 2));
|
|
5795
5923
|
}
|
|
5796
5924
|
function allocatePort(codeName) {
|
|
@@ -5814,10 +5942,10 @@ function freePort(codeName) {
|
|
|
5814
5942
|
}
|
|
5815
5943
|
}
|
|
5816
5944
|
function getStateFile() {
|
|
5817
|
-
return
|
|
5945
|
+
return join12(config?.configDir ?? join12(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
5818
5946
|
}
|
|
5819
5947
|
function channelHashCacheDir() {
|
|
5820
|
-
return config?.configDir ??
|
|
5948
|
+
return config?.configDir ?? join12(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
5821
5949
|
}
|
|
5822
5950
|
function loadChannelHashCache2() {
|
|
5823
5951
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -5828,7 +5956,7 @@ function saveChannelHashCache2() {
|
|
|
5828
5956
|
var _channelQuarantineStore = null;
|
|
5829
5957
|
function channelQuarantineStore() {
|
|
5830
5958
|
if (!_channelQuarantineStore) {
|
|
5831
|
-
const dir = config?.configDir ??
|
|
5959
|
+
const dir = config?.configDir ?? join12(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
5832
5960
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
5833
5961
|
}
|
|
5834
5962
|
return _channelQuarantineStore;
|
|
@@ -5836,7 +5964,7 @@ function channelQuarantineStore() {
|
|
|
5836
5964
|
var _hostFlagStore = null;
|
|
5837
5965
|
function hostFlagStore() {
|
|
5838
5966
|
if (!_hostFlagStore) {
|
|
5839
|
-
const dir = config?.configDir ??
|
|
5967
|
+
const dir = config?.configDir ?? join12(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
5840
5968
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
5841
5969
|
}
|
|
5842
5970
|
return _hostFlagStore;
|
|
@@ -5869,61 +5997,6 @@ function send(msg) {
|
|
|
5869
5997
|
log(`Error: ${msg.message}`);
|
|
5870
5998
|
}
|
|
5871
5999
|
}
|
|
5872
|
-
var managerLogPath = null;
|
|
5873
|
-
var managerLogWritable = true;
|
|
5874
|
-
function redactForDiskLog(value) {
|
|
5875
|
-
try {
|
|
5876
|
-
return value.replace(/\b(Bearer\s+)[A-Za-z0-9._-]+\b/gi, "$1[REDACTED]").replace(/\bxox[baprs]-[A-Za-z0-9-]+\b/g, "[REDACTED-SLACK]").replace(/\btlk_[A-Za-z0-9._-]+\b/g, "[REDACTED-HOST]").replace(/\bsk-ant-[A-Za-z0-9_-]+\b/g, "[REDACTED-ANTHROPIC]").replace(/\b\d{8,12}:[A-Za-z0-9_-]{30,}\b/g, "[REDACTED-TELEGRAM]").replace(
|
|
5877
|
-
/\b([A-Z0-9_]*(?:TOKEN|SECRET|API[_-]?KEY|PASSWORD)[A-Z0-9_]*)=(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s\r\n]+)/gi,
|
|
5878
|
-
"$1=[REDACTED]"
|
|
5879
|
-
);
|
|
5880
|
-
} catch {
|
|
5881
|
-
return "[REDACTED]";
|
|
5882
|
-
}
|
|
5883
|
-
}
|
|
5884
|
-
function log(msg) {
|
|
5885
|
-
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
5886
|
-
const safeMsg = redactForDiskLog(msg);
|
|
5887
|
-
const line = `[manager-worker ${ts}] ${safeMsg}
|
|
5888
|
-
`;
|
|
5889
|
-
if (!managerLogPath) {
|
|
5890
|
-
try {
|
|
5891
|
-
managerLogPath = join11(homedir5(), ".augmented", "manager.log");
|
|
5892
|
-
mkdirSync3(dirname2(managerLogPath), { recursive: true });
|
|
5893
|
-
if (existsSync5(managerLogPath)) {
|
|
5894
|
-
chmodSync(managerLogPath, 384);
|
|
5895
|
-
}
|
|
5896
|
-
} catch {
|
|
5897
|
-
}
|
|
5898
|
-
}
|
|
5899
|
-
let appendedToFile = false;
|
|
5900
|
-
if (managerLogPath && managerLogWritable) {
|
|
5901
|
-
try {
|
|
5902
|
-
appendFileSync(managerLogPath, line, { encoding: "utf-8", mode: 384 });
|
|
5903
|
-
appendedToFile = true;
|
|
5904
|
-
} catch (err) {
|
|
5905
|
-
managerLogWritable = false;
|
|
5906
|
-
process.stderr.write(
|
|
5907
|
-
`[manager-worker ${ts}] [log] manager.log append failed; falling back to stderr-only: ${err.message}
|
|
5908
|
-
`
|
|
5909
|
-
);
|
|
5910
|
-
}
|
|
5911
|
-
}
|
|
5912
|
-
if (!appendedToFile || process.stderr.isTTY === true) {
|
|
5913
|
-
process.stderr.write(line);
|
|
5914
|
-
}
|
|
5915
|
-
}
|
|
5916
|
-
function sha256(content) {
|
|
5917
|
-
return createHash3("sha256").update(content, "utf8").digest("hex");
|
|
5918
|
-
}
|
|
5919
|
-
function hashFile(filePath) {
|
|
5920
|
-
try {
|
|
5921
|
-
const content = readFileSync10(filePath, "utf-8");
|
|
5922
|
-
return sha256(content);
|
|
5923
|
-
} catch {
|
|
5924
|
-
return null;
|
|
5925
|
-
}
|
|
5926
|
-
}
|
|
5927
6000
|
var SKILLS_INDEX_START = "<!-- AGT:SKILLS_INDEX_START -->";
|
|
5928
6001
|
var SKILLS_INDEX_END = "<!-- AGT:SKILLS_INDEX_END -->";
|
|
5929
6002
|
function sanitizeSkillsIndexText(value) {
|
|
@@ -5943,12 +6016,12 @@ function parseSkillFrontmatter(content) {
|
|
|
5943
6016
|
}
|
|
5944
6017
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
5945
6018
|
const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync5 } = await import("fs");
|
|
5946
|
-
const skillsDir =
|
|
5947
|
-
const claudeMdPath =
|
|
6019
|
+
const skillsDir = join12(configDir, codeName, "project", ".claude", "skills");
|
|
6020
|
+
const claudeMdPath = join12(configDir, codeName, "project", "CLAUDE.md");
|
|
5948
6021
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
5949
6022
|
const entries = [];
|
|
5950
6023
|
for (const dir of readdirSync6(skillsDir).sort()) {
|
|
5951
|
-
const skillFile =
|
|
6024
|
+
const skillFile = join12(skillsDir, dir, "SKILL.md");
|
|
5952
6025
|
if (!ex(skillFile)) continue;
|
|
5953
6026
|
try {
|
|
5954
6027
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -5996,10 +6069,10 @@ ${SKILLS_INDEX_END}`;
|
|
|
5996
6069
|
}
|
|
5997
6070
|
async function migrateToProfiles() {
|
|
5998
6071
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5999
|
-
const sharedConfigPath =
|
|
6072
|
+
const sharedConfigPath = join12(homeDir, ".openclaw", "openclaw.json");
|
|
6000
6073
|
let sharedConfig;
|
|
6001
6074
|
try {
|
|
6002
|
-
sharedConfig = JSON.parse(
|
|
6075
|
+
sharedConfig = JSON.parse(readFileSync11(sharedConfigPath, "utf-8"));
|
|
6003
6076
|
} catch {
|
|
6004
6077
|
return;
|
|
6005
6078
|
}
|
|
@@ -6012,19 +6085,19 @@ async function migrateToProfiles() {
|
|
|
6012
6085
|
const codeName = agentEntry["id"];
|
|
6013
6086
|
if (!codeName) continue;
|
|
6014
6087
|
if (codeName === "main") continue;
|
|
6015
|
-
const profileDir =
|
|
6016
|
-
if (
|
|
6088
|
+
const profileDir = join12(homeDir, `.openclaw-${codeName}`);
|
|
6089
|
+
if (existsSync6(join12(profileDir, "openclaw.json"))) continue;
|
|
6017
6090
|
log(`Migrating agent '${codeName}' to per-agent profile`);
|
|
6018
6091
|
if (adapter.seedProfileConfig) {
|
|
6019
6092
|
adapter.seedProfileConfig(codeName);
|
|
6020
6093
|
}
|
|
6021
|
-
const sharedAuthDir =
|
|
6022
|
-
const profileAuthDir =
|
|
6023
|
-
const authFile =
|
|
6024
|
-
if (
|
|
6025
|
-
|
|
6026
|
-
const authContent =
|
|
6027
|
-
writeFileSync4(
|
|
6094
|
+
const sharedAuthDir = join12(homeDir, ".openclaw", "agents", codeName, "agent");
|
|
6095
|
+
const profileAuthDir = join12(profileDir, "agents", codeName, "agent");
|
|
6096
|
+
const authFile = join12(sharedAuthDir, "auth-profiles.json");
|
|
6097
|
+
if (existsSync6(authFile)) {
|
|
6098
|
+
mkdirSync4(profileAuthDir, { recursive: true });
|
|
6099
|
+
const authContent = readFileSync11(authFile, "utf-8");
|
|
6100
|
+
writeFileSync4(join12(profileAuthDir, "auth-profiles.json"), authContent);
|
|
6028
6101
|
}
|
|
6029
6102
|
allocatePort(codeName);
|
|
6030
6103
|
migrated++;
|
|
@@ -6062,7 +6135,7 @@ function readGatewayToken(codeName) {
|
|
|
6062
6135
|
}
|
|
6063
6136
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
6064
6137
|
try {
|
|
6065
|
-
const cfg = JSON.parse(
|
|
6138
|
+
const cfg = JSON.parse(readFileSync11(join12(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
|
|
6066
6139
|
return cfg?.gateway?.auth?.token;
|
|
6067
6140
|
} catch {
|
|
6068
6141
|
return void 0;
|
|
@@ -6071,10 +6144,10 @@ function readGatewayToken(codeName) {
|
|
|
6071
6144
|
var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
|
|
6072
6145
|
function isGatewayHung(codeName) {
|
|
6073
6146
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
6074
|
-
const jobsPath =
|
|
6075
|
-
if (!
|
|
6147
|
+
const jobsPath = join12(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
6148
|
+
if (!existsSync6(jobsPath)) return false;
|
|
6076
6149
|
try {
|
|
6077
|
-
const data = JSON.parse(
|
|
6150
|
+
const data = JSON.parse(readFileSync11(jobsPath, "utf-8"));
|
|
6078
6151
|
const jobs = data.jobs ?? data;
|
|
6079
6152
|
if (!Array.isArray(jobs)) return false;
|
|
6080
6153
|
const now = Date.now();
|
|
@@ -6107,15 +6180,15 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
6107
6180
|
}
|
|
6108
6181
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
6109
6182
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
6110
|
-
const cronJobsPath =
|
|
6183
|
+
const cronJobsPath = join12(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
6111
6184
|
clearStaleCronRunState(cronJobsPath);
|
|
6112
6185
|
} else {
|
|
6113
6186
|
if (status.port) {
|
|
6114
6187
|
try {
|
|
6115
6188
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
6116
|
-
const configPath =
|
|
6117
|
-
if (
|
|
6118
|
-
const cfg = JSON.parse(
|
|
6189
|
+
const configPath = join12(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
6190
|
+
if (existsSync6(configPath)) {
|
|
6191
|
+
const cfg = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
6119
6192
|
if (cfg.gateway?.port !== status.port) {
|
|
6120
6193
|
if (!cfg.gateway) cfg.gateway = {};
|
|
6121
6194
|
cfg.gateway.port = status.port;
|
|
@@ -6139,9 +6212,9 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
6139
6212
|
gatewaysStartedThisCycle.add(codeName);
|
|
6140
6213
|
try {
|
|
6141
6214
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
6142
|
-
const configPath =
|
|
6143
|
-
if (
|
|
6144
|
-
const cfg = JSON.parse(
|
|
6215
|
+
const configPath = join12(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
6216
|
+
if (existsSync6(configPath)) {
|
|
6217
|
+
const cfg = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
6145
6218
|
if (!cfg.gateway) cfg.gateway = {};
|
|
6146
6219
|
cfg.gateway.port = port;
|
|
6147
6220
|
writeFileSync4(configPath, JSON.stringify(cfg, null, 2));
|
|
@@ -6325,7 +6398,7 @@ async function pollCycle() {
|
|
|
6325
6398
|
claudeAuth = await detectClaudeAuth();
|
|
6326
6399
|
} catch (err) {
|
|
6327
6400
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6328
|
-
const errId =
|
|
6401
|
+
const errId = createHash4("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6329
6402
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
6330
6403
|
}
|
|
6331
6404
|
const hostHasClaudeCode = state6.agents.some(
|
|
@@ -6678,7 +6751,7 @@ async function pollCycle() {
|
|
|
6678
6751
|
}
|
|
6679
6752
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
6680
6753
|
freePort(prev.codeName);
|
|
6681
|
-
const agentDir =
|
|
6754
|
+
const agentDir = join12(adapter.getAgentDir(prev.codeName), "provision");
|
|
6682
6755
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
6683
6756
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
6684
6757
|
}
|
|
@@ -6764,10 +6837,10 @@ async function pollCycle() {
|
|
|
6764
6837
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
6765
6838
|
// the watchdog, never fails the poll cycle.
|
|
6766
6839
|
signalGiveUp: (codeName) => {
|
|
6767
|
-
const dir =
|
|
6768
|
-
if (!
|
|
6840
|
+
const dir = join12(homedir6(), ".augmented", codeName);
|
|
6841
|
+
if (!existsSync6(dir)) return;
|
|
6769
6842
|
atomicWriteFileSync(
|
|
6770
|
-
|
|
6843
|
+
join12(dir, "watchdog-give-up.json"),
|
|
6771
6844
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
6772
6845
|
);
|
|
6773
6846
|
}
|
|
@@ -6894,7 +6967,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6894
6967
|
}
|
|
6895
6968
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6896
6969
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
6897
|
-
let agentDir =
|
|
6970
|
+
let agentDir = join12(adapter.getAgentDir(agent.code_name), "provision");
|
|
6898
6971
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
6899
6972
|
if (previousKnownStatus !== agent.status) {
|
|
6900
6973
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -6946,7 +7019,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6946
7019
|
const residuals = {
|
|
6947
7020
|
gatewayRunning: gatewayLiveness.running,
|
|
6948
7021
|
portAllocated: Object.prototype.hasOwnProperty.call(ports, agent.code_name),
|
|
6949
|
-
provisionDirExists:
|
|
7022
|
+
provisionDirExists: existsSync6(agentDir)
|
|
6950
7023
|
};
|
|
6951
7024
|
if (!hasRevokedResiduals(residuals)) {
|
|
6952
7025
|
agentStates.push({
|
|
@@ -7098,7 +7171,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7098
7171
|
const frameworkId = refreshData.agent.framework ?? "openclaw";
|
|
7099
7172
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
7100
7173
|
const frameworkAdapter = getFramework(frameworkId);
|
|
7101
|
-
agentDir =
|
|
7174
|
+
agentDir = join12(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
7102
7175
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
7103
7176
|
if (frameworkAdapter.migrateSecretStorage && !migratedSecretStorage.has(agent.code_name)) {
|
|
7104
7177
|
try {
|
|
@@ -7139,9 +7212,9 @@ async function processAgent(agent, agentStates) {
|
|
|
7139
7212
|
try {
|
|
7140
7213
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter);
|
|
7141
7214
|
const changedFiles = [];
|
|
7142
|
-
|
|
7215
|
+
mkdirSync4(agentDir, { recursive: true });
|
|
7143
7216
|
for (const artifact of artifacts) {
|
|
7144
|
-
const filePath =
|
|
7217
|
+
const filePath = join12(agentDir, artifact.relativePath);
|
|
7145
7218
|
let existingHash;
|
|
7146
7219
|
let newHash;
|
|
7147
7220
|
let writeContent = artifact.content;
|
|
@@ -7160,8 +7233,8 @@ async function processAgent(agent, agentStates) {
|
|
|
7160
7233
|
};
|
|
7161
7234
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
7162
7235
|
try {
|
|
7163
|
-
const projectClaudeMd =
|
|
7164
|
-
const existing =
|
|
7236
|
+
const projectClaudeMd = join12(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
7237
|
+
const existing = readFileSync11(projectClaudeMd, "utf-8");
|
|
7165
7238
|
existingHash = sha256(stripDynamicSections(existing));
|
|
7166
7239
|
} catch {
|
|
7167
7240
|
existingHash = null;
|
|
@@ -7179,7 +7252,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7179
7252
|
const generatorKeys = Object.keys(generatorServers);
|
|
7180
7253
|
let existingRaw = "";
|
|
7181
7254
|
try {
|
|
7182
|
-
existingRaw =
|
|
7255
|
+
existingRaw = readFileSync11(filePath, "utf-8");
|
|
7183
7256
|
} catch {
|
|
7184
7257
|
}
|
|
7185
7258
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -7201,13 +7274,13 @@ async function processAgent(agent, agentStates) {
|
|
|
7201
7274
|
}
|
|
7202
7275
|
}
|
|
7203
7276
|
if (changedFiles.length > 0) {
|
|
7204
|
-
const isFirst = !
|
|
7277
|
+
const isFirst = !existsSync6(join12(agentDir, "CHARTER.md"));
|
|
7205
7278
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
7206
7279
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
7207
7280
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
7208
7281
|
for (const file of changedFiles) {
|
|
7209
|
-
const filePath =
|
|
7210
|
-
|
|
7282
|
+
const filePath = join12(agentDir, file.relativePath);
|
|
7283
|
+
mkdirSync4(dirname3(filePath), { recursive: true });
|
|
7211
7284
|
if (file.relativePath === ".mcp.json") {
|
|
7212
7285
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
7213
7286
|
} else {
|
|
@@ -7215,12 +7288,12 @@ async function processAgent(agent, agentStates) {
|
|
|
7215
7288
|
}
|
|
7216
7289
|
}
|
|
7217
7290
|
try {
|
|
7218
|
-
const provSkillsDir =
|
|
7219
|
-
if (
|
|
7291
|
+
const provSkillsDir = join12(agentDir, ".claude", "skills");
|
|
7292
|
+
if (existsSync6(provSkillsDir)) {
|
|
7220
7293
|
for (const folder of readdirSync5(provSkillsDir)) {
|
|
7221
7294
|
if (folder.startsWith("knowledge-")) {
|
|
7222
7295
|
try {
|
|
7223
|
-
rmSync2(
|
|
7296
|
+
rmSync2(join12(provSkillsDir, folder), { recursive: true });
|
|
7224
7297
|
} catch {
|
|
7225
7298
|
}
|
|
7226
7299
|
}
|
|
@@ -7233,7 +7306,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7233
7306
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
7234
7307
|
const hashes = /* @__PURE__ */ new Map();
|
|
7235
7308
|
for (const file of trackedFiles2) {
|
|
7236
|
-
const h = hashFile(
|
|
7309
|
+
const h = hashFile(join12(agentDir, file));
|
|
7237
7310
|
if (h) hashes.set(file, h);
|
|
7238
7311
|
}
|
|
7239
7312
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -7251,14 +7324,14 @@ async function processAgent(agent, agentStates) {
|
|
|
7251
7324
|
}
|
|
7252
7325
|
if (Array.isArray(refreshData.workflows)) {
|
|
7253
7326
|
try {
|
|
7254
|
-
const provWorkflowsDir =
|
|
7255
|
-
if (
|
|
7327
|
+
const provWorkflowsDir = join12(agentDir, ".claude", "workflows");
|
|
7328
|
+
if (existsSync6(provWorkflowsDir)) {
|
|
7256
7329
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
7257
7330
|
for (const file of readdirSync5(provWorkflowsDir)) {
|
|
7258
7331
|
if (!file.endsWith(".js")) continue;
|
|
7259
7332
|
if (expected.has(file)) continue;
|
|
7260
7333
|
try {
|
|
7261
|
-
rmSync2(
|
|
7334
|
+
rmSync2(join12(provWorkflowsDir, file));
|
|
7262
7335
|
} catch {
|
|
7263
7336
|
}
|
|
7264
7337
|
}
|
|
@@ -7315,10 +7388,10 @@ async function processAgent(agent, agentStates) {
|
|
|
7315
7388
|
}
|
|
7316
7389
|
let lastDriftCheckAt = now;
|
|
7317
7390
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
7318
|
-
if (written &&
|
|
7391
|
+
if (written && existsSync6(agentDir)) {
|
|
7319
7392
|
const driftedFiles = [];
|
|
7320
7393
|
for (const [file, expectedHash] of written) {
|
|
7321
|
-
const localHash = hashFile(
|
|
7394
|
+
const localHash = hashFile(join12(agentDir, file));
|
|
7322
7395
|
if (localHash && localHash !== expectedHash) {
|
|
7323
7396
|
driftedFiles.push(file);
|
|
7324
7397
|
}
|
|
@@ -7329,7 +7402,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7329
7402
|
try {
|
|
7330
7403
|
const localHashes = {};
|
|
7331
7404
|
for (const file of driftedFiles) {
|
|
7332
|
-
localHashes[file] = hashFile(
|
|
7405
|
+
localHashes[file] = hashFile(join12(agentDir, file));
|
|
7333
7406
|
}
|
|
7334
7407
|
await api.post("/host/drift", {
|
|
7335
7408
|
agent_id: agent.agent_id,
|
|
@@ -7403,7 +7476,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7403
7476
|
const sessionModeForHash = refreshData.agent.session_mode;
|
|
7404
7477
|
const senderPolicyForHash = refreshData.sender_policy ?? null;
|
|
7405
7478
|
const CHANNEL_WRITE_VERSION = 9;
|
|
7406
|
-
const configHash =
|
|
7479
|
+
const configHash = createHash4("sha256").update(
|
|
7407
7480
|
canonicalJson({
|
|
7408
7481
|
writeVersion: CHANNEL_WRITE_VERSION,
|
|
7409
7482
|
config: entry.config,
|
|
@@ -7517,7 +7590,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7517
7590
|
if (channelConfigConverged) {
|
|
7518
7591
|
const hasSenderPolicyChannel = currentChannelIds.has("slack") || currentChannelIds.has("msteams");
|
|
7519
7592
|
const senderPolicyForRestartHash = refreshData.sender_policy ?? null;
|
|
7520
|
-
const senderPolicyHash =
|
|
7593
|
+
const senderPolicyHash = createHash4("sha256").update(canonicalJson({ senderPolicy: senderPolicyForRestartHash })).digest("hex");
|
|
7521
7594
|
const prevSenderPolicyHash = agentState.knownSenderPolicyHashes.get(agent.agent_id);
|
|
7522
7595
|
const senderPolicyDecision = hasSenderPolicyChannel ? decideSenderPolicyRestart({
|
|
7523
7596
|
previousHash: prevSenderPolicyHash,
|
|
@@ -7559,7 +7632,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7559
7632
|
const behaviourSubset = extractMsTeamsBehaviourSubset(
|
|
7560
7633
|
msteamsEntry?.config
|
|
7561
7634
|
);
|
|
7562
|
-
const behaviourHash =
|
|
7635
|
+
const behaviourHash = createHash4("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
|
|
7563
7636
|
const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
|
|
7564
7637
|
const behaviourDecision = decideSenderPolicyRestart({
|
|
7565
7638
|
previousHash: prevBehaviourHash,
|
|
@@ -7606,7 +7679,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7606
7679
|
const slackBehaviourSubset = extractSlackBehaviourSubset(
|
|
7607
7680
|
slackEntry?.config
|
|
7608
7681
|
);
|
|
7609
|
-
const slackBehaviourHash =
|
|
7682
|
+
const slackBehaviourHash = createHash4("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
|
|
7610
7683
|
const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
|
|
7611
7684
|
const slackBehaviourDecision = decideSenderPolicyRestart({
|
|
7612
7685
|
previousHash: prevSlackBehaviourHash,
|
|
@@ -7653,24 +7726,24 @@ async function processAgent(agent, agentStates) {
|
|
|
7653
7726
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? "openclaw") === "claude-code") {
|
|
7654
7727
|
try {
|
|
7655
7728
|
const agentProvisionDir = agentDir;
|
|
7656
|
-
const projectDir =
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
const provisionMcpPath =
|
|
7660
|
-
const projectMcpPath =
|
|
7729
|
+
const projectDir = join12(homedir6(), ".augmented", agent.code_name, "project");
|
|
7730
|
+
mkdirSync4(agentProvisionDir, { recursive: true });
|
|
7731
|
+
mkdirSync4(projectDir, { recursive: true });
|
|
7732
|
+
const provisionMcpPath = join12(agentProvisionDir, ".mcp.json");
|
|
7733
|
+
const projectMcpPath = join12(projectDir, ".mcp.json");
|
|
7661
7734
|
let mcpConfig = { mcpServers: {} };
|
|
7662
7735
|
try {
|
|
7663
|
-
mcpConfig = JSON.parse(
|
|
7736
|
+
mcpConfig = JSON.parse(readFileSync11(provisionMcpPath, "utf-8"));
|
|
7664
7737
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
7665
7738
|
} catch {
|
|
7666
7739
|
}
|
|
7667
|
-
const localDirectChatChannel =
|
|
7740
|
+
const localDirectChatChannel = join12(homedir6(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
7668
7741
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
7669
7742
|
const directChatTz = (() => {
|
|
7670
7743
|
const tz = directChatTeamSettings?.["timezone"];
|
|
7671
7744
|
return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
|
|
7672
7745
|
})();
|
|
7673
|
-
if (
|
|
7746
|
+
if (existsSync6(localDirectChatChannel)) {
|
|
7674
7747
|
const directChatEnv = {
|
|
7675
7748
|
AGT_HOST: requireHost(),
|
|
7676
7749
|
// ENG-5901 Track D: templated — the manager exports the real
|
|
@@ -7694,8 +7767,8 @@ async function processAgent(agent, agentStates) {
|
|
|
7694
7767
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
7695
7768
|
}
|
|
7696
7769
|
}
|
|
7697
|
-
const staleChannelsPath =
|
|
7698
|
-
if (
|
|
7770
|
+
const staleChannelsPath = join12(projectDir, ".mcp-channels.json");
|
|
7771
|
+
if (existsSync6(staleChannelsPath)) {
|
|
7699
7772
|
try {
|
|
7700
7773
|
rmSync2(staleChannelsPath, { force: true });
|
|
7701
7774
|
} catch {
|
|
@@ -7759,7 +7832,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7759
7832
|
}
|
|
7760
7833
|
if (process.env.AGT_CONNECTIVITY_PROBE_ENABLED === "true") {
|
|
7761
7834
|
try {
|
|
7762
|
-
const probeProjectDir =
|
|
7835
|
+
const probeProjectDir = join12(homedir6(), ".augmented", agent.code_name, "project");
|
|
7763
7836
|
await runAgentConnectivityProbes(agent, integrations, probeProjectDir);
|
|
7764
7837
|
} catch (err) {
|
|
7765
7838
|
log(`Connectivity probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -7777,11 +7850,11 @@ async function processAgent(agent, agentStates) {
|
|
|
7777
7850
|
recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
|
|
7778
7851
|
}
|
|
7779
7852
|
if (intHash !== prevIntHash) {
|
|
7780
|
-
const projectDir =
|
|
7781
|
-
const envIntPath =
|
|
7853
|
+
const projectDir = join12(homedir6(), ".augmented", agent.code_name, "project");
|
|
7854
|
+
const envIntPath = join12(projectDir, ".env.integrations");
|
|
7782
7855
|
let preWriteEnv;
|
|
7783
7856
|
try {
|
|
7784
|
-
preWriteEnv =
|
|
7857
|
+
preWriteEnv = readFileSync11(envIntPath, "utf-8");
|
|
7785
7858
|
} catch {
|
|
7786
7859
|
preWriteEnv = void 0;
|
|
7787
7860
|
}
|
|
@@ -7793,9 +7866,9 @@ async function processAgent(agent, agentStates) {
|
|
|
7793
7866
|
let rotationHandled = true;
|
|
7794
7867
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
7795
7868
|
try {
|
|
7796
|
-
const projectMcpPath =
|
|
7797
|
-
const postWriteEnv =
|
|
7798
|
-
const mcpContent =
|
|
7869
|
+
const projectMcpPath = join12(projectDir, ".mcp.json");
|
|
7870
|
+
const postWriteEnv = readFileSync11(envIntPath, "utf-8");
|
|
7871
|
+
const mcpContent = readFileSync11(projectMcpPath, "utf-8");
|
|
7799
7872
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
7800
7873
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
7801
7874
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -7850,10 +7923,10 @@ async function processAgent(agent, agentStates) {
|
|
|
7850
7923
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
7851
7924
|
}
|
|
7852
7925
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
7853
|
-
const headersHash =
|
|
7926
|
+
const headersHash = createHash4("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
7854
7927
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
7855
7928
|
}).join("\n");
|
|
7856
|
-
const mcpHash =
|
|
7929
|
+
const mcpHash = createHash4("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
7857
7930
|
const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
|
|
7858
7931
|
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
7859
7932
|
const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
|
|
@@ -7868,15 +7941,15 @@ async function processAgent(agent, agentStates) {
|
|
|
7868
7941
|
if (mcpHash !== prevMcpHash) {
|
|
7869
7942
|
for (const e of desiredEntries) {
|
|
7870
7943
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
7871
|
-
const urlHash =
|
|
7944
|
+
const urlHash = createHash4("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
7872
7945
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
7873
7946
|
}
|
|
7874
7947
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
|
|
7875
7948
|
const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
|
|
7876
7949
|
if (mcpPath) {
|
|
7877
7950
|
try {
|
|
7878
|
-
const { readFileSync:
|
|
7879
|
-
const mcpConfig = JSON.parse(
|
|
7951
|
+
const { readFileSync: readFileSync12 } = await import("fs");
|
|
7952
|
+
const mcpConfig = JSON.parse(readFileSync12(mcpPath, "utf-8"));
|
|
7880
7953
|
if (mcpConfig.mcpServers) {
|
|
7881
7954
|
const managedPrefixes = [
|
|
7882
7955
|
"composio_",
|
|
@@ -7977,8 +8050,8 @@ async function processAgent(agent, agentStates) {
|
|
|
7977
8050
|
if (agent.status === "active") {
|
|
7978
8051
|
if (frameworkAdapter.installPlugin) {
|
|
7979
8052
|
try {
|
|
7980
|
-
const pluginPath =
|
|
7981
|
-
if (
|
|
8053
|
+
const pluginPath = join12(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
|
|
8054
|
+
if (existsSync6(pluginPath)) {
|
|
7982
8055
|
frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
|
|
7983
8056
|
agtHost: requireHost(),
|
|
7984
8057
|
agtApiKey: getApiKey() ?? void 0,
|
|
@@ -8002,7 +8075,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8002
8075
|
if (frameworkAdapter.installSkillFiles) {
|
|
8003
8076
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
8004
8077
|
const installedIntegrationSkills = [];
|
|
8005
|
-
const { createHash:
|
|
8078
|
+
const { createHash: createHash5 } = await import("crypto");
|
|
8006
8079
|
const refreshAny = refreshData;
|
|
8007
8080
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
8008
8081
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -8031,7 +8104,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8031
8104
|
)
|
|
8032
8105
|
}));
|
|
8033
8106
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
8034
|
-
const contentHash =
|
|
8107
|
+
const contentHash = createHash5("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
8035
8108
|
const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
|
|
8036
8109
|
if (agentState.knownSkillHashes.get(hashKey) === contentHash) continue;
|
|
8037
8110
|
frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
|
|
@@ -8044,20 +8117,20 @@ async function processAgent(agent, agentStates) {
|
|
|
8044
8117
|
}
|
|
8045
8118
|
try {
|
|
8046
8119
|
const { readdirSync: readdirSync6, rmSync: rmSync3 } = await import("fs");
|
|
8047
|
-
const { homedir:
|
|
8120
|
+
const { homedir: homedir7 } = await import("os");
|
|
8048
8121
|
const frameworkId2 = frameworkAdapter.id;
|
|
8049
8122
|
const candidateSkillDirs = [
|
|
8050
8123
|
// Claude Code — framework runtime tree
|
|
8051
|
-
|
|
8124
|
+
join12(homedir7(), ".augmented", agent.code_name, "skills"),
|
|
8052
8125
|
// Claude Code — project tree
|
|
8053
|
-
|
|
8126
|
+
join12(homedir7(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
8054
8127
|
// OpenClaw — framework runtime tree
|
|
8055
|
-
|
|
8128
|
+
join12(homedir7(), `.openclaw-${agent.code_name}`, "skills"),
|
|
8056
8129
|
// Defensive: legacy provision-side path, not currently an
|
|
8057
8130
|
// install target but cheap to sweep.
|
|
8058
|
-
|
|
8131
|
+
join12(agentDir, ".claude", "skills")
|
|
8059
8132
|
];
|
|
8060
|
-
const existingDirs = candidateSkillDirs.filter((d) =>
|
|
8133
|
+
const existingDirs = candidateSkillDirs.filter((d) => existsSync6(d));
|
|
8061
8134
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
8062
8135
|
for (const dir of existingDirs) {
|
|
8063
8136
|
try {
|
|
@@ -8071,8 +8144,8 @@ async function processAgent(agent, agentStates) {
|
|
|
8071
8144
|
}
|
|
8072
8145
|
const removeSkillFolder = (entry, reason) => {
|
|
8073
8146
|
for (const dir of existingDirs) {
|
|
8074
|
-
const p =
|
|
8075
|
-
if (
|
|
8147
|
+
const p = join12(dir, entry);
|
|
8148
|
+
if (existsSync6(p)) {
|
|
8076
8149
|
rmSync3(p, { recursive: true, force: true });
|
|
8077
8150
|
}
|
|
8078
8151
|
}
|
|
@@ -8090,7 +8163,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8090
8163
|
const plan = planGlobalSkillSync(
|
|
8091
8164
|
refreshAny.global_skills ?? [],
|
|
8092
8165
|
agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
8093
|
-
(content) =>
|
|
8166
|
+
(content) => createHash5("sha256").update(content).digest("hex").slice(0, 12),
|
|
8094
8167
|
(skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`)
|
|
8095
8168
|
);
|
|
8096
8169
|
for (const { skillId, content, hash } of plan.installs) {
|
|
@@ -8100,17 +8173,17 @@ async function processAgent(agent, agentStates) {
|
|
|
8100
8173
|
}
|
|
8101
8174
|
if (plan.removes.length) {
|
|
8102
8175
|
const { rmSync: rmSync3 } = await import("fs");
|
|
8103
|
-
const { homedir:
|
|
8176
|
+
const { homedir: homedir7 } = await import("os");
|
|
8104
8177
|
const globalSkillDirs = [
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8178
|
+
join12(homedir7(), ".augmented", agent.code_name, "skills"),
|
|
8179
|
+
join12(homedir7(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
8180
|
+
join12(homedir7(), `.openclaw-${agent.code_name}`, "skills"),
|
|
8181
|
+
join12(agentDir, ".claude", "skills")
|
|
8109
8182
|
];
|
|
8110
8183
|
for (const id of plan.removes) {
|
|
8111
8184
|
for (const dir of globalSkillDirs) {
|
|
8112
|
-
const p =
|
|
8113
|
-
if (
|
|
8185
|
+
const p = join12(dir, id);
|
|
8186
|
+
if (existsSync6(p)) rmSync3(p, { recursive: true, force: true });
|
|
8114
8187
|
}
|
|
8115
8188
|
agentState.knownSkillHashes.delete(`global-skill:${agent.agent_id}:${id}`);
|
|
8116
8189
|
log(`Removed unpublished global skill '${id}' for '${agent.code_name}'`);
|
|
@@ -8134,7 +8207,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8134
8207
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
8135
8208
|
if (!slug) continue;
|
|
8136
8209
|
try {
|
|
8137
|
-
const scriptHash =
|
|
8210
|
+
const scriptHash = createHash5("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
8138
8211
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
8139
8212
|
if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
8140
8213
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -8149,9 +8222,9 @@ async function processAgent(agent, agentStates) {
|
|
|
8149
8222
|
} else if (result.timedOut) {
|
|
8150
8223
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
8151
8224
|
} else {
|
|
8152
|
-
const stderrHash =
|
|
8225
|
+
const stderrHash = createHash5("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
8153
8226
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
8154
|
-
const missingCmdHash = missingCmd ?
|
|
8227
|
+
const missingCmdHash = missingCmd ? createHash5("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
8155
8228
|
log(
|
|
8156
8229
|
`Integration hook on_install '${slug}' exited ${result.exitCode} for '${agent.code_name}' ` + (missingCmdHash ? `[missing_command_hash=${missingCmdHash}] ` : "") + `[stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
|
|
8157
8230
|
);
|
|
@@ -8285,8 +8358,8 @@ async function processAgent(agent, agentStates) {
|
|
|
8285
8358
|
const sess = getSessionState(agent.code_name);
|
|
8286
8359
|
let mcpJsonParsed = null;
|
|
8287
8360
|
try {
|
|
8288
|
-
const mcpPath =
|
|
8289
|
-
mcpJsonParsed = JSON.parse(
|
|
8361
|
+
const mcpPath = join12(getProjectDir(agent.code_name), ".mcp.json");
|
|
8362
|
+
mcpJsonParsed = JSON.parse(readFileSync11(mcpPath, "utf-8"));
|
|
8290
8363
|
} catch {
|
|
8291
8364
|
}
|
|
8292
8365
|
reapMissingMcpSessions({
|
|
@@ -8420,10 +8493,10 @@ async function processAgent(agent, agentStates) {
|
|
|
8420
8493
|
} else if (agentFw === "claude-code" && tasks.length > 0) {
|
|
8421
8494
|
await syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData);
|
|
8422
8495
|
} else if (frameworkAdapter.syncScheduledTasks && gatewayRunning && gatewayPort) {
|
|
8423
|
-
const stableTasksHash =
|
|
8424
|
-
const boardHash = boardItems.length > 0 ?
|
|
8496
|
+
const stableTasksHash = createHash4("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
8497
|
+
const boardHash = boardItems.length > 0 ? createHash4("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
|
|
8425
8498
|
const resolvedModels = resolveModelChain(refreshData);
|
|
8426
|
-
const modelsHash =
|
|
8499
|
+
const modelsHash = createHash4("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
8427
8500
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
8428
8501
|
const prevTasksHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
8429
8502
|
if (combinedHash !== prevTasksHash) {
|
|
@@ -8495,10 +8568,10 @@ async function processAgent(agent, agentStates) {
|
|
|
8495
8568
|
lastWorkTriggerAt.set(agent.code_name, triggerTs);
|
|
8496
8569
|
if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
|
|
8497
8570
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8498
|
-
const jobsPath =
|
|
8499
|
-
if (
|
|
8571
|
+
const jobsPath = join12(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
|
|
8572
|
+
if (existsSync6(jobsPath)) {
|
|
8500
8573
|
try {
|
|
8501
|
-
const jobsData = JSON.parse(
|
|
8574
|
+
const jobsData = JSON.parse(readFileSync11(jobsPath, "utf-8"));
|
|
8502
8575
|
const kanbanJob = (jobsData.jobs ?? []).find(
|
|
8503
8576
|
(j) => typeof j.name === "string" && j.name.includes("kanban-work")
|
|
8504
8577
|
);
|
|
@@ -8632,10 +8705,10 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
|
|
|
8632
8705
|
}
|
|
8633
8706
|
}
|
|
8634
8707
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
8635
|
-
if (trackedFiles.length > 0 &&
|
|
8708
|
+
if (trackedFiles.length > 0 && existsSync6(agentDir)) {
|
|
8636
8709
|
const hashes = /* @__PURE__ */ new Map();
|
|
8637
8710
|
for (const file of trackedFiles) {
|
|
8638
|
-
const h = hashFile(
|
|
8711
|
+
const h = hashFile(join12(agentDir, file));
|
|
8639
8712
|
if (h) hashes.set(file, h);
|
|
8640
8713
|
}
|
|
8641
8714
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -8669,19 +8742,19 @@ function cleanupStaleSessions(codeName) {
|
|
|
8669
8742
|
lastCleanupAt.set(codeName, Date.now());
|
|
8670
8743
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8671
8744
|
for (const agentDir of ["main", codeName]) {
|
|
8672
|
-
const sessionsDir =
|
|
8745
|
+
const sessionsDir = join12(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
|
|
8673
8746
|
cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
|
|
8674
8747
|
}
|
|
8675
|
-
const cronRunsDir =
|
|
8748
|
+
const cronRunsDir = join12(homeDir, `.openclaw-${codeName}`, "cron", "runs");
|
|
8676
8749
|
cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
|
|
8677
|
-
const cronJobsPath =
|
|
8750
|
+
const cronJobsPath = join12(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
8678
8751
|
clearStaleCronRunState(cronJobsPath);
|
|
8679
8752
|
}
|
|
8680
8753
|
function cleanupCronSessions(sessionsDir, keepCount) {
|
|
8681
|
-
const indexPath =
|
|
8682
|
-
if (!
|
|
8754
|
+
const indexPath = join12(sessionsDir, "sessions.json");
|
|
8755
|
+
if (!existsSync6(indexPath)) return;
|
|
8683
8756
|
try {
|
|
8684
|
-
const raw =
|
|
8757
|
+
const raw = readFileSync11(indexPath, "utf-8");
|
|
8685
8758
|
const index = JSON.parse(raw);
|
|
8686
8759
|
const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
|
|
8687
8760
|
key: k,
|
|
@@ -8694,9 +8767,9 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
8694
8767
|
for (const entry of toDelete) {
|
|
8695
8768
|
delete index[entry.key];
|
|
8696
8769
|
if (entry.sessionId) {
|
|
8697
|
-
const sessionFile =
|
|
8770
|
+
const sessionFile = join12(sessionsDir, `${entry.sessionId}.jsonl`);
|
|
8698
8771
|
try {
|
|
8699
|
-
if (
|
|
8772
|
+
if (existsSync6(sessionFile)) {
|
|
8700
8773
|
unlinkSync(sessionFile);
|
|
8701
8774
|
deletedFiles++;
|
|
8702
8775
|
}
|
|
@@ -8716,8 +8789,8 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
8716
8789
|
delete index[parentKey];
|
|
8717
8790
|
if (parentSessionId) {
|
|
8718
8791
|
try {
|
|
8719
|
-
const f =
|
|
8720
|
-
if (
|
|
8792
|
+
const f = join12(sessionsDir, `${parentSessionId}.jsonl`);
|
|
8793
|
+
if (existsSync6(f)) {
|
|
8721
8794
|
unlinkSync(f);
|
|
8722
8795
|
deletedFiles++;
|
|
8723
8796
|
}
|
|
@@ -8735,9 +8808,9 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
8735
8808
|
}
|
|
8736
8809
|
var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
|
|
8737
8810
|
function clearStaleCronRunState(jobsPath) {
|
|
8738
|
-
if (!
|
|
8811
|
+
if (!existsSync6(jobsPath)) return;
|
|
8739
8812
|
try {
|
|
8740
|
-
const raw =
|
|
8813
|
+
const raw = readFileSync11(jobsPath, "utf-8");
|
|
8741
8814
|
const data = JSON.parse(raw);
|
|
8742
8815
|
const jobs = data.jobs ?? data;
|
|
8743
8816
|
if (!Array.isArray(jobs)) return;
|
|
@@ -8768,13 +8841,13 @@ function clearStaleCronRunState(jobsPath) {
|
|
|
8768
8841
|
}
|
|
8769
8842
|
}
|
|
8770
8843
|
function cleanupOldFiles(dir, maxAgeDays, ext) {
|
|
8771
|
-
if (!
|
|
8844
|
+
if (!existsSync6(dir)) return;
|
|
8772
8845
|
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
8773
8846
|
let removed = 0;
|
|
8774
8847
|
try {
|
|
8775
8848
|
for (const f of readdirSync5(dir)) {
|
|
8776
8849
|
if (!f.endsWith(ext)) continue;
|
|
8777
|
-
const fullPath =
|
|
8850
|
+
const fullPath = join12(dir, f);
|
|
8778
8851
|
try {
|
|
8779
8852
|
const st = statSync4(fullPath);
|
|
8780
8853
|
if (st.mtimeMs < cutoff) {
|
|
@@ -8814,7 +8887,7 @@ var inFlightClaudeTasks = /* @__PURE__ */ new Set();
|
|
|
8814
8887
|
var claudeTaskConcurrency = /* @__PURE__ */ new Map();
|
|
8815
8888
|
var MAX_CLAUDE_CONCURRENCY = 2;
|
|
8816
8889
|
function claudePidFilePath() {
|
|
8817
|
-
return
|
|
8890
|
+
return join12(homedir6(), ".augmented", "manager-claude-pids.json");
|
|
8818
8891
|
}
|
|
8819
8892
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
8820
8893
|
function registerClaudeSpawn(record) {
|
|
@@ -8835,10 +8908,10 @@ function unregisterClaudeSpawn(pid) {
|
|
|
8835
8908
|
var claudeSchedulerStates = /* @__PURE__ */ new Map();
|
|
8836
8909
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
|
|
8837
8910
|
const codeName = agent.code_name;
|
|
8838
|
-
const stableTasksHash =
|
|
8839
|
-
const boardHash = boardItems.length > 0 ?
|
|
8911
|
+
const stableTasksHash = createHash4("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
8912
|
+
const boardHash = boardItems.length > 0 ? createHash4("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
|
|
8840
8913
|
const resolvedModels = resolveModelChain(refreshData);
|
|
8841
|
-
const modelsHash =
|
|
8914
|
+
const modelsHash = createHash4("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
8842
8915
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
8843
8916
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
8844
8917
|
if (combinedHash !== prevHash) {
|
|
@@ -8904,7 +8977,7 @@ async function startRun(opts) {
|
|
|
8904
8977
|
return { run_id: res.run_id ?? null, kanban_item_id: res.kanban_item_id ?? null };
|
|
8905
8978
|
} catch (err) {
|
|
8906
8979
|
const errText = err instanceof Error ? err.message : String(err);
|
|
8907
|
-
const errId =
|
|
8980
|
+
const errId = createHash4("sha256").update(errText).digest("hex").slice(0, 12);
|
|
8908
8981
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
8909
8982
|
return { run_id: null, kanban_item_id: null };
|
|
8910
8983
|
}
|
|
@@ -8921,7 +8994,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
8921
8994
|
});
|
|
8922
8995
|
} catch (err) {
|
|
8923
8996
|
const errText = err instanceof Error ? err.message : String(err);
|
|
8924
|
-
const errId =
|
|
8997
|
+
const errId = createHash4("sha256").update(errText).digest("hex").slice(0, 12);
|
|
8925
8998
|
log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
|
|
8926
8999
|
}
|
|
8927
9000
|
}
|
|
@@ -8938,7 +9011,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
8938
9011
|
return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
|
|
8939
9012
|
} catch (err) {
|
|
8940
9013
|
const errText = err instanceof Error ? err.message : String(err);
|
|
8941
|
-
const errId =
|
|
9014
|
+
const errId = createHash4("sha256").update(errText).digest("hex").slice(0, 12);
|
|
8942
9015
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
8943
9016
|
return [];
|
|
8944
9017
|
}
|
|
@@ -9154,7 +9227,7 @@ async function fireScheduledTaskViaKanban(codeName, agentId, task, prompt) {
|
|
|
9154
9227
|
}
|
|
9155
9228
|
async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
9156
9229
|
const projectDir = getProjectDir2(codeName);
|
|
9157
|
-
const mcpConfigPath =
|
|
9230
|
+
const mcpConfigPath = join12(projectDir, ".mcp.json");
|
|
9158
9231
|
let runId = null;
|
|
9159
9232
|
let kanbanItemId = null;
|
|
9160
9233
|
let taskResult;
|
|
@@ -9162,11 +9235,11 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
|
9162
9235
|
const priorRuns = await fetchPriorScheduledRuns(agentId, task.taskId);
|
|
9163
9236
|
prompt = wrapScheduledTaskPrompt(prompt, { priorRuns });
|
|
9164
9237
|
try {
|
|
9165
|
-
const claudeMdPath =
|
|
9238
|
+
const claudeMdPath = join12(projectDir, "CLAUDE.md");
|
|
9166
9239
|
const serverNames = [];
|
|
9167
|
-
if (
|
|
9240
|
+
if (existsSync6(mcpConfigPath)) {
|
|
9168
9241
|
try {
|
|
9169
|
-
const d = JSON.parse(
|
|
9242
|
+
const d = JSON.parse(readFileSync11(mcpConfigPath, "utf-8"));
|
|
9170
9243
|
if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
|
|
9171
9244
|
} catch {
|
|
9172
9245
|
}
|
|
@@ -9185,14 +9258,14 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
|
9185
9258
|
"--allowedTools",
|
|
9186
9259
|
allowedTools
|
|
9187
9260
|
];
|
|
9188
|
-
if (
|
|
9261
|
+
if (existsSync6(claudeMdPath)) {
|
|
9189
9262
|
claudeArgs.push("--system-prompt-file", claudeMdPath);
|
|
9190
9263
|
}
|
|
9191
9264
|
const childEnv = { ...process.env };
|
|
9192
|
-
const envIntPath =
|
|
9193
|
-
if (
|
|
9265
|
+
const envIntPath = join12(projectDir, ".env.integrations");
|
|
9266
|
+
if (existsSync6(envIntPath)) {
|
|
9194
9267
|
try {
|
|
9195
|
-
Object.assign(childEnv, parseEnvIntegrations(
|
|
9268
|
+
Object.assign(childEnv, parseEnvIntegrations(readFileSync11(envIntPath, "utf-8")));
|
|
9196
9269
|
} catch {
|
|
9197
9270
|
}
|
|
9198
9271
|
}
|
|
@@ -9294,10 +9367,10 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
9294
9367
|
const classification = classifyOutput(rawOutput);
|
|
9295
9368
|
if (classification.action === "suppress") {
|
|
9296
9369
|
const trimmed = (rawOutput ?? "").trim();
|
|
9297
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
9370
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash4("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
9298
9371
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
9299
9372
|
if (classification.suppressedNotes) {
|
|
9300
|
-
const notesHash =
|
|
9373
|
+
const notesHash = createHash4("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
9301
9374
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
9302
9375
|
}
|
|
9303
9376
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -9364,8 +9437,8 @@ var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
|
9364
9437
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
9365
9438
|
const codeName = agent.code_name;
|
|
9366
9439
|
const projectDir = getProjectDir(codeName);
|
|
9367
|
-
const mcpConfigPath =
|
|
9368
|
-
const claudeMdPath =
|
|
9440
|
+
const mcpConfigPath = join12(projectDir, ".mcp.json");
|
|
9441
|
+
const claudeMdPath = join12(projectDir, "CLAUDE.md");
|
|
9369
9442
|
if (restartBreaker.isTripped(codeName)) {
|
|
9370
9443
|
const trip = restartBreaker.getTrip(codeName);
|
|
9371
9444
|
return {
|
|
@@ -9482,7 +9555,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
9482
9555
|
const ctx = getLastFailureContext(codeName);
|
|
9483
9556
|
const recovery = prepareForRespawn(codeName);
|
|
9484
9557
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
9485
|
-
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${
|
|
9558
|
+
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash4("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
|
|
9486
9559
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
9487
9560
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
9488
9561
|
log(
|
|
@@ -9496,7 +9569,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash3("sha256").
|
|
|
9496
9569
|
);
|
|
9497
9570
|
getHostId().then((hostId) => {
|
|
9498
9571
|
if (!hostId) return;
|
|
9499
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
9572
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash4("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
9500
9573
|
return api.post("/host/events", {
|
|
9501
9574
|
host_id: hostId,
|
|
9502
9575
|
agent_code_name: codeName,
|
|
@@ -9575,7 +9648,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash3("sha256").
|
|
|
9575
9648
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
9576
9649
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
9577
9650
|
}
|
|
9578
|
-
const stableTasksHash =
|
|
9651
|
+
const stableTasksHash = createHash4("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
9579
9652
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
9580
9653
|
if (stableTasksHash !== prevHash) {
|
|
9581
9654
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
@@ -9964,8 +10037,8 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
9964
10037
|
if (isSessionHealthy(agent.codeName)) {
|
|
9965
10038
|
if (hostFlagStore().getBoolean("direct-chat-doorbell")) {
|
|
9966
10039
|
try {
|
|
9967
|
-
const doorbell = directChatDoorbellPath(agent.agentId,
|
|
9968
|
-
|
|
10040
|
+
const doorbell = directChatDoorbellPath(agent.agentId, homedir6());
|
|
10041
|
+
mkdirSync4(dirname3(doorbell), { recursive: true });
|
|
9969
10042
|
writeFileSync4(doorbell, String(Date.now()));
|
|
9970
10043
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
9971
10044
|
return;
|
|
@@ -10010,11 +10083,11 @@ ${escapeXml(msg.content)}
|
|
|
10010
10083
|
log(`[direct-chat] One-shot spawn for '${agent.codeName}' (msg=${msg.id}; host in-flight=${directChatSpawnGate.hostInFlight}, queued=${directChatSpawnGate.queuedCount})`);
|
|
10011
10084
|
const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
10012
10085
|
const projDir = ccProjectDir(agent.codeName);
|
|
10013
|
-
const mcpConfigPath =
|
|
10086
|
+
const mcpConfigPath = join12(projDir, ".mcp.json");
|
|
10014
10087
|
const serverNames = [];
|
|
10015
|
-
if (
|
|
10088
|
+
if (existsSync6(mcpConfigPath)) {
|
|
10016
10089
|
try {
|
|
10017
|
-
const d = JSON.parse(
|
|
10090
|
+
const d = JSON.parse(readFileSync11(mcpConfigPath, "utf-8"));
|
|
10018
10091
|
if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
|
|
10019
10092
|
} catch {
|
|
10020
10093
|
}
|
|
@@ -10033,15 +10106,15 @@ ${escapeXml(msg.content)}
|
|
|
10033
10106
|
"--allowedTools",
|
|
10034
10107
|
allowedTools
|
|
10035
10108
|
];
|
|
10036
|
-
const chatClaudeMd =
|
|
10037
|
-
if (
|
|
10109
|
+
const chatClaudeMd = join12(projDir, "CLAUDE.md");
|
|
10110
|
+
if (existsSync6(chatClaudeMd)) {
|
|
10038
10111
|
chatArgs.push("--system-prompt-file", chatClaudeMd);
|
|
10039
10112
|
}
|
|
10040
|
-
const envIntPath =
|
|
10113
|
+
const envIntPath = join12(projDir, ".env.integrations");
|
|
10041
10114
|
const childEnv = { ...process.env };
|
|
10042
|
-
if (
|
|
10115
|
+
if (existsSync6(envIntPath)) {
|
|
10043
10116
|
try {
|
|
10044
|
-
Object.assign(childEnv, parseEnvIntegrations(
|
|
10117
|
+
Object.assign(childEnv, parseEnvIntegrations(readFileSync11(envIntPath, "utf-8")));
|
|
10045
10118
|
} catch {
|
|
10046
10119
|
}
|
|
10047
10120
|
}
|
|
@@ -10101,7 +10174,7 @@ ${escapeXml(msg.content)}
|
|
|
10101
10174
|
log(`[direct-chat] Reply sent for '${agent.codeName}'`);
|
|
10102
10175
|
} catch (err) {
|
|
10103
10176
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
10104
|
-
const errorId =
|
|
10177
|
+
const errorId = createHash4("sha256").update(errMsg).digest("hex").slice(0, 12);
|
|
10105
10178
|
log(`[direct-chat] Failed to process message for '${agent.codeName}': error_id=${errorId} error=${errMsg.slice(0, 500)}`);
|
|
10106
10179
|
try {
|
|
10107
10180
|
await api.post("/host/direct-chat/reply", {
|
|
@@ -10419,12 +10492,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
10419
10492
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
10420
10493
|
try {
|
|
10421
10494
|
const candidates = [
|
|
10422
|
-
|
|
10423
|
-
|
|
10495
|
+
join12(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
10496
|
+
join12(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
10424
10497
|
];
|
|
10425
10498
|
for (const candidate of candidates) {
|
|
10426
|
-
if (
|
|
10427
|
-
const content =
|
|
10499
|
+
if (existsSync6(candidate)) {
|
|
10500
|
+
const content = readFileSync11(candidate, "utf-8");
|
|
10428
10501
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
10429
10502
|
builtInSkillCache.set(skillId, files);
|
|
10430
10503
|
return files;
|
|
@@ -10563,73 +10636,6 @@ function formatBoardForPrompt(items, template) {
|
|
|
10563
10636
|
}
|
|
10564
10637
|
return lines.join("\n");
|
|
10565
10638
|
}
|
|
10566
|
-
async function execFilePromise(cmd, args) {
|
|
10567
|
-
const { execFile: ef } = await import("child_process");
|
|
10568
|
-
return new Promise((resolve, reject) => {
|
|
10569
|
-
ef(cmd, args, { timeout: 15e3 }, (err, stdout, stderr) => {
|
|
10570
|
-
if (err) reject(err);
|
|
10571
|
-
else resolve({ stdout, stderr });
|
|
10572
|
-
});
|
|
10573
|
-
});
|
|
10574
|
-
}
|
|
10575
|
-
var ChildProcessError = class extends Error {
|
|
10576
|
-
code;
|
|
10577
|
-
stdout;
|
|
10578
|
-
stderr;
|
|
10579
|
-
constructor(code, stdout, stderr) {
|
|
10580
|
-
const stderrSnippet = stderr.trim().slice(0, 500);
|
|
10581
|
-
const stdoutSnippet = stdout.trim().slice(0, 500);
|
|
10582
|
-
const detail = stderrSnippet || stdoutSnippet || "(no output)";
|
|
10583
|
-
super(`Exit code ${code}: ${detail}`);
|
|
10584
|
-
this.name = "ChildProcessError";
|
|
10585
|
-
this.code = code;
|
|
10586
|
-
this.stdout = stdout;
|
|
10587
|
-
this.stderr = stderr;
|
|
10588
|
-
}
|
|
10589
|
-
};
|
|
10590
|
-
async function execFilePromiseLong(cmd, args, opts) {
|
|
10591
|
-
const { spawn: sp } = await import("child_process");
|
|
10592
|
-
return new Promise((resolve, reject) => {
|
|
10593
|
-
const child = sp(cmd, args, {
|
|
10594
|
-
cwd: opts?.cwd,
|
|
10595
|
-
stdio: [opts?.stdin === "ignore" ? "ignore" : "pipe", "pipe", "pipe"],
|
|
10596
|
-
...opts?.env ? { env: opts.env } : {}
|
|
10597
|
-
});
|
|
10598
|
-
if (opts?.onSpawn && typeof child.pid === "number") {
|
|
10599
|
-
try {
|
|
10600
|
-
opts.onSpawn(child.pid);
|
|
10601
|
-
} catch {
|
|
10602
|
-
}
|
|
10603
|
-
}
|
|
10604
|
-
let stdout = "";
|
|
10605
|
-
let stderr = "";
|
|
10606
|
-
child.stdout?.on("data", (d) => {
|
|
10607
|
-
stdout += d.toString();
|
|
10608
|
-
});
|
|
10609
|
-
child.stderr?.on("data", (d) => {
|
|
10610
|
-
stderr += d.toString();
|
|
10611
|
-
});
|
|
10612
|
-
const timer = setTimeout(() => {
|
|
10613
|
-
child.kill();
|
|
10614
|
-
reject(new Error(`Timed out after ${opts?.timeout ?? 12e4}ms`));
|
|
10615
|
-
}, opts?.timeout ?? 12e4);
|
|
10616
|
-
child.on("close", (code) => {
|
|
10617
|
-
clearTimeout(timer);
|
|
10618
|
-
if (opts?.onExit && typeof child.pid === "number") {
|
|
10619
|
-
try {
|
|
10620
|
-
opts.onExit(child.pid);
|
|
10621
|
-
} catch {
|
|
10622
|
-
}
|
|
10623
|
-
}
|
|
10624
|
-
if (code !== 0) reject(new ChildProcessError(code, stdout, stderr));
|
|
10625
|
-
else resolve({ stdout, stderr });
|
|
10626
|
-
});
|
|
10627
|
-
child.on("error", (err) => {
|
|
10628
|
-
clearTimeout(timer);
|
|
10629
|
-
reject(err);
|
|
10630
|
-
});
|
|
10631
|
-
});
|
|
10632
|
-
}
|
|
10633
10639
|
var LATE_THRESHOLD_MS = 5 * 60 * 1e3;
|
|
10634
10640
|
async function monitorCronHealth(agentStates) {
|
|
10635
10641
|
const alerts = [];
|
|
@@ -11393,8 +11399,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
11393
11399
|
};
|
|
11394
11400
|
}
|
|
11395
11401
|
async function syncMemories(agent, configDir, log2) {
|
|
11396
|
-
const projectDir =
|
|
11397
|
-
const memoryDir =
|
|
11402
|
+
const projectDir = join12(configDir, agent.code_name, "project");
|
|
11403
|
+
const memoryDir = join12(projectDir, "memory");
|
|
11398
11404
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
11399
11405
|
if (isFreshSync) {
|
|
11400
11406
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -11405,15 +11411,15 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
11405
11411
|
}
|
|
11406
11412
|
pendingFreshMemorySync.delete(agent.agent_id);
|
|
11407
11413
|
}
|
|
11408
|
-
if (
|
|
11414
|
+
if (existsSync6(memoryDir)) {
|
|
11409
11415
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
11410
11416
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
11411
11417
|
const changedMemories = [];
|
|
11412
11418
|
for (const file of readdirSync5(memoryDir)) {
|
|
11413
11419
|
if (!file.endsWith(".md")) continue;
|
|
11414
11420
|
try {
|
|
11415
|
-
const raw =
|
|
11416
|
-
const fileHash =
|
|
11421
|
+
const raw = readFileSync11(join12(memoryDir, file), "utf-8");
|
|
11422
|
+
const fileHash = createHash4("sha256").update(raw).digest("hex").slice(0, 16);
|
|
11417
11423
|
currentHashes.set(file, fileHash);
|
|
11418
11424
|
if (prevHashes.get(file) === fileHash) continue;
|
|
11419
11425
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -11437,7 +11443,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
11437
11443
|
} catch (err) {
|
|
11438
11444
|
for (const mem of changedMemories) {
|
|
11439
11445
|
for (const [file] of currentHashes) {
|
|
11440
|
-
const parsed = parseMemoryFile(
|
|
11446
|
+
const parsed = parseMemoryFile(readFileSync11(join12(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
11441
11447
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
11442
11448
|
}
|
|
11443
11449
|
}
|
|
@@ -11450,29 +11456,29 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
11450
11456
|
}
|
|
11451
11457
|
}
|
|
11452
11458
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
11453
|
-
const localFiles =
|
|
11454
|
-
const localListHash =
|
|
11459
|
+
const localFiles = existsSync6(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
11460
|
+
const localListHash = createHash4("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
11455
11461
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
11456
11462
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
11457
11463
|
try {
|
|
11458
11464
|
const dbMemories = await api.post("/host/memories", {
|
|
11459
11465
|
agent_id: agent.agent_id
|
|
11460
11466
|
});
|
|
11461
|
-
const responseHash =
|
|
11467
|
+
const responseHash = createHash4("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
|
|
11462
11468
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
11463
11469
|
return true;
|
|
11464
11470
|
}
|
|
11465
11471
|
lastDownloadHash.set(agent.agent_id, responseHash);
|
|
11466
11472
|
lastLocalFileHash.set(agent.agent_id, localListHash);
|
|
11467
11473
|
if (dbMemories.memories?.length) {
|
|
11468
|
-
|
|
11474
|
+
mkdirSync4(memoryDir, { recursive: true });
|
|
11469
11475
|
let written = 0;
|
|
11470
11476
|
let overwritten = 0;
|
|
11471
11477
|
for (let i = 0; i < dbMemories.memories.length; i++) {
|
|
11472
11478
|
const mem = dbMemories.memories[i];
|
|
11473
11479
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
11474
11480
|
const slug = rawSlug || `memory-${i}`;
|
|
11475
|
-
const filePath =
|
|
11481
|
+
const filePath = join12(memoryDir, `${slug}.md`);
|
|
11476
11482
|
const desired = `---
|
|
11477
11483
|
name: ${JSON.stringify(mem.name)}
|
|
11478
11484
|
type: ${mem.type}
|
|
@@ -11481,10 +11487,10 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
|
|
|
11481
11487
|
|
|
11482
11488
|
${mem.content}
|
|
11483
11489
|
`;
|
|
11484
|
-
if (
|
|
11490
|
+
if (existsSync6(filePath)) {
|
|
11485
11491
|
let existing = "";
|
|
11486
11492
|
try {
|
|
11487
|
-
existing =
|
|
11493
|
+
existing = readFileSync11(filePath, "utf-8");
|
|
11488
11494
|
} catch {
|
|
11489
11495
|
}
|
|
11490
11496
|
if (existing === desired) continue;
|
|
@@ -11497,7 +11503,7 @@ ${mem.content}
|
|
|
11497
11503
|
}
|
|
11498
11504
|
if (written > 0 || overwritten > 0) {
|
|
11499
11505
|
const updatedFiles = readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
11500
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
11506
|
+
lastLocalFileHash.set(agent.agent_id, createHash4("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
11501
11507
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
11502
11508
|
}
|
|
11503
11509
|
}
|
|
@@ -11508,7 +11514,7 @@ ${mem.content}
|
|
|
11508
11514
|
}
|
|
11509
11515
|
}
|
|
11510
11516
|
async function cleanupAgentFiles(codeName, agentDir) {
|
|
11511
|
-
if (
|
|
11517
|
+
if (existsSync6(agentDir)) {
|
|
11512
11518
|
try {
|
|
11513
11519
|
rmSync2(agentDir, { recursive: true, force: true });
|
|
11514
11520
|
log(`Removed provision directory for '${codeName}'`);
|
|
@@ -11738,8 +11744,8 @@ function startManager(opts) {
|
|
|
11738
11744
|
config = opts;
|
|
11739
11745
|
try {
|
|
11740
11746
|
const stateFile = getStateFile();
|
|
11741
|
-
if (
|
|
11742
|
-
const raw =
|
|
11747
|
+
if (existsSync6(stateFile)) {
|
|
11748
|
+
const raw = readFileSync11(stateFile, "utf-8");
|
|
11743
11749
|
const parsed = JSON.parse(raw);
|
|
11744
11750
|
if (Array.isArray(parsed.agents)) {
|
|
11745
11751
|
state6.agents = parsed.agents;
|
|
@@ -11760,7 +11766,7 @@ function startManager(opts) {
|
|
|
11760
11766
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
11761
11767
|
}
|
|
11762
11768
|
log(
|
|
11763
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
11769
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join12(homedir6(), ".augmented", "manager.log")}`
|
|
11764
11770
|
);
|
|
11765
11771
|
deployMcpAssets();
|
|
11766
11772
|
reapOrphanChannelMcps({ log });
|
|
@@ -11781,7 +11787,7 @@ async function reapOrphanedClaudePids() {
|
|
|
11781
11787
|
const looksLikeClaude = (pid) => {
|
|
11782
11788
|
if (process.platform !== "linux") return true;
|
|
11783
11789
|
try {
|
|
11784
|
-
const comm =
|
|
11790
|
+
const comm = readFileSync11(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
11785
11791
|
return comm.includes("claude");
|
|
11786
11792
|
} catch {
|
|
11787
11793
|
return false;
|
|
@@ -11891,18 +11897,18 @@ function restartRunningChannelMcps(basenames) {
|
|
|
11891
11897
|
}
|
|
11892
11898
|
}
|
|
11893
11899
|
function deployMcpAssets() {
|
|
11894
|
-
const targetDir =
|
|
11895
|
-
|
|
11896
|
-
const moduleDir =
|
|
11900
|
+
const targetDir = join12(homedir6(), ".augmented", "_mcp");
|
|
11901
|
+
mkdirSync4(targetDir, { recursive: true });
|
|
11902
|
+
const moduleDir = dirname3(fileURLToPath(import.meta.url));
|
|
11897
11903
|
let mcpSourceDir = "";
|
|
11898
11904
|
let dir = moduleDir;
|
|
11899
11905
|
for (let i = 0; i < 6; i++) {
|
|
11900
|
-
const candidate =
|
|
11901
|
-
if (
|
|
11906
|
+
const candidate = join12(dir, "dist", "mcp");
|
|
11907
|
+
if (existsSync6(join12(candidate, "index.js"))) {
|
|
11902
11908
|
mcpSourceDir = candidate;
|
|
11903
11909
|
break;
|
|
11904
11910
|
}
|
|
11905
|
-
const parent =
|
|
11911
|
+
const parent = dirname3(dir);
|
|
11906
11912
|
if (parent === dir) break;
|
|
11907
11913
|
dir = parent;
|
|
11908
11914
|
}
|
|
@@ -11913,8 +11919,8 @@ function deployMcpAssets() {
|
|
|
11913
11919
|
const changedBasenames = [];
|
|
11914
11920
|
const fileHash = (p) => {
|
|
11915
11921
|
try {
|
|
11916
|
-
if (!
|
|
11917
|
-
return
|
|
11922
|
+
if (!existsSync6(p)) return null;
|
|
11923
|
+
return createHash4("sha256").update(readFileSync11(p)).digest("hex");
|
|
11918
11924
|
} catch {
|
|
11919
11925
|
return null;
|
|
11920
11926
|
}
|
|
@@ -11941,9 +11947,9 @@ function deployMcpAssets() {
|
|
|
11941
11947
|
// natural session restart.
|
|
11942
11948
|
"augmented-admin.js"
|
|
11943
11949
|
]) {
|
|
11944
|
-
const src =
|
|
11945
|
-
const dst =
|
|
11946
|
-
if (!
|
|
11950
|
+
const src = join12(mcpSourceDir, file);
|
|
11951
|
+
const dst = join12(targetDir, file);
|
|
11952
|
+
if (!existsSync6(src)) continue;
|
|
11947
11953
|
const before = fileHash(dst);
|
|
11948
11954
|
try {
|
|
11949
11955
|
copyFileSync(src, dst);
|
|
@@ -11960,16 +11966,16 @@ function deployMcpAssets() {
|
|
|
11960
11966
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
11961
11967
|
restartRunningChannelMcps(changedBasenames);
|
|
11962
11968
|
}
|
|
11963
|
-
const localMcpPath =
|
|
11969
|
+
const localMcpPath = join12(targetDir, "index.js");
|
|
11964
11970
|
try {
|
|
11965
|
-
const agentsDir =
|
|
11966
|
-
if (
|
|
11971
|
+
const agentsDir = join12(homedir6(), ".augmented", "agents");
|
|
11972
|
+
if (existsSync6(agentsDir)) {
|
|
11967
11973
|
for (const entry of readdirSync5(agentsDir, { withFileTypes: true })) {
|
|
11968
11974
|
if (!entry.isDirectory()) continue;
|
|
11969
11975
|
for (const subdir of ["provision", "project"]) {
|
|
11970
|
-
const mcpJsonPath =
|
|
11976
|
+
const mcpJsonPath = join12(agentsDir, entry.name, subdir, ".mcp.json");
|
|
11971
11977
|
try {
|
|
11972
|
-
const raw =
|
|
11978
|
+
const raw = readFileSync11(mcpJsonPath, "utf-8");
|
|
11973
11979
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
11974
11980
|
const mcpConfig = JSON.parse(raw);
|
|
11975
11981
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
@@ -12012,7 +12018,6 @@ process.on("disconnect", () => {
|
|
|
12012
12018
|
});
|
|
12013
12019
|
export {
|
|
12014
12020
|
BACK_ONLINE_GREETING_GUIDANCE,
|
|
12015
|
-
ChildProcessError,
|
|
12016
12021
|
SCHEDULED_CARD_DELIVERY_CONTRACT,
|
|
12017
12022
|
__resetScheduledDeliveryDedupeForTest,
|
|
12018
12023
|
__setAgentChannelTokensForTest,
|