@integrity-labs/agt-cli 0.28.720 → 0.28.722
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 +13 -5
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-V5T2K5NN.js → chunk-LWDPZWSO.js} +6 -2
- package/dist/{chunk-V5T2K5NN.js.map → chunk-LWDPZWSO.js.map} +1 -1
- package/dist/lib/manager-worker.js +482 -334
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
safeWriteJsonAtomic,
|
|
58
58
|
setConfigHash,
|
|
59
59
|
tripClass
|
|
60
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-LWDPZWSO.js";
|
|
61
61
|
import {
|
|
62
62
|
getProjectDir as getProjectDir2,
|
|
63
63
|
getReadyTasks,
|
|
@@ -206,8 +206,8 @@ import {
|
|
|
206
206
|
} from "../chunk-XWVM4KPK.js";
|
|
207
207
|
|
|
208
208
|
// src/lib/manager-worker.ts
|
|
209
|
-
import { createHash as
|
|
210
|
-
import { readFileSync as
|
|
209
|
+
import { createHash as createHash19 } from "crypto";
|
|
210
|
+
import { readFileSync as readFileSync31, writeFileSync as writeFileSync17, mkdirSync as mkdirSync13, existsSync as existsSync18, rmSync as rmSync7, readdirSync as readdirSync11, statSync as statSync10, unlinkSync as unlinkSync6, renameSync as renameSync10, utimesSync as utimesSync3 } from "fs";
|
|
211
211
|
|
|
212
212
|
// src/lib/atomic-file-replace.ts
|
|
213
213
|
import { copyFileSync, renameSync, unlinkSync } from "fs";
|
|
@@ -233,7 +233,7 @@ function defaultUnique() {
|
|
|
233
233
|
|
|
234
234
|
// src/lib/manager-worker.ts
|
|
235
235
|
import { execFileSync as syncExecFile } from "child_process";
|
|
236
|
-
import { join as
|
|
236
|
+
import { join as join40, dirname as dirname10, delimiter as pathDelimiter } from "path";
|
|
237
237
|
import { homedir as homedir17 } from "os";
|
|
238
238
|
import { fileURLToPath } from "url";
|
|
239
239
|
|
|
@@ -1694,12 +1694,12 @@ function isPathInsideDir(candidate, dir) {
|
|
|
1694
1694
|
return resolvedCandidate.startsWith(resolvedDir.endsWith(sep) ? resolvedDir : resolvedDir + sep);
|
|
1695
1695
|
}
|
|
1696
1696
|
function findMissingMcpBundles(mcpConfigPath, deps = {}) {
|
|
1697
|
-
const
|
|
1698
|
-
const
|
|
1697
|
+
const existsSync19 = deps.existsSync ?? nodeExistsSync;
|
|
1698
|
+
const readFileSync32 = deps.readFileSync ?? nodeReadFileSync;
|
|
1699
1699
|
const mcpDir = deps.mcpDir ?? getSharedMcpDir();
|
|
1700
1700
|
let parsed;
|
|
1701
1701
|
try {
|
|
1702
|
-
parsed = JSON.parse(
|
|
1702
|
+
parsed = JSON.parse(readFileSync32(mcpConfigPath, "utf-8"));
|
|
1703
1703
|
} catch {
|
|
1704
1704
|
return [];
|
|
1705
1705
|
}
|
|
@@ -1719,7 +1719,7 @@ function findMissingMcpBundles(mcpConfigPath, deps = {}) {
|
|
|
1719
1719
|
if (seenPaths.has(resolvedBundlePath)) continue;
|
|
1720
1720
|
let present;
|
|
1721
1721
|
try {
|
|
1722
|
-
present =
|
|
1722
|
+
present = existsSync19(bundlePath);
|
|
1723
1723
|
} catch {
|
|
1724
1724
|
continue;
|
|
1725
1725
|
}
|
|
@@ -5300,19 +5300,140 @@ async function resolveKnowledgeFromManifest(args) {
|
|
|
5300
5300
|
}));
|
|
5301
5301
|
}
|
|
5302
5302
|
|
|
5303
|
-
// src/lib/
|
|
5304
|
-
import {
|
|
5303
|
+
// src/lib/skill-cache.ts
|
|
5304
|
+
import { createHash as createHash10 } from "crypto";
|
|
5305
|
+
import {
|
|
5306
|
+
existsSync as existsSync7,
|
|
5307
|
+
mkdirSync as mkdirSync7,
|
|
5308
|
+
readFileSync as readFileSync18,
|
|
5309
|
+
readdirSync as readdirSync6,
|
|
5310
|
+
renameSync as renameSync6,
|
|
5311
|
+
rmSync as rmSync4,
|
|
5312
|
+
statSync as statSync6,
|
|
5313
|
+
utimesSync as utimesSync2,
|
|
5314
|
+
writeFileSync as writeFileSync9
|
|
5315
|
+
} from "fs";
|
|
5305
5316
|
import { join as join24 } from "path";
|
|
5317
|
+
var SKILL_FETCH_CHUNK = 100;
|
|
5318
|
+
var CACHE_TTL_MS2 = 30 * 24 * 60 * 60 * 1e3;
|
|
5319
|
+
var SWEEP_INTERVAL_MS2 = 24 * 60 * 60 * 1e3;
|
|
5320
|
+
var lastSweepAt2 = 0;
|
|
5321
|
+
function skillHash(content) {
|
|
5322
|
+
return createHash10("sha256").update(content, "utf8").digest("hex");
|
|
5323
|
+
}
|
|
5324
|
+
function cachePath2(cacheDir, hash) {
|
|
5325
|
+
return join24(cacheDir, hash);
|
|
5326
|
+
}
|
|
5327
|
+
function readCachedSkill(cacheDir, hash) {
|
|
5328
|
+
const path = cachePath2(cacheDir, hash);
|
|
5329
|
+
try {
|
|
5330
|
+
const content = readFileSync18(path, "utf-8");
|
|
5331
|
+
try {
|
|
5332
|
+
const now = /* @__PURE__ */ new Date();
|
|
5333
|
+
utimesSync2(path, now, now);
|
|
5334
|
+
} catch {
|
|
5335
|
+
}
|
|
5336
|
+
return content;
|
|
5337
|
+
} catch {
|
|
5338
|
+
return null;
|
|
5339
|
+
}
|
|
5340
|
+
}
|
|
5341
|
+
function writeCachedSkill(cacheDir, hash, content) {
|
|
5342
|
+
if (skillHash(content) !== hash) return "mismatch";
|
|
5343
|
+
try {
|
|
5344
|
+
mkdirSync7(cacheDir, { recursive: true });
|
|
5345
|
+
const tmp = `${cachePath2(cacheDir, hash)}.tmp-${process.pid}`;
|
|
5346
|
+
writeFileSync9(tmp, content, "utf-8");
|
|
5347
|
+
renameSync6(tmp, cachePath2(cacheDir, hash));
|
|
5348
|
+
return "written";
|
|
5349
|
+
} catch {
|
|
5350
|
+
return "write-failed";
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
function sweepSkillCache(cacheDir, now = Date.now()) {
|
|
5354
|
+
if (now - lastSweepAt2 < SWEEP_INTERVAL_MS2) return;
|
|
5355
|
+
lastSweepAt2 = now;
|
|
5356
|
+
try {
|
|
5357
|
+
if (!existsSync7(cacheDir)) return;
|
|
5358
|
+
for (const name of readdirSync6(cacheDir)) {
|
|
5359
|
+
const path = join24(cacheDir, name);
|
|
5360
|
+
try {
|
|
5361
|
+
if (now - statSync6(path).mtimeMs > CACHE_TTL_MS2) rmSync4(path, { force: true });
|
|
5362
|
+
} catch {
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
} catch {
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
async function resolveSkillsFromManifest(args) {
|
|
5369
|
+
const { globals, shared, cacheDir, fetchContents, log: log2 } = args;
|
|
5370
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
5371
|
+
const missing = [];
|
|
5372
|
+
for (const entry of [...globals, ...shared]) {
|
|
5373
|
+
if (!entry.hash) {
|
|
5374
|
+
log2?.(`[skills] manifest entry '${entry.code_name}' has no hash \u2014 skipping skill sync`);
|
|
5375
|
+
return null;
|
|
5376
|
+
}
|
|
5377
|
+
if (bodies.has(entry.hash) || missing.includes(entry.hash)) continue;
|
|
5378
|
+
const cached = readCachedSkill(cacheDir, entry.hash);
|
|
5379
|
+
if (cached !== null) bodies.set(entry.hash, cached);
|
|
5380
|
+
else missing.push(entry.hash);
|
|
5381
|
+
}
|
|
5382
|
+
for (let i = 0; i < missing.length; i += SKILL_FETCH_CHUNK) {
|
|
5383
|
+
const chunk2 = missing.slice(i, i + SKILL_FETCH_CHUNK);
|
|
5384
|
+
try {
|
|
5385
|
+
for (const { hash, content } of await fetchContents(chunk2)) {
|
|
5386
|
+
const written = writeCachedSkill(cacheDir, hash, content);
|
|
5387
|
+
if (written === "mismatch") {
|
|
5388
|
+
log2?.(`[skills] hash mismatch for ${hash} \u2014 skipping skill sync this poll`);
|
|
5389
|
+
continue;
|
|
5390
|
+
}
|
|
5391
|
+
if (written === "write-failed") {
|
|
5392
|
+
log2?.(`[skills] cache write failed for ${hash} \u2014 serving it uncached this poll`);
|
|
5393
|
+
}
|
|
5394
|
+
bodies.set(hash, content);
|
|
5395
|
+
}
|
|
5396
|
+
} catch (err) {
|
|
5397
|
+
log2?.(`[skills] fetch failed for ${chunk2.length} entries: ${err.message}`);
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
sweepSkillCache(cacheDir);
|
|
5401
|
+
const resolve2 = (entries) => {
|
|
5402
|
+
const out = [];
|
|
5403
|
+
for (const e of entries) {
|
|
5404
|
+
const content = e.hash ? bodies.get(e.hash) : void 0;
|
|
5405
|
+
if (content === void 0) return null;
|
|
5406
|
+
out.push({
|
|
5407
|
+
code_name: e.code_name,
|
|
5408
|
+
...e.display_name !== void 0 ? { display_name: e.display_name } : {},
|
|
5409
|
+
...e.scope !== void 0 ? { scope: e.scope } : {},
|
|
5410
|
+
content
|
|
5411
|
+
});
|
|
5412
|
+
}
|
|
5413
|
+
return out;
|
|
5414
|
+
};
|
|
5415
|
+
const resolvedGlobals = resolve2(globals);
|
|
5416
|
+
const resolvedShared = resolve2(shared);
|
|
5417
|
+
if (resolvedGlobals === null || resolvedShared === null) {
|
|
5418
|
+
log2?.("[skills] one or more bodies unresolved \u2014 leaving on-disk skills untouched this poll");
|
|
5419
|
+
return null;
|
|
5420
|
+
}
|
|
5421
|
+
return { globals: resolvedGlobals, shared: resolvedShared };
|
|
5422
|
+
}
|
|
5423
|
+
|
|
5424
|
+
// src/lib/channel-hash-cache.ts
|
|
5425
|
+
import { existsSync as existsSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync10 } from "fs";
|
|
5426
|
+
import { join as join25 } from "path";
|
|
5306
5427
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
5307
5428
|
function getChannelHashCacheFile(configDir) {
|
|
5308
|
-
return
|
|
5429
|
+
return join25(configDir, CACHE_FILENAME);
|
|
5309
5430
|
}
|
|
5310
5431
|
function loadChannelHashCache(target, configDir) {
|
|
5311
5432
|
const path = getChannelHashCacheFile(configDir);
|
|
5312
|
-
if (!
|
|
5433
|
+
if (!existsSync8(path)) return;
|
|
5313
5434
|
let parsed;
|
|
5314
5435
|
try {
|
|
5315
|
-
parsed = JSON.parse(
|
|
5436
|
+
parsed = JSON.parse(readFileSync19(path, "utf-8"));
|
|
5316
5437
|
} catch {
|
|
5317
5438
|
return;
|
|
5318
5439
|
}
|
|
@@ -5326,14 +5447,14 @@ function saveChannelHashCache(source, configDir) {
|
|
|
5326
5447
|
const obj = {};
|
|
5327
5448
|
for (const [key, value] of source) obj[key] = value;
|
|
5328
5449
|
try {
|
|
5329
|
-
|
|
5450
|
+
writeFileSync10(path, JSON.stringify(obj, null, 2));
|
|
5330
5451
|
} catch {
|
|
5331
5452
|
}
|
|
5332
5453
|
}
|
|
5333
5454
|
|
|
5334
5455
|
// src/lib/sender-policy-baseline.ts
|
|
5335
|
-
import { existsSync as
|
|
5336
|
-
import { join as
|
|
5456
|
+
import { existsSync as existsSync9, readFileSync as readFileSync20 } from "fs";
|
|
5457
|
+
import { join as join26 } from "path";
|
|
5337
5458
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
5338
5459
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
5339
5460
|
var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
|
|
@@ -5345,14 +5466,14 @@ function createDeliveryBaselineMaps() {
|
|
|
5345
5466
|
};
|
|
5346
5467
|
}
|
|
5347
5468
|
function getSenderPolicyBaselineFile(configDir) {
|
|
5348
|
-
return
|
|
5469
|
+
return join26(configDir, BASELINE_FILENAME);
|
|
5349
5470
|
}
|
|
5350
5471
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
5351
5472
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
5352
|
-
if (!
|
|
5473
|
+
if (!existsSync9(path)) return;
|
|
5353
5474
|
let parsed;
|
|
5354
5475
|
try {
|
|
5355
|
-
parsed = JSON.parse(
|
|
5476
|
+
parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
5356
5477
|
} catch (err) {
|
|
5357
5478
|
log2?.(
|
|
5358
5479
|
`[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
|
|
@@ -5401,8 +5522,8 @@ function saveSenderPolicyBaseline(source, configDir, log2) {
|
|
|
5401
5522
|
}
|
|
5402
5523
|
|
|
5403
5524
|
// src/lib/stuck-streak-store.ts
|
|
5404
|
-
import { existsSync as
|
|
5405
|
-
import { join as
|
|
5525
|
+
import { existsSync as existsSync10, readFileSync as readFileSync21 } from "fs";
|
|
5526
|
+
import { join as join27 } from "path";
|
|
5406
5527
|
var STORE_FILENAME = "stuck-streaks.json";
|
|
5407
5528
|
var STUCK_STREAK_STORE_VERSION = 1;
|
|
5408
5529
|
var STUCK_STREAK_CONCERNS = ["channelSync", "realtimeRebind"];
|
|
@@ -5410,7 +5531,7 @@ function createStuckStreakMaps() {
|
|
|
5410
5531
|
return { channelSync: /* @__PURE__ */ new Map(), realtimeRebind: /* @__PURE__ */ new Map() };
|
|
5411
5532
|
}
|
|
5412
5533
|
function getStuckStreakStoreFile(configDir) {
|
|
5413
|
-
return
|
|
5534
|
+
return join27(configDir, STORE_FILENAME);
|
|
5414
5535
|
}
|
|
5415
5536
|
function isValidPersistedStreak(value) {
|
|
5416
5537
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -5449,10 +5570,10 @@ function buildStuckStreakPayload(source) {
|
|
|
5449
5570
|
}
|
|
5450
5571
|
function loadStuckStreaks(target, configDir, log2) {
|
|
5451
5572
|
const path = getStuckStreakStoreFile(configDir);
|
|
5452
|
-
if (!
|
|
5573
|
+
if (!existsSync10(path)) return;
|
|
5453
5574
|
let parsed;
|
|
5454
5575
|
try {
|
|
5455
|
-
parsed = JSON.parse(
|
|
5576
|
+
parsed = JSON.parse(readFileSync21(path, "utf-8"));
|
|
5456
5577
|
} catch (err) {
|
|
5457
5578
|
log2?.(
|
|
5458
5579
|
`[stuck-streaks] discarding corrupt ${STORE_FILENAME} (${err.message}) \u2014 stuck-streak ages restart from zero and one spurious "recovered" close may follow`
|
|
@@ -5969,7 +6090,7 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
5969
6090
|
}
|
|
5970
6091
|
|
|
5971
6092
|
// src/lib/manager/integration-skill-cache.ts
|
|
5972
|
-
import { join as
|
|
6093
|
+
import { join as join28 } from "path";
|
|
5973
6094
|
function integrationSkillHashKey(agentId, skillId) {
|
|
5974
6095
|
return `plugin-skill:${agentId}:${skillId}`;
|
|
5975
6096
|
}
|
|
@@ -5985,21 +6106,21 @@ function forgetIntegrationSkill(cache2, agentId, skillId) {
|
|
|
5985
6106
|
function removeIntegrationSkillFolder(opts) {
|
|
5986
6107
|
forgetIntegrationSkill(opts.cache, opts.agentId, opts.entry);
|
|
5987
6108
|
for (const dir of opts.dirs) {
|
|
5988
|
-
opts.removeDir(
|
|
6109
|
+
opts.removeDir(join28(dir, opts.entry));
|
|
5989
6110
|
}
|
|
5990
6111
|
}
|
|
5991
6112
|
|
|
5992
6113
|
// src/lib/manager/managed-skill-manifest.ts
|
|
5993
|
-
import { existsSync as
|
|
5994
|
-
import { dirname as dirname7, join as
|
|
6114
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync22, writeFileSync as writeFileSync11 } from "fs";
|
|
6115
|
+
import { dirname as dirname7, join as join29 } from "path";
|
|
5995
6116
|
var MANIFEST_VERSION = 1;
|
|
5996
6117
|
function managedSkillManifestPath(agentRootDir) {
|
|
5997
|
-
return
|
|
6118
|
+
return join29(agentRootDir, "managed-skills.json");
|
|
5998
6119
|
}
|
|
5999
6120
|
function readManagedSkillManifest(path) {
|
|
6000
6121
|
try {
|
|
6001
|
-
if (!
|
|
6002
|
-
const parsed = JSON.parse(
|
|
6122
|
+
if (!existsSync11(path)) return /* @__PURE__ */ new Set();
|
|
6123
|
+
const parsed = JSON.parse(readFileSync22(path, "utf-8"));
|
|
6003
6124
|
const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
|
|
6004
6125
|
return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
|
|
6005
6126
|
} catch {
|
|
@@ -6008,12 +6129,12 @@ function readManagedSkillManifest(path) {
|
|
|
6008
6129
|
}
|
|
6009
6130
|
function writeManagedSkillManifest(path, ids) {
|
|
6010
6131
|
try {
|
|
6011
|
-
|
|
6132
|
+
mkdirSync8(dirname7(path), { recursive: true });
|
|
6012
6133
|
const body = {
|
|
6013
6134
|
version: MANIFEST_VERSION,
|
|
6014
6135
|
globalSkillIds: [...ids].sort()
|
|
6015
6136
|
};
|
|
6016
|
-
|
|
6137
|
+
writeFileSync11(path, JSON.stringify(body, null, 2));
|
|
6017
6138
|
} catch {
|
|
6018
6139
|
}
|
|
6019
6140
|
}
|
|
@@ -6128,8 +6249,8 @@ function resolveModelChain(refreshData) {
|
|
|
6128
6249
|
}
|
|
6129
6250
|
|
|
6130
6251
|
// src/lib/manager/claude-auth.ts
|
|
6131
|
-
import { existsSync as
|
|
6132
|
-
import { join as
|
|
6252
|
+
import { existsSync as existsSync12, rmSync as rmSync5 } from "fs";
|
|
6253
|
+
import { join as join30 } from "path";
|
|
6133
6254
|
import { homedir as homedir13 } from "os";
|
|
6134
6255
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
6135
6256
|
const apiKey = getApiKey();
|
|
@@ -6142,12 +6263,12 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
6142
6263
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
6143
6264
|
}
|
|
6144
6265
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
6145
|
-
const claudeDir =
|
|
6266
|
+
const claudeDir = join30(homedir13(), ".claude");
|
|
6146
6267
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
6147
|
-
const p =
|
|
6148
|
-
if (
|
|
6268
|
+
const p = join30(claudeDir, filename);
|
|
6269
|
+
if (existsSync12(p)) {
|
|
6149
6270
|
try {
|
|
6150
|
-
|
|
6271
|
+
rmSync5(p, { force: true });
|
|
6151
6272
|
log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
|
|
6152
6273
|
} catch {
|
|
6153
6274
|
}
|
|
@@ -6226,8 +6347,8 @@ function heartbeatRuntimeAuthFields(probeVerdict) {
|
|
|
6226
6347
|
}
|
|
6227
6348
|
|
|
6228
6349
|
// src/lib/manager/kanban/parsers.ts
|
|
6229
|
-
import { existsSync as
|
|
6230
|
-
import { join as
|
|
6350
|
+
import { existsSync as existsSync13, readFileSync as readFileSync23 } from "fs";
|
|
6351
|
+
import { join as join31 } from "path";
|
|
6231
6352
|
var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
|
|
6232
6353
|
var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
|
|
6233
6354
|
var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
|
|
@@ -6379,12 +6500,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
6379
6500
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
6380
6501
|
try {
|
|
6381
6502
|
const candidates = [
|
|
6382
|
-
|
|
6383
|
-
|
|
6503
|
+
join31(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
6504
|
+
join31(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
6384
6505
|
];
|
|
6385
6506
|
for (const candidate of candidates) {
|
|
6386
|
-
if (
|
|
6387
|
-
const content =
|
|
6507
|
+
if (existsSync13(candidate)) {
|
|
6508
|
+
const content = readFileSync23(candidate, "utf-8");
|
|
6388
6509
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
6389
6510
|
builtInSkillCache.set(skillId, files);
|
|
6390
6511
|
return files;
|
|
@@ -6525,19 +6646,19 @@ function formatBoardForPrompt(items, template) {
|
|
|
6525
6646
|
}
|
|
6526
6647
|
|
|
6527
6648
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
6528
|
-
import { existsSync as
|
|
6529
|
-
import { join as
|
|
6649
|
+
import { existsSync as existsSync14, readFileSync as readFileSync24, writeFileSync as writeFileSync12 } from "fs";
|
|
6650
|
+
import { join as join32 } from "path";
|
|
6530
6651
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
6531
6652
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
6532
6653
|
function getKanbanNudgeStateFile(configDir) {
|
|
6533
|
-
return
|
|
6654
|
+
return join32(configDir, CACHE_FILENAME2);
|
|
6534
6655
|
}
|
|
6535
6656
|
function loadKanbanNudgeState(target, configDir) {
|
|
6536
6657
|
const path = getKanbanNudgeStateFile(configDir);
|
|
6537
|
-
if (!
|
|
6658
|
+
if (!existsSync14(path)) return;
|
|
6538
6659
|
let parsed;
|
|
6539
6660
|
try {
|
|
6540
|
-
parsed = JSON.parse(
|
|
6661
|
+
parsed = JSON.parse(readFileSync24(path, "utf-8"));
|
|
6541
6662
|
} catch {
|
|
6542
6663
|
return;
|
|
6543
6664
|
}
|
|
@@ -6569,13 +6690,13 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
6569
6690
|
const agents = {};
|
|
6570
6691
|
for (const [codeName, state9] of source) agents[codeName] = state9;
|
|
6571
6692
|
try {
|
|
6572
|
-
|
|
6693
|
+
writeFileSync12(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
6573
6694
|
} catch {
|
|
6574
6695
|
}
|
|
6575
6696
|
}
|
|
6576
6697
|
|
|
6577
6698
|
// src/lib/manager/kanban/notify.ts
|
|
6578
|
-
import { createHash as
|
|
6699
|
+
import { createHash as createHash11 } from "crypto";
|
|
6579
6700
|
async function enqueueKanbanNotice(opts) {
|
|
6580
6701
|
try {
|
|
6581
6702
|
const res = await api.post(
|
|
@@ -6590,7 +6711,7 @@ async function enqueueKanbanNotice(opts) {
|
|
|
6590
6711
|
return res.ok === true;
|
|
6591
6712
|
} catch (err) {
|
|
6592
6713
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6593
|
-
const errId =
|
|
6714
|
+
const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6594
6715
|
log(`[kanban] notice enqueue failed for agent_id=${opts.agentId} error_id=${errId}`);
|
|
6595
6716
|
return false;
|
|
6596
6717
|
}
|
|
@@ -6605,7 +6726,7 @@ async function cancelKanbanNotice(agentId) {
|
|
|
6605
6726
|
return typeof res.cancelled === "number" ? res.cancelled : 0;
|
|
6606
6727
|
} catch (err) {
|
|
6607
6728
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6608
|
-
const errId =
|
|
6729
|
+
const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6609
6730
|
log(`[kanban] notice cancel failed for agent_id=${agentId} error_id=${errId}`);
|
|
6610
6731
|
return null;
|
|
6611
6732
|
}
|
|
@@ -7011,7 +7132,7 @@ function deriveScheduledTaskNotify(task) {
|
|
|
7011
7132
|
}
|
|
7012
7133
|
|
|
7013
7134
|
// src/lib/manager/scheduler/runs.ts
|
|
7014
|
-
import { createHash as
|
|
7135
|
+
import { createHash as createHash12 } from "crypto";
|
|
7015
7136
|
async function startRun(opts) {
|
|
7016
7137
|
try {
|
|
7017
7138
|
const res = await api.post(
|
|
@@ -7026,7 +7147,7 @@ async function startRun(opts) {
|
|
|
7026
7147
|
};
|
|
7027
7148
|
} catch (err) {
|
|
7028
7149
|
const errText = err instanceof Error ? err.message : String(err);
|
|
7029
|
-
const errId =
|
|
7150
|
+
const errId = createHash12("sha256").update(errText).digest("hex").slice(0, 12);
|
|
7030
7151
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
7031
7152
|
return { run_id: null, kanban_item_id: null };
|
|
7032
7153
|
}
|
|
@@ -7065,7 +7186,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
7065
7186
|
return;
|
|
7066
7187
|
} catch (err) {
|
|
7067
7188
|
const errText = err instanceof Error ? err.message : String(err);
|
|
7068
|
-
const errId =
|
|
7189
|
+
const errId = createHash12("sha256").update(errText).digest("hex").slice(0, 12);
|
|
7069
7190
|
const status = err instanceof ApiError ? err.status : 0;
|
|
7070
7191
|
if (isRetryableFinishError(err) && attempt < maxRetries) {
|
|
7071
7192
|
log(
|
|
@@ -7094,7 +7215,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
7094
7215
|
return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
|
|
7095
7216
|
} catch (err) {
|
|
7096
7217
|
const errText = err instanceof Error ? err.message : String(err);
|
|
7097
|
-
const errId =
|
|
7218
|
+
const errId = createHash12("sha256").update(errText).digest("hex").slice(0, 12);
|
|
7098
7219
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
7099
7220
|
return [];
|
|
7100
7221
|
}
|
|
@@ -7154,13 +7275,13 @@ function closeSessionRunForCode(codeName, outcome, reason) {
|
|
|
7154
7275
|
}
|
|
7155
7276
|
|
|
7156
7277
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
7157
|
-
import { createHash as
|
|
7158
|
-
import { writeFileSync as
|
|
7278
|
+
import { createHash as createHash14 } from "crypto";
|
|
7279
|
+
import { writeFileSync as writeFileSync13, renameSync as renameSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync25, unlinkSync as unlinkSync3 } from "fs";
|
|
7159
7280
|
import { homedir as homedir14 } from "os";
|
|
7160
|
-
import { join as
|
|
7281
|
+
import { join as join33, dirname as dirname8 } from "path";
|
|
7161
7282
|
|
|
7162
7283
|
// src/lib/manager/scheduler/notify.ts
|
|
7163
|
-
import { createHash as
|
|
7284
|
+
import { createHash as createHash13 } from "crypto";
|
|
7164
7285
|
async function enqueueScheduledTaskNotice(opts) {
|
|
7165
7286
|
try {
|
|
7166
7287
|
const res = await api.post(
|
|
@@ -7177,7 +7298,7 @@ async function enqueueScheduledTaskNotice(opts) {
|
|
|
7177
7298
|
return res.ok === true;
|
|
7178
7299
|
} catch (err) {
|
|
7179
7300
|
const errText = err instanceof Error ? err.message : String(err);
|
|
7180
|
-
const errId =
|
|
7301
|
+
const errId = createHash13("sha256").update(errText).digest("hex").slice(0, 12);
|
|
7181
7302
|
log(
|
|
7182
7303
|
`[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
|
|
7183
7304
|
);
|
|
@@ -7516,19 +7637,19 @@ function resolveScheduledSlackTarget(task) {
|
|
|
7516
7637
|
}
|
|
7517
7638
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
7518
7639
|
try {
|
|
7519
|
-
const file =
|
|
7640
|
+
const file = join33(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
7520
7641
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
7521
7642
|
const tmp = `${file}.tmp`;
|
|
7522
|
-
|
|
7523
|
-
|
|
7643
|
+
writeFileSync13(tmp, JSON.stringify(marker), "utf8");
|
|
7644
|
+
renameSync7(tmp, file);
|
|
7524
7645
|
} catch (err) {
|
|
7525
7646
|
log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
|
|
7526
7647
|
}
|
|
7527
7648
|
}
|
|
7528
7649
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
7529
|
-
const file =
|
|
7650
|
+
const file = join33(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
7530
7651
|
try {
|
|
7531
|
-
const raw = JSON.parse(
|
|
7652
|
+
const raw = JSON.parse(readFileSync25(file, "utf8"));
|
|
7532
7653
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
7533
7654
|
unlinkSync3(file);
|
|
7534
7655
|
log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
|
|
@@ -7589,8 +7710,8 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt, dura
|
|
|
7589
7710
|
}
|
|
7590
7711
|
try {
|
|
7591
7712
|
const doorbell = directChatDoorbellPath(agentId, homedir14());
|
|
7592
|
-
|
|
7593
|
-
|
|
7713
|
+
mkdirSync9(dirname8(doorbell), { recursive: true });
|
|
7714
|
+
writeFileSync13(doorbell, String(Date.now()));
|
|
7594
7715
|
} catch (err) {
|
|
7595
7716
|
log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
7596
7717
|
}
|
|
@@ -7656,24 +7777,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
7656
7777
|
const assertion = parseDeliverAssertion(rawOutput);
|
|
7657
7778
|
if (!assertion.deliver) {
|
|
7658
7779
|
const trimmed = (rawOutput ?? "").trim();
|
|
7659
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
7780
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash14("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
7660
7781
|
log(`[claude-scheduler] Suppressed by delivery_policy=conditional for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 ${assertion.vacuous ? "deliver marker had a vacuous reason" : "no deliver marker"}; output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
7661
7782
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
7662
7783
|
await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
|
|
7663
7784
|
}
|
|
7664
7785
|
return { ok: true };
|
|
7665
7786
|
}
|
|
7666
|
-
const reasonHash =
|
|
7787
|
+
const reasonHash = createHash14("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
|
|
7667
7788
|
log(`[claude-scheduler] Delivering conditional run for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 agent asserted a concrete trigger (reason_len=${(assertion.reason ?? "").length} reason_hash=${reasonHash})`);
|
|
7668
7789
|
rawOutput = assertion.deliverable;
|
|
7669
7790
|
}
|
|
7670
7791
|
const classification = classifyOutput(rawOutput);
|
|
7671
7792
|
if (classification.action === "suppress") {
|
|
7672
7793
|
const trimmed = (rawOutput ?? "").trim();
|
|
7673
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
7794
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash14("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
7674
7795
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
7675
7796
|
if (classification.suppressedNotes) {
|
|
7676
|
-
const notesHash =
|
|
7797
|
+
const notesHash = createHash14("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
7677
7798
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
7678
7799
|
}
|
|
7679
7800
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -7739,13 +7860,13 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
7739
7860
|
}
|
|
7740
7861
|
|
|
7741
7862
|
// src/lib/manager/scheduler/execution.ts
|
|
7742
|
-
import { createHash as
|
|
7863
|
+
import { createHash as createHash15 } from "crypto";
|
|
7743
7864
|
import { homedir as homedir15 } from "os";
|
|
7744
|
-
import { join as
|
|
7865
|
+
import { join as join35 } from "path";
|
|
7745
7866
|
|
|
7746
7867
|
// src/lib/agent-serving-probe.ts
|
|
7747
|
-
import { readFileSync as
|
|
7748
|
-
import { join as
|
|
7868
|
+
import { readFileSync as readFileSync26, readdirSync as readdirSync7, statSync as statSync7 } from "fs";
|
|
7869
|
+
import { join as join34 } from "path";
|
|
7749
7870
|
var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
|
|
7750
7871
|
function probeRateLimit(args) {
|
|
7751
7872
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
@@ -7754,23 +7875,23 @@ function probeRateLimit(args) {
|
|
|
7754
7875
|
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
7755
7876
|
let entries;
|
|
7756
7877
|
try {
|
|
7757
|
-
entries =
|
|
7878
|
+
entries = readdirSync7(dir);
|
|
7758
7879
|
} catch {
|
|
7759
7880
|
return UNKNOWN_RATE_LIMIT;
|
|
7760
7881
|
}
|
|
7761
7882
|
let newest = UNKNOWN_RATE_LIMIT;
|
|
7762
7883
|
for (const name of entries) {
|
|
7763
7884
|
if (!name.endsWith(".jsonl")) continue;
|
|
7764
|
-
const path =
|
|
7885
|
+
const path = join34(dir, name);
|
|
7765
7886
|
try {
|
|
7766
|
-
const st =
|
|
7887
|
+
const st = statSync7(path);
|
|
7767
7888
|
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
7768
7889
|
} catch {
|
|
7769
7890
|
continue;
|
|
7770
7891
|
}
|
|
7771
7892
|
let content;
|
|
7772
7893
|
try {
|
|
7773
|
-
content =
|
|
7894
|
+
content = readFileSync26(path, "utf-8");
|
|
7774
7895
|
} catch {
|
|
7775
7896
|
continue;
|
|
7776
7897
|
}
|
|
@@ -7832,7 +7953,7 @@ function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
|
|
|
7832
7953
|
|
|
7833
7954
|
// src/lib/manager/scheduler/execution.ts
|
|
7834
7955
|
function claudePidFilePath() {
|
|
7835
|
-
return
|
|
7956
|
+
return join35(homedir15(), ".augmented", "manager-claude-pids.json");
|
|
7836
7957
|
}
|
|
7837
7958
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
7838
7959
|
function registerClaudeSpawn(record) {
|
|
@@ -7852,10 +7973,10 @@ function unregisterClaudeSpawn(pid) {
|
|
|
7852
7973
|
}
|
|
7853
7974
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData, durableScheduledNudge = false) {
|
|
7854
7975
|
const codeName = agent.code_name;
|
|
7855
|
-
const stableTasksHash =
|
|
7856
|
-
const boardHash = boardItems.length > 0 ?
|
|
7976
|
+
const stableTasksHash = createHash15("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
7977
|
+
const boardHash = boardItems.length > 0 ? createHash15("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";
|
|
7857
7978
|
const resolvedModels = resolveModelChain(refreshData);
|
|
7858
|
-
const modelsHash =
|
|
7979
|
+
const modelsHash = createHash15("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
7859
7980
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
7860
7981
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
7861
7982
|
if (combinedHash !== prevHash) {
|
|
@@ -7902,8 +8023,8 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
7902
8023
|
}
|
|
7903
8024
|
|
|
7904
8025
|
// src/lib/occupancy-gate.ts
|
|
7905
|
-
import { closeSync as closeSync2, openSync as openSync2, readdirSync as
|
|
7906
|
-
import { join as
|
|
8026
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync8, readSync as readSync2, statSync as statSync8 } from "fs";
|
|
8027
|
+
import { join as join36 } from "path";
|
|
7907
8028
|
function rostersMeasuredZero(mode, attested, runtimeRunning) {
|
|
7908
8029
|
return mode === "enforce" && attested && runtimeRunning;
|
|
7909
8030
|
}
|
|
@@ -7917,7 +8038,7 @@ var brackets = /* @__PURE__ */ new Map();
|
|
|
7917
8038
|
function readAlignedTail(path, tailBytes, maxAlignBytes) {
|
|
7918
8039
|
let fd = null;
|
|
7919
8040
|
try {
|
|
7920
|
-
const size =
|
|
8041
|
+
const size = statSync8(path).size;
|
|
7921
8042
|
if (size <= 0) return { content: "", complete: true, truncated: false };
|
|
7922
8043
|
fd = openSync2(path, "r");
|
|
7923
8044
|
let readStart = Math.max(0, size - tailBytes);
|
|
@@ -7987,26 +8108,26 @@ function candidateTranscriptPaths(dir) {
|
|
|
7987
8108
|
const paths = [];
|
|
7988
8109
|
let top;
|
|
7989
8110
|
try {
|
|
7990
|
-
top =
|
|
8111
|
+
top = readdirSync8(dir);
|
|
7991
8112
|
} catch {
|
|
7992
8113
|
return { paths, complete: false };
|
|
7993
8114
|
}
|
|
7994
8115
|
let complete = true;
|
|
7995
8116
|
for (const name of top) {
|
|
7996
8117
|
if (name.endsWith(".jsonl")) {
|
|
7997
|
-
paths.push(
|
|
8118
|
+
paths.push(join36(dir, name));
|
|
7998
8119
|
continue;
|
|
7999
8120
|
}
|
|
8000
|
-
const subDir =
|
|
8121
|
+
const subDir = join36(dir, name, "subagents");
|
|
8001
8122
|
let subs;
|
|
8002
8123
|
try {
|
|
8003
|
-
subs =
|
|
8124
|
+
subs = readdirSync8(subDir);
|
|
8004
8125
|
} catch (err) {
|
|
8005
8126
|
if (!isAbsentDirError(err)) complete = false;
|
|
8006
8127
|
continue;
|
|
8007
8128
|
}
|
|
8008
8129
|
for (const sub of subs) {
|
|
8009
|
-
if (sub.endsWith(".jsonl")) paths.push(
|
|
8130
|
+
if (sub.endsWith(".jsonl")) paths.push(join36(subDir, sub));
|
|
8010
8131
|
}
|
|
8011
8132
|
}
|
|
8012
8133
|
return { paths, complete };
|
|
@@ -8061,7 +8182,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
|
|
|
8061
8182
|
for (const path of paths) {
|
|
8062
8183
|
let st;
|
|
8063
8184
|
try {
|
|
8064
|
-
st =
|
|
8185
|
+
st = statSync8(path);
|
|
8065
8186
|
} catch (err) {
|
|
8066
8187
|
if (!isAbsentDirError(err)) complete = false;
|
|
8067
8188
|
continue;
|
|
@@ -8167,7 +8288,7 @@ function qualifyBuckets(buckets, qualifying, mode, nowMs, neighbourhoodMs = DEFA
|
|
|
8167
8288
|
}
|
|
8168
8289
|
|
|
8169
8290
|
// src/lib/pane-occupancy-sampler.ts
|
|
8170
|
-
import { statSync as
|
|
8291
|
+
import { statSync as statSync9 } from "fs";
|
|
8171
8292
|
var SAMPLE_INTERVAL_MS = 1e4;
|
|
8172
8293
|
var IDLE_GAP_MS = 12e4;
|
|
8173
8294
|
var POST_IDLE_CREDIT_MS = 6e4;
|
|
@@ -8181,7 +8302,7 @@ function hasFreshPaneObservation(codeName, nowMs, maxAgeMs = OBSERVATION_FRESH_M
|
|
|
8181
8302
|
}
|
|
8182
8303
|
function paneMtimeMs(codeName) {
|
|
8183
8304
|
try {
|
|
8184
|
-
return
|
|
8305
|
+
return statSync9(paneLogPath(codeName)).mtimeMs;
|
|
8185
8306
|
} catch {
|
|
8186
8307
|
return null;
|
|
8187
8308
|
}
|
|
@@ -8233,7 +8354,7 @@ function stopPaneOccupancySampler() {
|
|
|
8233
8354
|
|
|
8234
8355
|
// src/lib/pid-pressure-sampler.ts
|
|
8235
8356
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
8236
|
-
import { existsSync as
|
|
8357
|
+
import { existsSync as existsSync15, readFileSync as readFileSync27 } from "fs";
|
|
8237
8358
|
var SAMPLE_INTERVAL_MS2 = 3e4;
|
|
8238
8359
|
function warnFraction() {
|
|
8239
8360
|
const raw = Number(process.env.AGT_PID_PRESSURE_WARN_FRACTION);
|
|
@@ -8246,7 +8367,7 @@ function configuredCeiling() {
|
|
|
8246
8367
|
}
|
|
8247
8368
|
function readTextReal(path) {
|
|
8248
8369
|
try {
|
|
8249
|
-
return
|
|
8370
|
+
return readFileSync27(path, "utf-8");
|
|
8250
8371
|
} catch {
|
|
8251
8372
|
return null;
|
|
8252
8373
|
}
|
|
@@ -8255,7 +8376,7 @@ var cgroupDirCache = /* @__PURE__ */ new Map();
|
|
|
8255
8376
|
var resolveRetryAfter = /* @__PURE__ */ new Map();
|
|
8256
8377
|
var RESOLVE_RETRY_BACKOFF_MS = 5 * 6e4;
|
|
8257
8378
|
function resolveCgroupDirReal(codeName, deps = {}) {
|
|
8258
|
-
const exists = deps.exists ??
|
|
8379
|
+
const exists = deps.exists ?? existsSync15;
|
|
8259
8380
|
const inspectId = deps.inspectId ?? inspectContainerId;
|
|
8260
8381
|
const now = deps.now ?? Date.now;
|
|
8261
8382
|
const cached = cgroupDirCache.get(codeName);
|
|
@@ -8373,7 +8494,7 @@ function stopPidPressureSampler() {
|
|
|
8373
8494
|
}
|
|
8374
8495
|
|
|
8375
8496
|
// src/lib/opencode-slack-ingest.ts
|
|
8376
|
-
import { createHash as
|
|
8497
|
+
import { createHash as createHash16 } from "crypto";
|
|
8377
8498
|
|
|
8378
8499
|
// ../../packages/core/dist/channels/slack-rich-text.js
|
|
8379
8500
|
var MAX_DEPTH = 12;
|
|
@@ -9380,7 +9501,7 @@ function startSlackIngest(config2) {
|
|
|
9380
9501
|
// src/lib/opencode-slack-ingest.ts
|
|
9381
9502
|
var ingests = /* @__PURE__ */ new Map();
|
|
9382
9503
|
function fingerprint(params) {
|
|
9383
|
-
return
|
|
9504
|
+
return createHash16("sha256").update(
|
|
9384
9505
|
JSON.stringify({
|
|
9385
9506
|
appToken: params.appToken,
|
|
9386
9507
|
botToken: params.botToken,
|
|
@@ -9461,7 +9582,7 @@ function stopAllOpencodeSlackIngests(log2) {
|
|
|
9461
9582
|
}
|
|
9462
9583
|
|
|
9463
9584
|
// src/lib/manager/opencode-scheduler.ts
|
|
9464
|
-
import { createHash as
|
|
9585
|
+
import { createHash as createHash17 } from "crypto";
|
|
9465
9586
|
var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
|
|
9466
9587
|
var opencodeSchedulerStates = /* @__PURE__ */ new Map();
|
|
9467
9588
|
var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
|
|
@@ -9475,7 +9596,7 @@ function shouldDeliver(task, reply) {
|
|
|
9475
9596
|
}
|
|
9476
9597
|
async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
9477
9598
|
const codeName = agent.code_name;
|
|
9478
|
-
const tasksHash =
|
|
9599
|
+
const tasksHash = createHash17("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
9479
9600
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
9480
9601
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
9481
9602
|
const state10 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
@@ -9553,10 +9674,10 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
9553
9674
|
}
|
|
9554
9675
|
|
|
9555
9676
|
// src/lib/opencode-telegram-ingest.ts
|
|
9556
|
-
import { createHash as
|
|
9557
|
-
import { existsSync as
|
|
9677
|
+
import { createHash as createHash18 } from "crypto";
|
|
9678
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync28, renameSync as renameSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
9558
9679
|
import { randomUUID } from "crypto";
|
|
9559
|
-
import { join as
|
|
9680
|
+
import { join as join37 } from "path";
|
|
9560
9681
|
|
|
9561
9682
|
// src/lib/telegram-ingest.ts
|
|
9562
9683
|
import https2 from "https";
|
|
@@ -10089,7 +10210,7 @@ function anySignal(signals) {
|
|
|
10089
10210
|
// src/lib/opencode-telegram-ingest.ts
|
|
10090
10211
|
var ingests2 = /* @__PURE__ */ new Map();
|
|
10091
10212
|
function fingerprint2(params) {
|
|
10092
|
-
return
|
|
10213
|
+
return createHash18("sha256").update(
|
|
10093
10214
|
JSON.stringify({
|
|
10094
10215
|
botToken: params.botToken,
|
|
10095
10216
|
allowedChats: [...params.allowedChats].sort(),
|
|
@@ -10104,7 +10225,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10104
10225
|
let filePath;
|
|
10105
10226
|
try {
|
|
10106
10227
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
10107
|
-
filePath =
|
|
10228
|
+
filePath = join37(dir, "telegram-getupdates-offset-opencode.json");
|
|
10108
10229
|
} catch {
|
|
10109
10230
|
dir = null;
|
|
10110
10231
|
filePath = null;
|
|
@@ -10113,7 +10234,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10113
10234
|
load() {
|
|
10114
10235
|
if (!filePath) return 0;
|
|
10115
10236
|
try {
|
|
10116
|
-
const parsed = JSON.parse(
|
|
10237
|
+
const parsed = JSON.parse(readFileSync28(filePath, "utf-8"));
|
|
10117
10238
|
if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
|
|
10118
10239
|
log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
|
|
10119
10240
|
return 0;
|
|
@@ -10131,8 +10252,8 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10131
10252
|
if (!filePath || !dir) return;
|
|
10132
10253
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
10133
10254
|
try {
|
|
10134
|
-
|
|
10135
|
-
|
|
10255
|
+
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
10256
|
+
writeFileSync14(
|
|
10136
10257
|
tmpPath,
|
|
10137
10258
|
JSON.stringify({
|
|
10138
10259
|
offset,
|
|
@@ -10142,11 +10263,11 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10142
10263
|
}),
|
|
10143
10264
|
{ mode: 384 }
|
|
10144
10265
|
);
|
|
10145
|
-
|
|
10266
|
+
renameSync8(tmpPath, filePath);
|
|
10146
10267
|
} catch (err) {
|
|
10147
10268
|
log2(`[telegram-ingest:${codeName}] offset persist failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10148
10269
|
try {
|
|
10149
|
-
if (
|
|
10270
|
+
if (existsSync16(tmpPath)) unlinkSync4(tmpPath);
|
|
10150
10271
|
} catch {
|
|
10151
10272
|
}
|
|
10152
10273
|
}
|
|
@@ -10383,24 +10504,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
10383
10504
|
}
|
|
10384
10505
|
|
|
10385
10506
|
// src/lib/restart-flags.ts
|
|
10386
|
-
import { existsSync as
|
|
10507
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync11, readdirSync as readdirSync9, readFileSync as readFileSync29, renameSync as renameSync9, rmSync as rmSync6, writeFileSync as writeFileSync15 } from "fs";
|
|
10387
10508
|
import { homedir as homedir16 } from "os";
|
|
10388
|
-
import { join as
|
|
10509
|
+
import { join as join38 } from "path";
|
|
10389
10510
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
10390
10511
|
function restartFlagsDir() {
|
|
10391
|
-
return
|
|
10512
|
+
return join38(homedir16(), ".augmented", "restart-flags");
|
|
10392
10513
|
}
|
|
10393
10514
|
function flagPath(codeName) {
|
|
10394
|
-
return
|
|
10515
|
+
return join38(restartFlagsDir(), `${codeName}.flag`);
|
|
10395
10516
|
}
|
|
10396
10517
|
function readRestartFlags() {
|
|
10397
10518
|
const dir = restartFlagsDir();
|
|
10398
|
-
if (!
|
|
10519
|
+
if (!existsSync17(dir)) return [];
|
|
10399
10520
|
const out = [];
|
|
10400
|
-
for (const entry of
|
|
10521
|
+
for (const entry of readdirSync9(dir)) {
|
|
10401
10522
|
if (!entry.endsWith(".flag")) continue;
|
|
10402
10523
|
try {
|
|
10403
|
-
const raw =
|
|
10524
|
+
const raw = readFileSync29(join38(dir, entry), "utf8");
|
|
10404
10525
|
const parsed = JSON.parse(raw);
|
|
10405
10526
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
10406
10527
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -10418,8 +10539,8 @@ function readRestartFlags() {
|
|
|
10418
10539
|
}
|
|
10419
10540
|
function deleteRestartFlag(codeName) {
|
|
10420
10541
|
const path = flagPath(codeName);
|
|
10421
|
-
if (
|
|
10422
|
-
|
|
10542
|
+
if (existsSync17(path)) {
|
|
10543
|
+
rmSync6(path, { force: true });
|
|
10423
10544
|
}
|
|
10424
10545
|
}
|
|
10425
10546
|
|
|
@@ -10518,8 +10639,8 @@ async function sendError(flag, opts, text) {
|
|
|
10518
10639
|
}
|
|
10519
10640
|
|
|
10520
10641
|
// src/lib/restart-context.ts
|
|
10521
|
-
import { readdirSync as
|
|
10522
|
-
import { dirname as dirname9, join as
|
|
10642
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync16, mkdirSync as mkdirSync12, unlinkSync as unlinkSync5 } from "fs";
|
|
10643
|
+
import { dirname as dirname9, join as join39 } from "path";
|
|
10523
10644
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
10524
10645
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
10525
10646
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -10531,10 +10652,10 @@ function augmentedAgentDir(codeName) {
|
|
|
10531
10652
|
return dirname9(getProjectDir(codeName));
|
|
10532
10653
|
}
|
|
10533
10654
|
function slackPendingInboundDir(codeName) {
|
|
10534
|
-
return
|
|
10655
|
+
return join39(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
10535
10656
|
}
|
|
10536
10657
|
function slackRestartContextDir(codeName) {
|
|
10537
|
-
return
|
|
10658
|
+
return join39(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
10538
10659
|
}
|
|
10539
10660
|
function sanitizeTopic(raw) {
|
|
10540
10661
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -10569,14 +10690,14 @@ function computeRestartContextHints(markers, allTurns, nowMs, reconstruct = reco
|
|
|
10569
10690
|
}
|
|
10570
10691
|
function safeReaddir(dir) {
|
|
10571
10692
|
try {
|
|
10572
|
-
return
|
|
10693
|
+
return readdirSync10(dir);
|
|
10573
10694
|
} catch {
|
|
10574
10695
|
return [];
|
|
10575
10696
|
}
|
|
10576
10697
|
}
|
|
10577
10698
|
function readStrandedMarker(path) {
|
|
10578
10699
|
try {
|
|
10579
|
-
const parsed = JSON.parse(
|
|
10700
|
+
const parsed = JSON.parse(readFileSync30(path, "utf-8"));
|
|
10580
10701
|
if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
|
|
10581
10702
|
return { channel: parsed.channel, thread_ts: parsed.thread_ts };
|
|
10582
10703
|
}
|
|
@@ -10585,8 +10706,8 @@ function readStrandedMarker(path) {
|
|
|
10585
10706
|
return null;
|
|
10586
10707
|
}
|
|
10587
10708
|
function writeHintFile(path, dir, hint) {
|
|
10588
|
-
|
|
10589
|
-
|
|
10709
|
+
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
10710
|
+
writeFileSync16(path, JSON.stringify(hint), { mode: 384 });
|
|
10590
10711
|
}
|
|
10591
10712
|
function pruneHintsExcept(codeName, freshFilenames) {
|
|
10592
10713
|
const ctxDir = slackRestartContextDir(codeName);
|
|
@@ -10594,7 +10715,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
10594
10715
|
if (!filename.endsWith(".json")) continue;
|
|
10595
10716
|
if (freshFilenames.has(filename)) continue;
|
|
10596
10717
|
try {
|
|
10597
|
-
unlinkSync5(
|
|
10718
|
+
unlinkSync5(join39(ctxDir, filename));
|
|
10598
10719
|
} catch {
|
|
10599
10720
|
}
|
|
10600
10721
|
}
|
|
@@ -10615,7 +10736,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
10615
10736
|
}
|
|
10616
10737
|
const markers = [];
|
|
10617
10738
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
10618
|
-
const parsed = readStrandedMarker(
|
|
10739
|
+
const parsed = readStrandedMarker(join39(markerDir, filename));
|
|
10619
10740
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
10620
10741
|
}
|
|
10621
10742
|
if (markers.length === 0) {
|
|
@@ -10629,7 +10750,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
10629
10750
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
10630
10751
|
for (const { filename, hint } of hints) {
|
|
10631
10752
|
try {
|
|
10632
|
-
writeHintFile(
|
|
10753
|
+
writeHintFile(join39(ctxDir, filename), ctxDir, hint);
|
|
10633
10754
|
freshFilenames.add(filename);
|
|
10634
10755
|
} catch (err) {
|
|
10635
10756
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -12163,7 +12284,7 @@ function performLazyDayRolloverReset(codeName, agentTimezone) {
|
|
|
12163
12284
|
}
|
|
12164
12285
|
function paneLogAgeSecondsFor(codeName) {
|
|
12165
12286
|
try {
|
|
12166
|
-
const mtimeMs =
|
|
12287
|
+
const mtimeMs = statSync10(paneLogPath(codeName)).mtimeMs;
|
|
12167
12288
|
return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
|
|
12168
12289
|
} catch (err) {
|
|
12169
12290
|
if (err?.code === "ENOENT") return null;
|
|
@@ -12313,15 +12434,15 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
12313
12434
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
12314
12435
|
function projectMcpHash(_codeName, projectDir) {
|
|
12315
12436
|
try {
|
|
12316
|
-
const raw =
|
|
12317
|
-
return
|
|
12437
|
+
const raw = readFileSync31(join40(projectDir, ".mcp.json"), "utf-8");
|
|
12438
|
+
return createHash19("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
12318
12439
|
} catch {
|
|
12319
12440
|
return null;
|
|
12320
12441
|
}
|
|
12321
12442
|
}
|
|
12322
12443
|
function projectMcpKeys(_codeName, projectDir) {
|
|
12323
12444
|
try {
|
|
12324
|
-
const raw =
|
|
12445
|
+
const raw = readFileSync31(join40(projectDir, ".mcp.json"), "utf-8");
|
|
12325
12446
|
const parsed = JSON.parse(raw);
|
|
12326
12447
|
const servers = parsed.mcpServers;
|
|
12327
12448
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -12339,7 +12460,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
12339
12460
|
else runningMcpServerKeys.delete(codeName);
|
|
12340
12461
|
let launchStructure = null;
|
|
12341
12462
|
try {
|
|
12342
|
-
const raw =
|
|
12463
|
+
const raw = readFileSync31(join40(projectDir, ".mcp.json"), "utf-8");
|
|
12343
12464
|
launchStructure = managedMcpStructureHashFromFile(
|
|
12344
12465
|
JSON.parse(raw),
|
|
12345
12466
|
isManagedMcpServerKey
|
|
@@ -12465,7 +12586,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
12465
12586
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
12466
12587
|
let mcpJsonForRebind = null;
|
|
12467
12588
|
try {
|
|
12468
|
-
mcpJsonForRebind = JSON.parse(
|
|
12589
|
+
mcpJsonForRebind = JSON.parse(readFileSync31(join40(projectDir, ".mcp.json"), "utf-8"));
|
|
12469
12590
|
} catch {
|
|
12470
12591
|
mcpJsonForRebind = null;
|
|
12471
12592
|
}
|
|
@@ -12613,7 +12734,7 @@ function shouldInjectChannelSecrets(agentId) {
|
|
|
12613
12734
|
function projectChannelSecretHash(projectDir) {
|
|
12614
12735
|
try {
|
|
12615
12736
|
const entries = parseEnvIntegrations(
|
|
12616
|
-
|
|
12737
|
+
readFileSync31(join40(projectDir, ".env.integrations"), "utf-8")
|
|
12617
12738
|
);
|
|
12618
12739
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
12619
12740
|
} catch {
|
|
@@ -12711,7 +12832,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
12711
12832
|
var lastVersionCheckAt = 0;
|
|
12712
12833
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
12713
12834
|
var lastResponsivenessProbeAt = 0;
|
|
12714
|
-
var agtCliVersion = true ? "0.28.
|
|
12835
|
+
var agtCliVersion = true ? "0.28.722" : "dev";
|
|
12715
12836
|
function resolveBrewPath(execFileSync3) {
|
|
12716
12837
|
try {
|
|
12717
12838
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -12724,7 +12845,7 @@ function resolveBrewPath(execFileSync3) {
|
|
|
12724
12845
|
"/usr/local/bin/brew"
|
|
12725
12846
|
];
|
|
12726
12847
|
for (const path of fallbacks) {
|
|
12727
|
-
if (
|
|
12848
|
+
if (existsSync18(path)) return path;
|
|
12728
12849
|
}
|
|
12729
12850
|
return null;
|
|
12730
12851
|
}
|
|
@@ -12734,7 +12855,7 @@ function claudeBinaryInstalled(execFileSync3) {
|
|
|
12734
12855
|
"/opt/homebrew/bin/claude",
|
|
12735
12856
|
"/usr/local/bin/claude"
|
|
12736
12857
|
];
|
|
12737
|
-
if (canonical.some((path) =>
|
|
12858
|
+
if (canonical.some((path) => existsSync18(path))) return true;
|
|
12738
12859
|
try {
|
|
12739
12860
|
execFileSync3("which", ["claude"], { timeout: 5e3 });
|
|
12740
12861
|
return true;
|
|
@@ -13044,8 +13165,8 @@ var MANAGED_SETTINGS_KEYS = ["channelsEnabled", "enableAllProjectMcpServers"];
|
|
|
13044
13165
|
function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
13045
13166
|
try {
|
|
13046
13167
|
let settings = {};
|
|
13047
|
-
if (
|
|
13048
|
-
const raw =
|
|
13168
|
+
if (existsSync18(path)) {
|
|
13169
|
+
const raw = readFileSync31(path, "utf-8").trim();
|
|
13049
13170
|
if (raw) {
|
|
13050
13171
|
let parsed;
|
|
13051
13172
|
try {
|
|
@@ -13062,8 +13183,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
13062
13183
|
const missing = MANAGED_SETTINGS_KEYS.filter((key) => settings[key] !== true);
|
|
13063
13184
|
if (missing.length === 0) return "ok";
|
|
13064
13185
|
for (const key of missing) settings[key] = true;
|
|
13065
|
-
|
|
13066
|
-
|
|
13186
|
+
mkdirSync13(dirname10(path), { recursive: true });
|
|
13187
|
+
writeFileSync17(path, `${JSON.stringify(settings, null, 2)}
|
|
13067
13188
|
`);
|
|
13068
13189
|
log(`[managed-settings] set ${missing.map((k) => `${k}:true`).join(", ")} in ${path} (ENG-5786 unblocks Claude Code channels; ENG-9223 pre-approves project MCP servers so a headless session never freezes on the trust prompt)`);
|
|
13069
13190
|
return "ok";
|
|
@@ -13101,7 +13222,7 @@ async function ensureOpencodeBinary() {
|
|
|
13101
13222
|
try {
|
|
13102
13223
|
const prefix = execFileSync3("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
13103
13224
|
if (prefix) {
|
|
13104
|
-
const npmBin =
|
|
13225
|
+
const npmBin = join40(prefix, "bin");
|
|
13105
13226
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
13106
13227
|
if (!current.includes(npmBin)) {
|
|
13107
13228
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -13162,7 +13283,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
13162
13283
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
13163
13284
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
13164
13285
|
}
|
|
13165
|
-
if (
|
|
13286
|
+
if (existsSync18("/home/linuxbrew/.linuxbrew/bin/claude")) {
|
|
13166
13287
|
log("Claude Code installed successfully");
|
|
13167
13288
|
} else {
|
|
13168
13289
|
log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
|
|
@@ -13218,7 +13339,7 @@ ${r.stderr}`;
|
|
|
13218
13339
|
}
|
|
13219
13340
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
13220
13341
|
function selfUpdateAppliedMarkerPath() {
|
|
13221
|
-
return
|
|
13342
|
+
return join40(homedir17(), ".augmented", ".last-self-update-applied");
|
|
13222
13343
|
}
|
|
13223
13344
|
var selfUpdateUpToDateLogged = false;
|
|
13224
13345
|
var selfUpdatePinnedLogged = false;
|
|
@@ -13269,7 +13390,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
13269
13390
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
13270
13391
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
13271
13392
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
13272
|
-
const markerPath =
|
|
13393
|
+
const markerPath = join40(homedir17(), ".augmented", ".last-update-check");
|
|
13273
13394
|
if (!force) {
|
|
13274
13395
|
try {
|
|
13275
13396
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -13762,14 +13883,14 @@ async function checkClaudeAuth() {
|
|
|
13762
13883
|
}
|
|
13763
13884
|
var evalEmptyMcpConfigPath = null;
|
|
13764
13885
|
function ensureEvalEmptyMcpConfig() {
|
|
13765
|
-
if (evalEmptyMcpConfigPath &&
|
|
13766
|
-
const dir =
|
|
13886
|
+
if (evalEmptyMcpConfigPath && existsSync18(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
13887
|
+
const dir = join40(homedir17(), ".augmented");
|
|
13767
13888
|
try {
|
|
13768
|
-
|
|
13889
|
+
mkdirSync13(dir, { recursive: true });
|
|
13769
13890
|
} catch {
|
|
13770
13891
|
}
|
|
13771
|
-
const p =
|
|
13772
|
-
|
|
13892
|
+
const p = join40(dir, ".eval-empty-mcp.json");
|
|
13893
|
+
writeFileSync17(p, JSON.stringify({ mcpServers: {} }));
|
|
13773
13894
|
evalEmptyMcpConfigPath = p;
|
|
13774
13895
|
return p;
|
|
13775
13896
|
}
|
|
@@ -13863,10 +13984,10 @@ function resolveConversationEvalBackend() {
|
|
|
13863
13984
|
return conversationEvalBackend;
|
|
13864
13985
|
}
|
|
13865
13986
|
function getStateFile() {
|
|
13866
|
-
return
|
|
13987
|
+
return join40(config?.configDir ?? join40(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
13867
13988
|
}
|
|
13868
13989
|
function channelHashCacheDir() {
|
|
13869
|
-
return config?.configDir ??
|
|
13990
|
+
return config?.configDir ?? join40(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
13870
13991
|
}
|
|
13871
13992
|
function loadChannelHashCache2() {
|
|
13872
13993
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -14071,7 +14192,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
14071
14192
|
var _channelQuarantineStore = null;
|
|
14072
14193
|
function channelQuarantineStore() {
|
|
14073
14194
|
if (!_channelQuarantineStore) {
|
|
14074
|
-
const dir = config?.configDir ??
|
|
14195
|
+
const dir = config?.configDir ?? join40(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
14075
14196
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
14076
14197
|
}
|
|
14077
14198
|
return _channelQuarantineStore;
|
|
@@ -14087,12 +14208,12 @@ function claudeMdSizeFor(codeName) {
|
|
|
14087
14208
|
}
|
|
14088
14209
|
function forwardedToolsFor(codeName) {
|
|
14089
14210
|
if (!config?.configDir) return null;
|
|
14090
|
-
return readForwardedToolsReport(
|
|
14211
|
+
return readForwardedToolsReport(join40(config.configDir, codeName));
|
|
14091
14212
|
}
|
|
14092
14213
|
var _hostFlagStore = null;
|
|
14093
14214
|
function hostFlagStore() {
|
|
14094
14215
|
if (!_hostFlagStore) {
|
|
14095
|
-
const dir = config?.configDir ??
|
|
14216
|
+
const dir = config?.configDir ?? join40(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
14096
14217
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
14097
14218
|
}
|
|
14098
14219
|
return _hostFlagStore;
|
|
@@ -14165,13 +14286,13 @@ function parseSkillFrontmatter(content) {
|
|
|
14165
14286
|
return out;
|
|
14166
14287
|
}
|
|
14167
14288
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
14168
|
-
const { readdirSync:
|
|
14169
|
-
const skillsDir =
|
|
14170
|
-
const claudeMdPath =
|
|
14289
|
+
const { readdirSync: readdirSync12, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync18 } = await import("fs");
|
|
14290
|
+
const skillsDir = join40(configDir, codeName, "project", ".claude", "skills");
|
|
14291
|
+
const claudeMdPath = join40(configDir, codeName, "project", "CLAUDE.md");
|
|
14171
14292
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
14172
14293
|
const entries = [];
|
|
14173
|
-
for (const dir of
|
|
14174
|
-
const skillFile =
|
|
14294
|
+
for (const dir of readdirSync12(skillsDir).sort()) {
|
|
14295
|
+
const skillFile = join40(skillsDir, dir, "SKILL.md");
|
|
14175
14296
|
if (!ex(skillFile)) continue;
|
|
14176
14297
|
try {
|
|
14177
14298
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -14215,7 +14336,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
14215
14336
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
14216
14337
|
}
|
|
14217
14338
|
if (next !== current) {
|
|
14218
|
-
|
|
14339
|
+
writeFileSync18(claudeMdPath, next, "utf-8");
|
|
14219
14340
|
log2(
|
|
14220
14341
|
injectSkillList ? `Refreshed skills index in CLAUDE.md for '${codeName}' (${entries.length} skills)` : `Refreshed CLAUDE.md managed block for '${codeName}' (skill list suppressed by claude-md-skills-index=false; ${entries.length} skills on disk)`
|
|
14221
14342
|
);
|
|
@@ -14386,7 +14507,7 @@ async function pollCycleInner() {
|
|
|
14386
14507
|
claudeAuth = await detectClaudeAuth();
|
|
14387
14508
|
} catch (err) {
|
|
14388
14509
|
const errText = err instanceof Error ? err.message : String(err);
|
|
14389
|
-
const errId =
|
|
14510
|
+
const errId = createHash19("sha256").update(errText).digest("hex").slice(0, 12);
|
|
14390
14511
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
14391
14512
|
}
|
|
14392
14513
|
const hostHasClaudeCode = state8.agents.some(
|
|
@@ -14724,13 +14845,13 @@ async function pollCycleInner() {
|
|
|
14724
14845
|
);
|
|
14725
14846
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
14726
14847
|
try {
|
|
14727
|
-
const paneTail =
|
|
14848
|
+
const paneTail = readFileSync31(paneLogPath(codeName), "utf8").slice(-65536);
|
|
14728
14849
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
14729
14850
|
if (transient) {
|
|
14730
|
-
const wedgeHome =
|
|
14731
|
-
if (
|
|
14851
|
+
const wedgeHome = join40(homedir17(), ".augmented", codeName);
|
|
14852
|
+
if (existsSync18(wedgeHome)) {
|
|
14732
14853
|
atomicWriteFileSync(
|
|
14733
|
-
|
|
14854
|
+
join40(wedgeHome, "watchdog-give-up.json"),
|
|
14734
14855
|
JSON.stringify({
|
|
14735
14856
|
gave_up_at: wedgeNow.toISOString(),
|
|
14736
14857
|
reason: "transient_overload"
|
|
@@ -15046,7 +15167,7 @@ async function pollCycleInner() {
|
|
|
15046
15167
|
`[drain-flush] FAILED for '${prev.codeName}': ${err.message} \u2014 proceeding to teardown; this session was NOT shipped (ENG-9491)`
|
|
15047
15168
|
);
|
|
15048
15169
|
}
|
|
15049
|
-
const agentDir =
|
|
15170
|
+
const agentDir = join40(adapter.getAgentDir(prev.codeName), "provision");
|
|
15050
15171
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
15051
15172
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
15052
15173
|
}
|
|
@@ -15133,10 +15254,10 @@ async function pollCycleInner() {
|
|
|
15133
15254
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
15134
15255
|
// the watchdog, never fails the poll cycle.
|
|
15135
15256
|
signalGiveUp: (codeName) => {
|
|
15136
|
-
const dir =
|
|
15137
|
-
if (!
|
|
15257
|
+
const dir = join40(homedir17(), ".augmented", codeName);
|
|
15258
|
+
if (!existsSync18(dir)) return;
|
|
15138
15259
|
atomicWriteFileSync(
|
|
15139
|
-
|
|
15260
|
+
join40(dir, "watchdog-give-up.json"),
|
|
15140
15261
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
15141
15262
|
);
|
|
15142
15263
|
},
|
|
@@ -15155,9 +15276,9 @@ async function pollCycleInner() {
|
|
|
15155
15276
|
// parser elsewhere can only reconstruct an hour (ENG-8901).
|
|
15156
15277
|
signalUsageLimit: (codeName, resetsHint) => {
|
|
15157
15278
|
const dir = getFramework("claude-code").getAgentDir(codeName);
|
|
15158
|
-
if (!
|
|
15279
|
+
if (!existsSync18(dir)) return;
|
|
15159
15280
|
atomicWriteFileSync(
|
|
15160
|
-
|
|
15281
|
+
join40(dir, "watchdog-give-up.json"),
|
|
15161
15282
|
JSON.stringify({
|
|
15162
15283
|
gave_up_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15163
15284
|
reason: "usage_limit",
|
|
@@ -15419,7 +15540,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15419
15540
|
}
|
|
15420
15541
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15421
15542
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
15422
|
-
let agentDir =
|
|
15543
|
+
let agentDir = join40(adapter.getAgentDir(agent.code_name), "provision");
|
|
15423
15544
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
15424
15545
|
forgetChannelSyncState(agent.agent_id);
|
|
15425
15546
|
if (previousKnownStatus !== agent.status) {
|
|
@@ -15460,7 +15581,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15460
15581
|
const residuals = {
|
|
15461
15582
|
gatewayRunning: false,
|
|
15462
15583
|
portAllocated: false,
|
|
15463
|
-
provisionDirExists:
|
|
15584
|
+
provisionDirExists: existsSync18(agentDir)
|
|
15464
15585
|
};
|
|
15465
15586
|
if (!hasRevokedResiduals(residuals)) {
|
|
15466
15587
|
agentStates.push({
|
|
@@ -15552,12 +15673,16 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15552
15673
|
// ENG-9585: ask for hashes instead of knowledge bodies. An API build that
|
|
15553
15674
|
// predates the manifest ignores this and answers with `knowledge` as
|
|
15554
15675
|
// before, which the resolution below handles without a version check.
|
|
15555
|
-
knowledge_manifest: true
|
|
15676
|
+
knowledge_manifest: true,
|
|
15677
|
+
// ENG-9585: the same for the two root-skill lanes. A separate flag
|
|
15678
|
+
// because the two shipped in different CLI versions — an API that
|
|
15679
|
+
// understands one and not the other must still be able to answer.
|
|
15680
|
+
skills_manifest: true
|
|
15556
15681
|
});
|
|
15557
15682
|
if (refreshData.knowledge_manifest) {
|
|
15558
15683
|
const resolved = await resolveKnowledgeFromManifest({
|
|
15559
15684
|
manifest: refreshData.knowledge_manifest,
|
|
15560
|
-
cacheDir:
|
|
15685
|
+
cacheDir: join40(config.configDir, "_knowledge"),
|
|
15561
15686
|
delivery: refreshData.agent?.knowledge_delivery ?? "both",
|
|
15562
15687
|
fetchContents: async (hashes) => {
|
|
15563
15688
|
const res = await api.post(
|
|
@@ -15570,6 +15695,25 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15570
15695
|
});
|
|
15571
15696
|
refreshData.knowledge = resolved;
|
|
15572
15697
|
}
|
|
15698
|
+
if (refreshData.global_skills_manifest || refreshData.shared_skills_manifest) {
|
|
15699
|
+
const resolvedSkills = await resolveSkillsFromManifest({
|
|
15700
|
+
globals: refreshData.global_skills_manifest ?? [],
|
|
15701
|
+
shared: refreshData.shared_skills_manifest ?? [],
|
|
15702
|
+
cacheDir: join40(config.configDir, "_skills"),
|
|
15703
|
+
fetchContents: async (hashes) => {
|
|
15704
|
+
const res = await api.post(
|
|
15705
|
+
"/host/skills/contents",
|
|
15706
|
+
{ agent_id: agent.agent_id, hashes }
|
|
15707
|
+
);
|
|
15708
|
+
return res.contents ?? [];
|
|
15709
|
+
},
|
|
15710
|
+
log
|
|
15711
|
+
});
|
|
15712
|
+
if (resolvedSkills) {
|
|
15713
|
+
refreshData.global_skills = resolvedSkills.globals;
|
|
15714
|
+
refreshData.shared_skills = resolvedSkills.shared;
|
|
15715
|
+
}
|
|
15716
|
+
}
|
|
15573
15717
|
} catch (err) {
|
|
15574
15718
|
log(`Refresh failed for '${agent.code_name}': ${err.message}`);
|
|
15575
15719
|
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
@@ -15614,7 +15758,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15614
15758
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
15615
15759
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
15616
15760
|
const frameworkAdapter = getFramework(frameworkId);
|
|
15617
|
-
agentDir =
|
|
15761
|
+
agentDir = join40(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
15618
15762
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
15619
15763
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
15620
15764
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -15670,9 +15814,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15670
15814
|
try {
|
|
15671
15815
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter, renderIntegrationsSection);
|
|
15672
15816
|
const changedFiles = [];
|
|
15673
|
-
|
|
15817
|
+
mkdirSync13(agentDir, { recursive: true });
|
|
15674
15818
|
for (const artifact of artifacts) {
|
|
15675
|
-
const filePath =
|
|
15819
|
+
const filePath = join40(agentDir, artifact.relativePath);
|
|
15676
15820
|
let existingHash;
|
|
15677
15821
|
let newHash;
|
|
15678
15822
|
let writeContent = artifact.content;
|
|
@@ -15691,8 +15835,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15691
15835
|
};
|
|
15692
15836
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
15693
15837
|
try {
|
|
15694
|
-
const projectClaudeMd =
|
|
15695
|
-
const existing =
|
|
15838
|
+
const projectClaudeMd = join40(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
15839
|
+
const existing = readFileSync31(projectClaudeMd, "utf-8");
|
|
15696
15840
|
existingHash = sha256(stripDynamicSections(existing));
|
|
15697
15841
|
} catch {
|
|
15698
15842
|
existingHash = null;
|
|
@@ -15710,7 +15854,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15710
15854
|
const generatorKeys = Object.keys(generatorServers);
|
|
15711
15855
|
let existingRaw = "";
|
|
15712
15856
|
try {
|
|
15713
|
-
existingRaw =
|
|
15857
|
+
existingRaw = readFileSync31(filePath, "utf-8");
|
|
15714
15858
|
} catch {
|
|
15715
15859
|
}
|
|
15716
15860
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -15726,7 +15870,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15726
15870
|
} else if (artifact.relativePath === "opencode.json") {
|
|
15727
15871
|
let existingRaw = null;
|
|
15728
15872
|
try {
|
|
15729
|
-
existingRaw =
|
|
15873
|
+
existingRaw = readFileSync31(filePath, "utf-8");
|
|
15730
15874
|
} catch {
|
|
15731
15875
|
}
|
|
15732
15876
|
const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
|
|
@@ -15742,26 +15886,26 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15742
15886
|
}
|
|
15743
15887
|
}
|
|
15744
15888
|
if (changedFiles.length > 0) {
|
|
15745
|
-
const isFirst = !
|
|
15889
|
+
const isFirst = !existsSync18(join40(agentDir, "CHARTER.md"));
|
|
15746
15890
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
15747
15891
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
15748
15892
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
15749
15893
|
for (const file of changedFiles) {
|
|
15750
|
-
const filePath =
|
|
15751
|
-
|
|
15894
|
+
const filePath = join40(agentDir, file.relativePath);
|
|
15895
|
+
mkdirSync13(dirname10(filePath), { recursive: true });
|
|
15752
15896
|
if (file.relativePath === ".mcp.json") {
|
|
15753
15897
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
15754
15898
|
} else {
|
|
15755
|
-
|
|
15899
|
+
writeFileSync17(filePath, file.content);
|
|
15756
15900
|
}
|
|
15757
15901
|
}
|
|
15758
15902
|
try {
|
|
15759
|
-
const provSkillsDir =
|
|
15760
|
-
if (
|
|
15761
|
-
for (const folder of
|
|
15903
|
+
const provSkillsDir = join40(agentDir, ".claude", "skills");
|
|
15904
|
+
if (existsSync18(provSkillsDir)) {
|
|
15905
|
+
for (const folder of readdirSync11(provSkillsDir)) {
|
|
15762
15906
|
if (folder.startsWith("knowledge-")) {
|
|
15763
15907
|
try {
|
|
15764
|
-
|
|
15908
|
+
rmSync7(join40(provSkillsDir, folder), { recursive: true });
|
|
15765
15909
|
} catch {
|
|
15766
15910
|
}
|
|
15767
15911
|
}
|
|
@@ -15774,7 +15918,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15774
15918
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
15775
15919
|
const hashes = /* @__PURE__ */ new Map();
|
|
15776
15920
|
for (const file of trackedFiles2) {
|
|
15777
|
-
const h = hashFile(
|
|
15921
|
+
const h = hashFile(join40(agentDir, file));
|
|
15778
15922
|
if (h) hashes.set(file, h);
|
|
15779
15923
|
}
|
|
15780
15924
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -15792,14 +15936,14 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15792
15936
|
}
|
|
15793
15937
|
if (Array.isArray(refreshData.workflows)) {
|
|
15794
15938
|
try {
|
|
15795
|
-
const provWorkflowsDir =
|
|
15796
|
-
if (
|
|
15939
|
+
const provWorkflowsDir = join40(agentDir, ".claude", "workflows");
|
|
15940
|
+
if (existsSync18(provWorkflowsDir)) {
|
|
15797
15941
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
15798
|
-
for (const file of
|
|
15942
|
+
for (const file of readdirSync11(provWorkflowsDir)) {
|
|
15799
15943
|
if (!file.endsWith(".js")) continue;
|
|
15800
15944
|
if (expected.has(file)) continue;
|
|
15801
15945
|
try {
|
|
15802
|
-
|
|
15946
|
+
rmSync7(join40(provWorkflowsDir, file));
|
|
15803
15947
|
} catch {
|
|
15804
15948
|
}
|
|
15805
15949
|
}
|
|
@@ -15878,10 +16022,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15878
16022
|
}
|
|
15879
16023
|
let lastDriftCheckAt = now;
|
|
15880
16024
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
15881
|
-
if (written &&
|
|
16025
|
+
if (written && existsSync18(agentDir)) {
|
|
15882
16026
|
const driftedFiles = [];
|
|
15883
16027
|
for (const [file, expectedHash] of written) {
|
|
15884
|
-
const localHash = hashFile(
|
|
16028
|
+
const localHash = hashFile(join40(agentDir, file));
|
|
15885
16029
|
if (localHash && localHash !== expectedHash) {
|
|
15886
16030
|
driftedFiles.push(file);
|
|
15887
16031
|
}
|
|
@@ -15892,7 +16036,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15892
16036
|
try {
|
|
15893
16037
|
const localHashes = {};
|
|
15894
16038
|
for (const file of driftedFiles) {
|
|
15895
|
-
localHashes[file] = hashFile(
|
|
16039
|
+
localHashes[file] = hashFile(join40(agentDir, file));
|
|
15896
16040
|
}
|
|
15897
16041
|
await api.post("/host/drift", {
|
|
15898
16042
|
agent_id: agent.agent_id,
|
|
@@ -16160,15 +16304,15 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16160
16304
|
const addedChannels = [...restartDecision.added];
|
|
16161
16305
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
16162
16306
|
try {
|
|
16163
|
-
const agentAugmentedDir =
|
|
16164
|
-
|
|
16307
|
+
const agentAugmentedDir = join40(homedir17(), ".augmented", agent.code_name);
|
|
16308
|
+
mkdirSync13(agentAugmentedDir, { recursive: true });
|
|
16165
16309
|
const markerJson = JSON.stringify({
|
|
16166
16310
|
version: 1,
|
|
16167
16311
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16168
16312
|
added: addedChannels
|
|
16169
16313
|
});
|
|
16170
16314
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
16171
|
-
atomicWriteFileSync(
|
|
16315
|
+
atomicWriteFileSync(join40(agentAugmentedDir, file), markerJson);
|
|
16172
16316
|
}
|
|
16173
16317
|
} catch (err) {
|
|
16174
16318
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -16244,7 +16388,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16244
16388
|
const behaviourSubset = extractMsTeamsBehaviourSubset(
|
|
16245
16389
|
msteamsEntry?.config
|
|
16246
16390
|
);
|
|
16247
|
-
const behaviourHash =
|
|
16391
|
+
const behaviourHash = createHash19("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
|
|
16248
16392
|
const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
|
|
16249
16393
|
const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
|
|
16250
16394
|
const behaviourDecision = decideSenderPolicyRestart({
|
|
@@ -16300,7 +16444,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16300
16444
|
const slackBehaviourSubset = extractSlackBehaviourSubset(
|
|
16301
16445
|
slackEntry?.config
|
|
16302
16446
|
);
|
|
16303
|
-
const slackBehaviourHash =
|
|
16447
|
+
const slackBehaviourHash = createHash19("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
|
|
16304
16448
|
const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
|
|
16305
16449
|
const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
|
|
16306
16450
|
const slackBehaviourDecision = decideSenderPolicyRestart({
|
|
@@ -16357,24 +16501,24 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16357
16501
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
16358
16502
|
try {
|
|
16359
16503
|
const agentProvisionDir = agentDir;
|
|
16360
|
-
const projectDir =
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
const provisionMcpPath =
|
|
16364
|
-
const projectMcpPath =
|
|
16504
|
+
const projectDir = join40(homedir17(), ".augmented", agent.code_name, "project");
|
|
16505
|
+
mkdirSync13(agentProvisionDir, { recursive: true });
|
|
16506
|
+
mkdirSync13(projectDir, { recursive: true });
|
|
16507
|
+
const provisionMcpPath = join40(agentProvisionDir, ".mcp.json");
|
|
16508
|
+
const projectMcpPath = join40(projectDir, ".mcp.json");
|
|
16365
16509
|
let mcpConfig = { mcpServers: {} };
|
|
16366
16510
|
try {
|
|
16367
|
-
mcpConfig = JSON.parse(
|
|
16511
|
+
mcpConfig = JSON.parse(readFileSync31(provisionMcpPath, "utf-8"));
|
|
16368
16512
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
16369
16513
|
} catch {
|
|
16370
16514
|
}
|
|
16371
|
-
const localDirectChatChannel =
|
|
16515
|
+
const localDirectChatChannel = join40(homedir17(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
16372
16516
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
16373
16517
|
const directChatTz = (() => {
|
|
16374
16518
|
const tz = directChatTeamSettings?.["timezone"];
|
|
16375
16519
|
return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
|
|
16376
16520
|
})();
|
|
16377
|
-
if (
|
|
16521
|
+
if (existsSync18(localDirectChatChannel)) {
|
|
16378
16522
|
const directChatEnv = {
|
|
16379
16523
|
AGT_HOST: requireHost(),
|
|
16380
16524
|
// ENG-5901 Track D: templated — the manager exports the real
|
|
@@ -16394,7 +16538,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16394
16538
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
16395
16539
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
16396
16540
|
// so it byte-matches the broker readers' path.
|
|
16397
|
-
AGT_TURN_INITIATOR_FILE:
|
|
16541
|
+
AGT_TURN_INITIATOR_FILE: join40(
|
|
16398
16542
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
16399
16543
|
".current-turn-initiator.json"
|
|
16400
16544
|
)
|
|
@@ -16414,10 +16558,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16414
16558
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
16415
16559
|
}
|
|
16416
16560
|
}
|
|
16417
|
-
const staleChannelsPath =
|
|
16418
|
-
if (
|
|
16561
|
+
const staleChannelsPath = join40(projectDir, ".mcp-channels.json");
|
|
16562
|
+
if (existsSync18(staleChannelsPath)) {
|
|
16419
16563
|
try {
|
|
16420
|
-
|
|
16564
|
+
rmSync7(staleChannelsPath, { force: true });
|
|
16421
16565
|
} catch {
|
|
16422
16566
|
}
|
|
16423
16567
|
}
|
|
@@ -16504,7 +16648,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16504
16648
|
}
|
|
16505
16649
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
16506
16650
|
try {
|
|
16507
|
-
const probeProjectDir =
|
|
16651
|
+
const probeProjectDir = join40(homedir17(), ".augmented", agent.code_name, "project");
|
|
16508
16652
|
let probeSet = integrations;
|
|
16509
16653
|
try {
|
|
16510
16654
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -16550,7 +16694,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16550
16694
|
const forceDue = attemptsLeft > 0;
|
|
16551
16695
|
let probeRan = false;
|
|
16552
16696
|
try {
|
|
16553
|
-
const probeProjectDir =
|
|
16697
|
+
const probeProjectDir = join40(homedir17(), ".augmented", agent.code_name, "project");
|
|
16554
16698
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
16555
16699
|
} catch (err) {
|
|
16556
16700
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -16627,11 +16771,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16627
16771
|
const intHash = computeIntegrationsHash(integrations);
|
|
16628
16772
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
16629
16773
|
if (intHash !== prevIntHash) {
|
|
16630
|
-
const projectDir =
|
|
16631
|
-
const envIntPath =
|
|
16774
|
+
const projectDir = join40(homedir17(), ".augmented", agent.code_name, "project");
|
|
16775
|
+
const envIntPath = join40(projectDir, ".env.integrations");
|
|
16632
16776
|
let preWriteEnv;
|
|
16633
16777
|
try {
|
|
16634
|
-
preWriteEnv =
|
|
16778
|
+
preWriteEnv = readFileSync31(envIntPath, "utf-8");
|
|
16635
16779
|
} catch {
|
|
16636
16780
|
preWriteEnv = void 0;
|
|
16637
16781
|
}
|
|
@@ -16650,9 +16794,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16650
16794
|
}
|
|
16651
16795
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
16652
16796
|
try {
|
|
16653
|
-
const projectMcpPath =
|
|
16654
|
-
const postWriteEnv =
|
|
16655
|
-
const mcpContent =
|
|
16797
|
+
const projectMcpPath = join40(projectDir, ".mcp.json");
|
|
16798
|
+
const postWriteEnv = readFileSync31(envIntPath, "utf-8");
|
|
16799
|
+
const mcpContent = readFileSync31(projectMcpPath, "utf-8");
|
|
16656
16800
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
16657
16801
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
16658
16802
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -16742,10 +16886,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16742
16886
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
16743
16887
|
}
|
|
16744
16888
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
16745
|
-
const headersHash =
|
|
16889
|
+
const headersHash = createHash19("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
16746
16890
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
16747
16891
|
}).join("\n");
|
|
16748
|
-
const mcpHash =
|
|
16892
|
+
const mcpHash = createHash19("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
16749
16893
|
const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
|
|
16750
16894
|
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
16751
16895
|
const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
|
|
@@ -16760,7 +16904,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16760
16904
|
if (mcpHash !== prevMcpHash) {
|
|
16761
16905
|
for (const e of desiredEntries) {
|
|
16762
16906
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
16763
|
-
const urlHash =
|
|
16907
|
+
const urlHash = createHash19("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
16764
16908
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
16765
16909
|
}
|
|
16766
16910
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.readMcpServers) {
|
|
@@ -16842,7 +16986,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16842
16986
|
}
|
|
16843
16987
|
const freshData = await api.post("/host/refresh", {
|
|
16844
16988
|
agent_id: agent.agent_id,
|
|
16845
|
-
knowledge_manifest: true
|
|
16989
|
+
knowledge_manifest: true,
|
|
16990
|
+
// Only `scheduled_tasks` is read here, so ask for the manifest shape on
|
|
16991
|
+
// both lanes — nothing in this branch consumes a skill body, and the
|
|
16992
|
+
// skill lanes are the largest part of the payload being discarded.
|
|
16993
|
+
skills_manifest: true
|
|
16846
16994
|
});
|
|
16847
16995
|
tasks = freshData.scheduled_tasks ?? tasks;
|
|
16848
16996
|
}
|
|
@@ -16866,7 +17014,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16866
17014
|
if (frameworkAdapter.installSkillFiles) {
|
|
16867
17015
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
16868
17016
|
const installedIntegrationSkills = [];
|
|
16869
|
-
const { createHash:
|
|
17017
|
+
const { createHash: createHash20 } = await import("crypto");
|
|
16870
17018
|
const refreshAny = refreshData;
|
|
16871
17019
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
16872
17020
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -16895,7 +17043,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16895
17043
|
)
|
|
16896
17044
|
}));
|
|
16897
17045
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
16898
|
-
const contentHash =
|
|
17046
|
+
const contentHash = createHash20("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
16899
17047
|
if (!shouldWriteIntegrationSkill(
|
|
16900
17048
|
agentState.knownSkillHashes,
|
|
16901
17049
|
agent.agent_id,
|
|
@@ -16918,23 +17066,23 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16918
17066
|
}
|
|
16919
17067
|
}
|
|
16920
17068
|
try {
|
|
16921
|
-
const { readdirSync:
|
|
17069
|
+
const { readdirSync: readdirSync12, rmSync: rmSync8 } = await import("fs");
|
|
16922
17070
|
const { homedir: homedir18 } = await import("os");
|
|
16923
17071
|
const frameworkId2 = frameworkAdapter.id;
|
|
16924
17072
|
const candidateSkillDirs = [
|
|
16925
17073
|
// Claude Code — framework runtime tree
|
|
16926
|
-
|
|
17074
|
+
join40(homedir18(), ".augmented", agent.code_name, "skills"),
|
|
16927
17075
|
// Claude Code — project tree
|
|
16928
|
-
|
|
17076
|
+
join40(homedir18(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
16929
17077
|
// Defensive: legacy provision-side path, not currently an
|
|
16930
17078
|
// install target but cheap to sweep.
|
|
16931
|
-
|
|
17079
|
+
join40(agentDir, ".claude", "skills")
|
|
16932
17080
|
];
|
|
16933
|
-
const existingDirs = candidateSkillDirs.filter((d) =>
|
|
17081
|
+
const existingDirs = candidateSkillDirs.filter((d) => existsSync18(d));
|
|
16934
17082
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
16935
17083
|
for (const dir of existingDirs) {
|
|
16936
17084
|
try {
|
|
16937
|
-
for (const entry of
|
|
17085
|
+
for (const entry of readdirSync12(dir)) {
|
|
16938
17086
|
if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
|
|
16939
17087
|
discoveredEntries.add(entry);
|
|
16940
17088
|
}
|
|
@@ -16949,8 +17097,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16949
17097
|
entry,
|
|
16950
17098
|
dirs: existingDirs,
|
|
16951
17099
|
removeDir: (p) => {
|
|
16952
|
-
if (
|
|
16953
|
-
|
|
17100
|
+
if (existsSync18(p)) {
|
|
17101
|
+
rmSync8(p, { recursive: true, force: true });
|
|
16954
17102
|
}
|
|
16955
17103
|
}
|
|
16956
17104
|
});
|
|
@@ -16969,7 +17117,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16969
17117
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
16970
17118
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
16971
17119
|
const manifestPath = managedSkillManifestPath(
|
|
16972
|
-
|
|
17120
|
+
join40(homedir17(), ".augmented", agent.code_name)
|
|
16973
17121
|
);
|
|
16974
17122
|
const prevIds = /* @__PURE__ */ new Set([
|
|
16975
17123
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -16978,7 +17126,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16978
17126
|
const plan = planGlobalSkillSync(
|
|
16979
17127
|
[...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
|
|
16980
17128
|
prevIds,
|
|
16981
|
-
(content) =>
|
|
17129
|
+
(content) => createHash20("sha256").update(content).digest("hex").slice(0, 12),
|
|
16982
17130
|
(skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
|
|
16983
17131
|
{ desiredResolved }
|
|
16984
17132
|
);
|
|
@@ -16989,16 +17137,16 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16989
17137
|
}
|
|
16990
17138
|
if (plan.removes.length) {
|
|
16991
17139
|
const globalSkillDirs = [
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
|
|
17140
|
+
join40(homedir17(), ".augmented", agent.code_name, "skills"),
|
|
17141
|
+
join40(homedir17(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
17142
|
+
join40(agentDir, ".claude", "skills")
|
|
16995
17143
|
];
|
|
16996
17144
|
for (const id of plan.removes) {
|
|
16997
17145
|
let prunedAny = false;
|
|
16998
17146
|
for (const dir of globalSkillDirs) {
|
|
16999
|
-
const p =
|
|
17000
|
-
if (
|
|
17001
|
-
|
|
17147
|
+
const p = join40(dir, id);
|
|
17148
|
+
if (existsSync18(p) && existsSync18(join40(p, "SKILL.md"))) {
|
|
17149
|
+
rmSync7(p, { recursive: true, force: true });
|
|
17002
17150
|
prunedAny = true;
|
|
17003
17151
|
}
|
|
17004
17152
|
}
|
|
@@ -17029,7 +17177,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17029
17177
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
17030
17178
|
if (!slug) continue;
|
|
17031
17179
|
try {
|
|
17032
|
-
const scriptHash =
|
|
17180
|
+
const scriptHash = createHash20("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
17033
17181
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
17034
17182
|
if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
17035
17183
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -17044,9 +17192,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17044
17192
|
} else if (result.timedOut) {
|
|
17045
17193
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
17046
17194
|
} else {
|
|
17047
|
-
const stderrHash =
|
|
17195
|
+
const stderrHash = createHash20("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
17048
17196
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
17049
|
-
const missingCmdHash = missingCmd ?
|
|
17197
|
+
const missingCmdHash = missingCmd ? createHash20("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
17050
17198
|
log(
|
|
17051
17199
|
`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}]`
|
|
17052
17200
|
);
|
|
@@ -17239,8 +17387,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17239
17387
|
const sess = getSessionState(agent.code_name);
|
|
17240
17388
|
let mcpJsonParsed = null;
|
|
17241
17389
|
try {
|
|
17242
|
-
const mcpPath =
|
|
17243
|
-
mcpJsonParsed = JSON.parse(
|
|
17390
|
+
const mcpPath = join40(getProjectDir(agent.code_name), ".mcp.json");
|
|
17391
|
+
mcpJsonParsed = JSON.parse(readFileSync31(mcpPath, "utf-8"));
|
|
17244
17392
|
} catch {
|
|
17245
17393
|
}
|
|
17246
17394
|
reapMissingMcpSessions({
|
|
@@ -17623,7 +17771,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17623
17771
|
freshDoneIds.add(item.id);
|
|
17624
17772
|
}
|
|
17625
17773
|
} catch (err) {
|
|
17626
|
-
const errId =
|
|
17774
|
+
const errId = createHash19("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
|
|
17627
17775
|
log(`Reap API error for item_id=${item.id} error_id=${errId}`);
|
|
17628
17776
|
}
|
|
17629
17777
|
if (reapAction === "dead_letter") {
|
|
@@ -17671,10 +17819,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
17671
17819
|
}
|
|
17672
17820
|
}
|
|
17673
17821
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
17674
|
-
if (trackedFiles.length > 0 &&
|
|
17822
|
+
if (trackedFiles.length > 0 && existsSync18(agentDir)) {
|
|
17675
17823
|
const hashes = /* @__PURE__ */ new Map();
|
|
17676
17824
|
for (const file of trackedFiles) {
|
|
17677
|
-
const h = hashFile(
|
|
17825
|
+
const h = hashFile(join40(agentDir, file));
|
|
17678
17826
|
if (h) hashes.set(file, h);
|
|
17679
17827
|
}
|
|
17680
17828
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -17689,7 +17837,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
17689
17837
|
refreshData.agent.onboarding_state
|
|
17690
17838
|
);
|
|
17691
17839
|
const obStep = obState.step;
|
|
17692
|
-
const markerPath =
|
|
17840
|
+
const markerPath = join40(homedir17(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
17693
17841
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
17694
17842
|
const obContactRaw = refreshData.agent.manager_last_contacted_at;
|
|
17695
17843
|
const obContact = typeof obContactRaw === "string" && obContactRaw ? obContactRaw : null;
|
|
@@ -17791,7 +17939,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
17791
17939
|
}
|
|
17792
17940
|
stopOpencodeSlackIngest(codeName, log);
|
|
17793
17941
|
stopOpencodeTelegramIngest(codeName, log);
|
|
17794
|
-
const opencodeProjectDir =
|
|
17942
|
+
const opencodeProjectDir = join40(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
17795
17943
|
const serveEnv = {
|
|
17796
17944
|
AGT_HOST: requireHost(),
|
|
17797
17945
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -17846,8 +17994,8 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
17846
17994
|
});
|
|
17847
17995
|
}
|
|
17848
17996
|
const projectDir = getProjectDir(codeName);
|
|
17849
|
-
const mcpConfigPath =
|
|
17850
|
-
const claudeMdPath =
|
|
17997
|
+
const mcpConfigPath = join40(projectDir, ".mcp.json");
|
|
17998
|
+
const claudeMdPath = join40(projectDir, "CLAUDE.md");
|
|
17851
17999
|
if (restartBreaker.isTripped(codeName)) {
|
|
17852
18000
|
const trip = restartBreaker.getTrip(codeName);
|
|
17853
18001
|
return {
|
|
@@ -18096,7 +18244,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
18096
18244
|
const ctx = getLastFailureContext(codeName);
|
|
18097
18245
|
const recovery = prepareForRespawn(codeName);
|
|
18098
18246
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
18099
|
-
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${
|
|
18247
|
+
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash19("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
|
|
18100
18248
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
18101
18249
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
18102
18250
|
log(
|
|
@@ -18110,7 +18258,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash18("sha256")
|
|
|
18110
18258
|
);
|
|
18111
18259
|
getHostId().then((hostId) => {
|
|
18112
18260
|
if (!hostId) return;
|
|
18113
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
18261
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash19("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
18114
18262
|
return api.post("/host/events", {
|
|
18115
18263
|
host_id: hostId,
|
|
18116
18264
|
agent_code_name: codeName,
|
|
@@ -18307,7 +18455,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash18("sha256")
|
|
|
18307
18455
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
18308
18456
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
18309
18457
|
}
|
|
18310
|
-
const stableTasksHash =
|
|
18458
|
+
const stableTasksHash = createHash19("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
18311
18459
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
18312
18460
|
if (stableTasksHash !== prevHash) {
|
|
18313
18461
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
@@ -18781,7 +18929,7 @@ function ensureRealtimeKanbanStarted(agentStates) {
|
|
|
18781
18929
|
);
|
|
18782
18930
|
}
|
|
18783
18931
|
}).catch((err) => {
|
|
18784
|
-
const errId =
|
|
18932
|
+
const errId = createHash19("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
|
|
18785
18933
|
log(
|
|
18786
18934
|
`[realtime] Work trigger enqueue threw for '${agent.codeName}' item_id=${item.id} error_id=${errId} \u2014 hybrid nudge will retry`
|
|
18787
18935
|
);
|
|
@@ -19071,8 +19219,8 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
19071
19219
|
if (useDoorbell) {
|
|
19072
19220
|
try {
|
|
19073
19221
|
const doorbell = directChatDoorbellPath(agent.agentId, homedir17());
|
|
19074
|
-
|
|
19075
|
-
|
|
19222
|
+
mkdirSync13(dirname10(doorbell), { recursive: true });
|
|
19223
|
+
writeFileSync17(doorbell, String(Date.now()));
|
|
19076
19224
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
19077
19225
|
return;
|
|
19078
19226
|
} catch (err) {
|
|
@@ -19200,8 +19348,8 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
19200
19348
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
19201
19349
|
try {
|
|
19202
19350
|
const doorbell = directChatDoorbellPath(agentId, homedir17());
|
|
19203
|
-
|
|
19204
|
-
|
|
19351
|
+
mkdirSync13(dirname10(doorbell), { recursive: true });
|
|
19352
|
+
writeFileSync17(doorbell, String(Date.now()));
|
|
19205
19353
|
} catch (err) {
|
|
19206
19354
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
19207
19355
|
}
|
|
@@ -19530,17 +19678,17 @@ var lastDownloadHash = /* @__PURE__ */ new Map();
|
|
|
19530
19678
|
var lastLocalFileHash = /* @__PURE__ */ new Map();
|
|
19531
19679
|
var memoryManifests = /* @__PURE__ */ new Map();
|
|
19532
19680
|
function memoryRetirementDir(configDir, codeName) {
|
|
19533
|
-
return
|
|
19681
|
+
return join40(configDir, "_memory-retirement", codeName);
|
|
19534
19682
|
}
|
|
19535
19683
|
function memoryManifestPath(configDir, codeName) {
|
|
19536
|
-
return
|
|
19684
|
+
return join40(memoryRetirementDir(configDir, codeName), "manifest.json");
|
|
19537
19685
|
}
|
|
19538
19686
|
function loadMemoryManifest(agentId, configDir, codeName) {
|
|
19539
19687
|
const cached = memoryManifests.get(agentId);
|
|
19540
19688
|
if (cached) return cached;
|
|
19541
19689
|
let manifest = {};
|
|
19542
19690
|
try {
|
|
19543
|
-
const raw =
|
|
19691
|
+
const raw = readFileSync31(memoryManifestPath(configDir, codeName), "utf-8");
|
|
19544
19692
|
const parsed = JSON.parse(raw);
|
|
19545
19693
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
19546
19694
|
for (const [name, entry] of Object.entries(parsed)) {
|
|
@@ -19560,15 +19708,15 @@ function saveMemoryManifest(agentId, configDir, codeName) {
|
|
|
19560
19708
|
if (!manifest) return;
|
|
19561
19709
|
try {
|
|
19562
19710
|
const path = memoryManifestPath(configDir, codeName);
|
|
19563
|
-
|
|
19711
|
+
mkdirSync13(memoryRetirementDir(configDir, codeName), { recursive: true });
|
|
19564
19712
|
const tmp = `${path}.tmp`;
|
|
19565
|
-
|
|
19566
|
-
|
|
19713
|
+
writeFileSync17(tmp, JSON.stringify(manifest, null, 2));
|
|
19714
|
+
renameSync10(tmp, path);
|
|
19567
19715
|
} catch {
|
|
19568
19716
|
}
|
|
19569
19717
|
}
|
|
19570
19718
|
function retiredMemoryDir(configDir, codeName) {
|
|
19571
|
-
return
|
|
19719
|
+
return join40(memoryRetirementDir(configDir, codeName), "retired");
|
|
19572
19720
|
}
|
|
19573
19721
|
var RETIRED_MEMORY_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
19574
19722
|
var lastRetirementReport = /* @__PURE__ */ new Map();
|
|
@@ -19646,15 +19794,15 @@ function applyMemoryTombstones(opts) {
|
|
|
19646
19794
|
log2(`[memory-retire] ${agent.code_name}: KEPT '${tomb.name}' \u2014 no write record, not ours to remove`);
|
|
19647
19795
|
continue;
|
|
19648
19796
|
}
|
|
19649
|
-
const filePath =
|
|
19650
|
-
if (!
|
|
19797
|
+
const filePath = join40(memoryDir, entry.file);
|
|
19798
|
+
if (!existsSync18(filePath)) {
|
|
19651
19799
|
outcomes.already_gone++;
|
|
19652
19800
|
delete manifest[tomb.name];
|
|
19653
19801
|
manifestDirty = true;
|
|
19654
19802
|
continue;
|
|
19655
19803
|
}
|
|
19656
19804
|
try {
|
|
19657
|
-
const actual =
|
|
19805
|
+
const actual = createHash19("sha256").update(readFileSync31(filePath)).digest("hex");
|
|
19658
19806
|
if (actual !== entry.sha) {
|
|
19659
19807
|
outcomes.kept_modified++;
|
|
19660
19808
|
outcomes.unapplied.push({ name: tomb.name, reason: "kept_modified" });
|
|
@@ -19664,16 +19812,16 @@ function applyMemoryTombstones(opts) {
|
|
|
19664
19812
|
continue;
|
|
19665
19813
|
}
|
|
19666
19814
|
const destDir = retiredMemoryDir(configDir, agent.code_name);
|
|
19667
|
-
|
|
19815
|
+
mkdirSync13(destDir, { recursive: true });
|
|
19668
19816
|
const stamp = Date.now();
|
|
19669
|
-
let dest =
|
|
19670
|
-
for (let n = 1;
|
|
19671
|
-
dest =
|
|
19817
|
+
let dest = join40(destDir, `${entry.file}.${stamp}.retired`);
|
|
19818
|
+
for (let n = 1; existsSync18(dest); n++) {
|
|
19819
|
+
dest = join40(destDir, `${entry.file}.${stamp}-${n}.retired`);
|
|
19672
19820
|
}
|
|
19673
|
-
|
|
19821
|
+
renameSync10(filePath, dest);
|
|
19674
19822
|
try {
|
|
19675
19823
|
const now = Date.now() / 1e3;
|
|
19676
|
-
|
|
19824
|
+
utimesSync3(dest, now, now);
|
|
19677
19825
|
} catch {
|
|
19678
19826
|
}
|
|
19679
19827
|
delete manifest[tomb.name];
|
|
@@ -19701,15 +19849,15 @@ function applyMemoryTombstones(opts) {
|
|
|
19701
19849
|
}
|
|
19702
19850
|
function reapRetiredMemories(configDir, codeName, log2) {
|
|
19703
19851
|
const dir = retiredMemoryDir(configDir, codeName);
|
|
19704
|
-
if (!
|
|
19852
|
+
if (!existsSync18(dir)) return;
|
|
19705
19853
|
const cutoff = Date.now() - RETIRED_MEMORY_TTL_MS;
|
|
19706
19854
|
let reaped = 0;
|
|
19707
19855
|
try {
|
|
19708
|
-
for (const file of
|
|
19856
|
+
for (const file of readdirSync11(dir)) {
|
|
19709
19857
|
if (!file.endsWith(".retired")) continue;
|
|
19710
|
-
const path =
|
|
19858
|
+
const path = join40(dir, file);
|
|
19711
19859
|
try {
|
|
19712
|
-
if (
|
|
19860
|
+
if (statSync10(path).mtimeMs < cutoff) {
|
|
19713
19861
|
unlinkSync6(path);
|
|
19714
19862
|
reaped++;
|
|
19715
19863
|
}
|
|
@@ -19722,8 +19870,8 @@ function reapRetiredMemories(configDir, codeName, log2) {
|
|
|
19722
19870
|
if (reaped > 0) log2(`[memory-retire] ${codeName}: reaped ${reaped} retired memory file(s) past TTL`);
|
|
19723
19871
|
}
|
|
19724
19872
|
async function syncMemories(agent, configDir, log2) {
|
|
19725
|
-
const projectDir =
|
|
19726
|
-
const memoryDir =
|
|
19873
|
+
const projectDir = join40(configDir, agent.code_name, "project");
|
|
19874
|
+
const memoryDir = join40(projectDir, "memory");
|
|
19727
19875
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
19728
19876
|
if (isFreshSync) {
|
|
19729
19877
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -19747,15 +19895,15 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19747
19895
|
}
|
|
19748
19896
|
pendingFreshMemorySync.delete(agent.agent_id);
|
|
19749
19897
|
}
|
|
19750
|
-
if (
|
|
19898
|
+
if (existsSync18(memoryDir)) {
|
|
19751
19899
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
19752
19900
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
19753
19901
|
const changedMemories = [];
|
|
19754
|
-
for (const file of
|
|
19902
|
+
for (const file of readdirSync11(memoryDir)) {
|
|
19755
19903
|
if (!file.endsWith(".md")) continue;
|
|
19756
19904
|
try {
|
|
19757
|
-
const raw =
|
|
19758
|
-
const fileHash =
|
|
19905
|
+
const raw = readFileSync31(join40(memoryDir, file), "utf-8");
|
|
19906
|
+
const fileHash = createHash19("sha256").update(raw).digest("hex").slice(0, 16);
|
|
19759
19907
|
currentHashes.set(file, fileHash);
|
|
19760
19908
|
if (prevHashes.get(file) === fileHash) continue;
|
|
19761
19909
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -19779,7 +19927,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19779
19927
|
} catch (err) {
|
|
19780
19928
|
for (const mem of changedMemories) {
|
|
19781
19929
|
for (const [file] of currentHashes) {
|
|
19782
|
-
const parsed = parseMemoryFile(
|
|
19930
|
+
const parsed = parseMemoryFile(readFileSync31(join40(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
19783
19931
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
19784
19932
|
}
|
|
19785
19933
|
}
|
|
@@ -19805,8 +19953,8 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19805
19953
|
}
|
|
19806
19954
|
}
|
|
19807
19955
|
async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
19808
|
-
const localFiles =
|
|
19809
|
-
const localListHash =
|
|
19956
|
+
const localFiles = existsSync18(memoryDir) ? readdirSync11(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
19957
|
+
const localListHash = createHash19("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
19810
19958
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
19811
19959
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
19812
19960
|
try {
|
|
@@ -19814,14 +19962,14 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
19814
19962
|
agent_id: agent.agent_id
|
|
19815
19963
|
});
|
|
19816
19964
|
const tombstones = Array.isArray(dbMemories.tombstones) ? dbMemories.tombstones : null;
|
|
19817
|
-
const responseHash =
|
|
19965
|
+
const responseHash = createHash19("sha256").update(JSON.stringify({ m: dbMemories.memories ?? [], t: tombstones })).digest("hex").slice(0, 16);
|
|
19818
19966
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
19819
19967
|
return { status: "skipped", tombstones, truncated: dbMemories.tombstones_truncated === true };
|
|
19820
19968
|
}
|
|
19821
19969
|
lastDownloadHash.set(agent.agent_id, responseHash);
|
|
19822
19970
|
lastLocalFileHash.set(agent.agent_id, localListHash);
|
|
19823
19971
|
if (dbMemories.memories?.length) {
|
|
19824
|
-
|
|
19972
|
+
mkdirSync13(memoryDir, { recursive: true });
|
|
19825
19973
|
const manifest = loadMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19826
19974
|
let written = 0;
|
|
19827
19975
|
let overwritten = 0;
|
|
@@ -19830,7 +19978,7 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
19830
19978
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
19831
19979
|
const slug = rawSlug || `memory-${i}`;
|
|
19832
19980
|
const fileName = `${slug}.md`;
|
|
19833
|
-
const filePath =
|
|
19981
|
+
const filePath = join40(memoryDir, fileName);
|
|
19834
19982
|
const desired = `---
|
|
19835
19983
|
name: ${JSON.stringify(mem.name)}
|
|
19836
19984
|
type: ${mem.type}
|
|
@@ -19840,17 +19988,17 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
|
|
|
19840
19988
|
${mem.content}
|
|
19841
19989
|
`;
|
|
19842
19990
|
const record = () => {
|
|
19843
|
-
const sha =
|
|
19991
|
+
const sha = createHash19("sha256").update(desired).digest("hex");
|
|
19844
19992
|
const prev = manifest[mem.name];
|
|
19845
19993
|
if (prev?.file === fileName && prev.sha === sha) return false;
|
|
19846
19994
|
manifest[mem.name] = { file: fileName, sha };
|
|
19847
19995
|
return true;
|
|
19848
19996
|
};
|
|
19849
19997
|
let manifestDirty = false;
|
|
19850
|
-
if (
|
|
19998
|
+
if (existsSync18(filePath)) {
|
|
19851
19999
|
let existing = "";
|
|
19852
20000
|
try {
|
|
19853
|
-
existing =
|
|
20001
|
+
existing = readFileSync31(filePath, "utf-8");
|
|
19854
20002
|
} catch {
|
|
19855
20003
|
}
|
|
19856
20004
|
if (existing === desired) {
|
|
@@ -19858,18 +20006,18 @@ ${mem.content}
|
|
|
19858
20006
|
if (manifestDirty) saveMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19859
20007
|
continue;
|
|
19860
20008
|
}
|
|
19861
|
-
|
|
20009
|
+
writeFileSync17(filePath, desired);
|
|
19862
20010
|
overwritten++;
|
|
19863
20011
|
} else {
|
|
19864
|
-
|
|
20012
|
+
writeFileSync17(filePath, desired);
|
|
19865
20013
|
written++;
|
|
19866
20014
|
}
|
|
19867
20015
|
if (record()) manifestDirty = true;
|
|
19868
20016
|
if (manifestDirty) saveMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19869
20017
|
}
|
|
19870
20018
|
if (written > 0 || overwritten > 0) {
|
|
19871
|
-
const updatedFiles =
|
|
19872
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
20019
|
+
const updatedFiles = readdirSync11(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
20020
|
+
lastLocalFileHash.set(agent.agent_id, createHash19("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
19873
20021
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
19874
20022
|
}
|
|
19875
20023
|
}
|
|
@@ -19880,9 +20028,9 @@ ${mem.content}
|
|
|
19880
20028
|
}
|
|
19881
20029
|
}
|
|
19882
20030
|
async function cleanupAgentFiles(codeName, agentDir) {
|
|
19883
|
-
if (
|
|
20031
|
+
if (existsSync18(agentDir)) {
|
|
19884
20032
|
try {
|
|
19885
|
-
|
|
20033
|
+
rmSync7(agentDir, { recursive: true, force: true });
|
|
19886
20034
|
log(`Removed provision directory for '${codeName}'`);
|
|
19887
20035
|
} catch (err) {
|
|
19888
20036
|
log(`Failed to remove provision dir for '${codeName}': ${err.message}`);
|
|
@@ -20150,8 +20298,8 @@ function startManager(opts) {
|
|
|
20150
20298
|
config = opts;
|
|
20151
20299
|
try {
|
|
20152
20300
|
const stateFile = getStateFile();
|
|
20153
|
-
if (
|
|
20154
|
-
const raw =
|
|
20301
|
+
if (existsSync18(stateFile)) {
|
|
20302
|
+
const raw = readFileSync31(stateFile, "utf-8");
|
|
20155
20303
|
const parsed = JSON.parse(raw);
|
|
20156
20304
|
if (Array.isArray(parsed.agents)) {
|
|
20157
20305
|
state8.agents = parsed.agents;
|
|
@@ -20178,7 +20326,7 @@ function startManager(opts) {
|
|
|
20178
20326
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
20179
20327
|
}
|
|
20180
20328
|
log(
|
|
20181
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
20329
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join40(homedir17(), ".augmented", "manager.log")}`
|
|
20182
20330
|
);
|
|
20183
20331
|
deployMcpAssets();
|
|
20184
20332
|
reapOrphanChannelMcps({ log });
|
|
@@ -20207,7 +20355,7 @@ async function reapOrphanedClaudePids() {
|
|
|
20207
20355
|
const looksLikeClaude = (pid) => {
|
|
20208
20356
|
if (process.platform !== "linux") return true;
|
|
20209
20357
|
try {
|
|
20210
|
-
const comm =
|
|
20358
|
+
const comm = readFileSync31(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
20211
20359
|
return comm.includes("claude");
|
|
20212
20360
|
} catch {
|
|
20213
20361
|
return false;
|
|
@@ -20304,14 +20452,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
20304
20452
|
}
|
|
20305
20453
|
}
|
|
20306
20454
|
function deployMcpAssets() {
|
|
20307
|
-
const targetDir =
|
|
20308
|
-
|
|
20455
|
+
const targetDir = join40(homedir17(), ".augmented", "_mcp");
|
|
20456
|
+
mkdirSync13(targetDir, { recursive: true });
|
|
20309
20457
|
const moduleDir = dirname10(fileURLToPath(import.meta.url));
|
|
20310
20458
|
let mcpSourceDir = "";
|
|
20311
20459
|
let dir = moduleDir;
|
|
20312
20460
|
for (let i = 0; i < 6; i++) {
|
|
20313
|
-
const candidate =
|
|
20314
|
-
if (
|
|
20461
|
+
const candidate = join40(dir, "dist", "mcp");
|
|
20462
|
+
if (existsSync18(join40(candidate, "index.js"))) {
|
|
20315
20463
|
mcpSourceDir = candidate;
|
|
20316
20464
|
break;
|
|
20317
20465
|
}
|
|
@@ -20328,8 +20476,8 @@ function deployMcpAssets() {
|
|
|
20328
20476
|
const failedFiles = [];
|
|
20329
20477
|
const fileHash = (p) => {
|
|
20330
20478
|
try {
|
|
20331
|
-
if (!
|
|
20332
|
-
return
|
|
20479
|
+
if (!existsSync18(p)) return null;
|
|
20480
|
+
return createHash19("sha256").update(readFileSync31(p)).digest("hex");
|
|
20333
20481
|
} catch {
|
|
20334
20482
|
return null;
|
|
20335
20483
|
}
|
|
@@ -20400,9 +20548,9 @@ function deployMcpAssets() {
|
|
|
20400
20548
|
// needs restarting to pick up a token rotation.
|
|
20401
20549
|
"xero.js"
|
|
20402
20550
|
]) {
|
|
20403
|
-
const src =
|
|
20404
|
-
const dst =
|
|
20405
|
-
if (!
|
|
20551
|
+
const src = join40(mcpSourceDir, file);
|
|
20552
|
+
const dst = join40(targetDir, file);
|
|
20553
|
+
if (!existsSync18(src)) continue;
|
|
20406
20554
|
attemptedFiles.push(file);
|
|
20407
20555
|
const before = fileHash(dst);
|
|
20408
20556
|
try {
|
|
@@ -20427,23 +20575,23 @@ function deployMcpAssets() {
|
|
|
20427
20575
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
20428
20576
|
restartRunningChannelMcps(changedBasenames);
|
|
20429
20577
|
}
|
|
20430
|
-
const localMcpPath =
|
|
20578
|
+
const localMcpPath = join40(targetDir, "index.js");
|
|
20431
20579
|
try {
|
|
20432
|
-
const agentsDir =
|
|
20433
|
-
if (
|
|
20434
|
-
for (const entry of
|
|
20580
|
+
const agentsDir = join40(homedir17(), ".augmented", "agents");
|
|
20581
|
+
if (existsSync18(agentsDir)) {
|
|
20582
|
+
for (const entry of readdirSync11(agentsDir, { withFileTypes: true })) {
|
|
20435
20583
|
if (!entry.isDirectory()) continue;
|
|
20436
20584
|
for (const subdir of ["provision", "project"]) {
|
|
20437
|
-
const mcpJsonPath =
|
|
20585
|
+
const mcpJsonPath = join40(agentsDir, entry.name, subdir, ".mcp.json");
|
|
20438
20586
|
try {
|
|
20439
|
-
const raw =
|
|
20587
|
+
const raw = readFileSync31(mcpJsonPath, "utf-8");
|
|
20440
20588
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
20441
20589
|
const mcpConfig = JSON.parse(raw);
|
|
20442
20590
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
20443
20591
|
if (!augServer) continue;
|
|
20444
20592
|
augServer.command = "node";
|
|
20445
20593
|
augServer.args = [localMcpPath];
|
|
20446
|
-
|
|
20594
|
+
writeFileSync17(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
20447
20595
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
20448
20596
|
} catch {
|
|
20449
20597
|
}
|