@integrity-labs/agt-cli 0.28.716 → 0.28.717
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 +5 -5
- package/dist/{chunk-ILDRNSOB.js → chunk-JN4D7534.js} +2 -2
- package/dist/{chunk-LHYYO4NY.js → chunk-KVR5KNED.js} +119 -1
- package/dist/chunk-KVR5KNED.js.map +1 -0
- package/dist/{chunk-OOYUWMTR.js → chunk-XSBRGOGL.js} +4 -4
- package/dist/{claude-pair-runtime-JK7GQU25.js → claude-pair-runtime-KWBCSCZO.js} +2 -2
- package/dist/lib/manager-worker.js +470 -344
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +118 -0
- package/dist/mcp/index.js +118 -0
- package/dist/mcp/origami.js +118 -0
- package/dist/mcp/slack-channel.js +118 -0
- package/dist/mcp/telegram-channel.js +127 -9
- package/dist/{persistent-session-DJSSEIR6.js → persistent-session-GB3D5OIA.js} +3 -3
- package/dist/{responsiveness-probe-A5335ORT.js → responsiveness-probe-TDZDQXBU.js} +3 -3
- package/dist/{session-auth-dead-KUYVUOK5.js → session-auth-dead-CPY4UZI7.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-LHYYO4NY.js.map +0 -1
- /package/dist/{chunk-ILDRNSOB.js.map → chunk-JN4D7534.js.map} +0 -0
- /package/dist/{chunk-OOYUWMTR.js.map → chunk-XSBRGOGL.js.map} +0 -0
- /package/dist/{claude-pair-runtime-JK7GQU25.js.map → claude-pair-runtime-KWBCSCZO.js.map} +0 -0
- /package/dist/{persistent-session-DJSSEIR6.js.map → persistent-session-GB3D5OIA.js.map} +0 -0
- /package/dist/{responsiveness-probe-A5335ORT.js.map → responsiveness-probe-TDZDQXBU.js.map} +0 -0
- /package/dist/{session-auth-dead-KUYVUOK5.js.map → session-auth-dead-CPY4UZI7.js.map} +0 -0
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
safeWriteJsonAtomic,
|
|
58
58
|
setConfigHash,
|
|
59
59
|
tripClass
|
|
60
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-XSBRGOGL.js";
|
|
61
61
|
import {
|
|
62
62
|
getProjectDir as getProjectDir2,
|
|
63
63
|
getReadyTasks,
|
|
@@ -115,7 +115,7 @@ import {
|
|
|
115
115
|
takeZombieDetection,
|
|
116
116
|
toOpencodeModel,
|
|
117
117
|
writeEgressAllowlist
|
|
118
|
-
} from "../chunk-
|
|
118
|
+
} from "../chunk-JN4D7534.js";
|
|
119
119
|
import {
|
|
120
120
|
ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
|
|
121
121
|
AnchorSessionClient,
|
|
@@ -200,14 +200,14 @@ import {
|
|
|
200
200
|
subagentActivityAgeSeconds,
|
|
201
201
|
sumTranscriptUsageInWindow,
|
|
202
202
|
transcriptActivityAgeSeconds
|
|
203
|
-
} from "../chunk-
|
|
203
|
+
} from "../chunk-KVR5KNED.js";
|
|
204
204
|
import {
|
|
205
205
|
reapOrphanChannelMcps
|
|
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 createHash18 } from "crypto";
|
|
210
|
+
import { readFileSync as readFileSync30, writeFileSync as writeFileSync16, mkdirSync as mkdirSync12, existsSync as existsSync17, rmSync as rmSync6, readdirSync as readdirSync10, statSync as statSync9, unlinkSync as unlinkSync6, renameSync as renameSync9, utimesSync as utimesSync2 } 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 join39, dirname as dirname10, delimiter as pathDelimiter } from "path";
|
|
237
237
|
import { homedir as homedir17 } from "os";
|
|
238
238
|
import { fileURLToPath } from "url";
|
|
239
239
|
|
|
@@ -1691,12 +1691,12 @@ function isPathInsideDir(candidate, dir) {
|
|
|
1691
1691
|
return resolvedCandidate.startsWith(resolvedDir.endsWith(sep) ? resolvedDir : resolvedDir + sep);
|
|
1692
1692
|
}
|
|
1693
1693
|
function findMissingMcpBundles(mcpConfigPath, deps = {}) {
|
|
1694
|
-
const
|
|
1695
|
-
const
|
|
1694
|
+
const existsSync18 = deps.existsSync ?? nodeExistsSync;
|
|
1695
|
+
const readFileSync31 = deps.readFileSync ?? nodeReadFileSync;
|
|
1696
1696
|
const mcpDir = deps.mcpDir ?? getSharedMcpDir();
|
|
1697
1697
|
let parsed;
|
|
1698
1698
|
try {
|
|
1699
|
-
parsed = JSON.parse(
|
|
1699
|
+
parsed = JSON.parse(readFileSync31(mcpConfigPath, "utf-8"));
|
|
1700
1700
|
} catch {
|
|
1701
1701
|
return [];
|
|
1702
1702
|
}
|
|
@@ -1716,7 +1716,7 @@ function findMissingMcpBundles(mcpConfigPath, deps = {}) {
|
|
|
1716
1716
|
if (seenPaths.has(resolvedBundlePath)) continue;
|
|
1717
1717
|
let present;
|
|
1718
1718
|
try {
|
|
1719
|
-
present =
|
|
1719
|
+
present = existsSync18(bundlePath);
|
|
1720
1720
|
} catch {
|
|
1721
1721
|
continue;
|
|
1722
1722
|
}
|
|
@@ -5194,19 +5194,122 @@ function computeChannelConfigHash(input) {
|
|
|
5194
5194
|
).digest("hex");
|
|
5195
5195
|
}
|
|
5196
5196
|
|
|
5197
|
-
// src/lib/
|
|
5198
|
-
import {
|
|
5197
|
+
// src/lib/knowledge-cache.ts
|
|
5198
|
+
import { createHash as createHash9 } from "crypto";
|
|
5199
|
+
import {
|
|
5200
|
+
existsSync as existsSync6,
|
|
5201
|
+
mkdirSync as mkdirSync6,
|
|
5202
|
+
readFileSync as readFileSync17,
|
|
5203
|
+
readdirSync as readdirSync5,
|
|
5204
|
+
renameSync as renameSync5,
|
|
5205
|
+
rmSync as rmSync3,
|
|
5206
|
+
statSync as statSync5,
|
|
5207
|
+
utimesSync,
|
|
5208
|
+
writeFileSync as writeFileSync8
|
|
5209
|
+
} from "fs";
|
|
5199
5210
|
import { join as join23 } from "path";
|
|
5211
|
+
var KNOWLEDGE_FETCH_CHUNK = 100;
|
|
5212
|
+
var CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
5213
|
+
var SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
5214
|
+
var lastSweepAt = 0;
|
|
5215
|
+
function knowledgeHash(content) {
|
|
5216
|
+
return createHash9("sha256").update(content, "utf8").digest("hex");
|
|
5217
|
+
}
|
|
5218
|
+
function cachePath(cacheDir, hash) {
|
|
5219
|
+
return join23(cacheDir, hash);
|
|
5220
|
+
}
|
|
5221
|
+
function readCachedKnowledge(cacheDir, hash) {
|
|
5222
|
+
const path = cachePath(cacheDir, hash);
|
|
5223
|
+
try {
|
|
5224
|
+
const content = readFileSync17(path, "utf-8");
|
|
5225
|
+
try {
|
|
5226
|
+
const now = /* @__PURE__ */ new Date();
|
|
5227
|
+
utimesSync(path, now, now);
|
|
5228
|
+
} catch {
|
|
5229
|
+
}
|
|
5230
|
+
return content;
|
|
5231
|
+
} catch {
|
|
5232
|
+
return null;
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
function writeCachedKnowledge(cacheDir, hash, content) {
|
|
5236
|
+
if (knowledgeHash(content) !== hash) return false;
|
|
5237
|
+
try {
|
|
5238
|
+
mkdirSync6(cacheDir, { recursive: true });
|
|
5239
|
+
const tmp = `${cachePath(cacheDir, hash)}.tmp-${process.pid}`;
|
|
5240
|
+
writeFileSync8(tmp, content, "utf-8");
|
|
5241
|
+
renameSync5(tmp, cachePath(cacheDir, hash));
|
|
5242
|
+
return true;
|
|
5243
|
+
} catch {
|
|
5244
|
+
return false;
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
function sweepKnowledgeCache(cacheDir, now = Date.now()) {
|
|
5248
|
+
if (now - lastSweepAt < SWEEP_INTERVAL_MS) return;
|
|
5249
|
+
lastSweepAt = now;
|
|
5250
|
+
try {
|
|
5251
|
+
if (!existsSync6(cacheDir)) return;
|
|
5252
|
+
for (const name of readdirSync5(cacheDir)) {
|
|
5253
|
+
const path = join23(cacheDir, name);
|
|
5254
|
+
try {
|
|
5255
|
+
if (now - statSync5(path).mtimeMs > CACHE_TTL_MS) rmSync3(path, { force: true });
|
|
5256
|
+
} catch {
|
|
5257
|
+
}
|
|
5258
|
+
}
|
|
5259
|
+
} catch {
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5262
|
+
async function resolveKnowledgeFromManifest(args) {
|
|
5263
|
+
const { manifest, cacheDir, delivery, fetchContents, log: log2 } = args;
|
|
5264
|
+
const meta = (e) => ({ title: e.title, slug: e.slug, scope: e.scope });
|
|
5265
|
+
if (delivery === "search") {
|
|
5266
|
+
sweepKnowledgeCache(cacheDir);
|
|
5267
|
+
return manifest.map((e) => ({ ...meta(e), content: null }));
|
|
5268
|
+
}
|
|
5269
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
5270
|
+
const missing = [];
|
|
5271
|
+
for (const entry of manifest) {
|
|
5272
|
+
if (!entry.hash || bodies.has(entry.hash)) continue;
|
|
5273
|
+
const cached = readCachedKnowledge(cacheDir, entry.hash);
|
|
5274
|
+
if (cached !== null) bodies.set(entry.hash, cached);
|
|
5275
|
+
else if (!missing.includes(entry.hash)) missing.push(entry.hash);
|
|
5276
|
+
}
|
|
5277
|
+
if (missing.length > 0) {
|
|
5278
|
+
for (let i = 0; i < missing.length; i += KNOWLEDGE_FETCH_CHUNK) {
|
|
5279
|
+
const chunk2 = missing.slice(i, i + KNOWLEDGE_FETCH_CHUNK);
|
|
5280
|
+
try {
|
|
5281
|
+
for (const { hash, content } of await fetchContents(chunk2)) {
|
|
5282
|
+
if (!writeCachedKnowledge(cacheDir, hash, content)) {
|
|
5283
|
+
log2?.(`[knowledge] hash mismatch for ${hash} \u2014 dropping this poll`);
|
|
5284
|
+
continue;
|
|
5285
|
+
}
|
|
5286
|
+
bodies.set(hash, content);
|
|
5287
|
+
}
|
|
5288
|
+
} catch (err) {
|
|
5289
|
+
log2?.(`[knowledge] fetch failed for ${chunk2.length} entries: ${err.message}`);
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
sweepKnowledgeCache(cacheDir);
|
|
5294
|
+
return manifest.map((e) => ({
|
|
5295
|
+
...meta(e),
|
|
5296
|
+
content: (e.hash ? bodies.get(e.hash) : void 0) ?? null
|
|
5297
|
+
}));
|
|
5298
|
+
}
|
|
5299
|
+
|
|
5300
|
+
// src/lib/channel-hash-cache.ts
|
|
5301
|
+
import { existsSync as existsSync7, readFileSync as readFileSync18, writeFileSync as writeFileSync9 } from "fs";
|
|
5302
|
+
import { join as join24 } from "path";
|
|
5200
5303
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
5201
5304
|
function getChannelHashCacheFile(configDir) {
|
|
5202
|
-
return
|
|
5305
|
+
return join24(configDir, CACHE_FILENAME);
|
|
5203
5306
|
}
|
|
5204
5307
|
function loadChannelHashCache(target, configDir) {
|
|
5205
5308
|
const path = getChannelHashCacheFile(configDir);
|
|
5206
|
-
if (!
|
|
5309
|
+
if (!existsSync7(path)) return;
|
|
5207
5310
|
let parsed;
|
|
5208
5311
|
try {
|
|
5209
|
-
parsed = JSON.parse(
|
|
5312
|
+
parsed = JSON.parse(readFileSync18(path, "utf-8"));
|
|
5210
5313
|
} catch {
|
|
5211
5314
|
return;
|
|
5212
5315
|
}
|
|
@@ -5220,14 +5323,14 @@ function saveChannelHashCache(source, configDir) {
|
|
|
5220
5323
|
const obj = {};
|
|
5221
5324
|
for (const [key, value] of source) obj[key] = value;
|
|
5222
5325
|
try {
|
|
5223
|
-
|
|
5326
|
+
writeFileSync9(path, JSON.stringify(obj, null, 2));
|
|
5224
5327
|
} catch {
|
|
5225
5328
|
}
|
|
5226
5329
|
}
|
|
5227
5330
|
|
|
5228
5331
|
// src/lib/sender-policy-baseline.ts
|
|
5229
|
-
import { existsSync as
|
|
5230
|
-
import { join as
|
|
5332
|
+
import { existsSync as existsSync8, readFileSync as readFileSync19 } from "fs";
|
|
5333
|
+
import { join as join25 } from "path";
|
|
5231
5334
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
5232
5335
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
5233
5336
|
var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
|
|
@@ -5239,14 +5342,14 @@ function createDeliveryBaselineMaps() {
|
|
|
5239
5342
|
};
|
|
5240
5343
|
}
|
|
5241
5344
|
function getSenderPolicyBaselineFile(configDir) {
|
|
5242
|
-
return
|
|
5345
|
+
return join25(configDir, BASELINE_FILENAME);
|
|
5243
5346
|
}
|
|
5244
5347
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
5245
5348
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
5246
|
-
if (!
|
|
5349
|
+
if (!existsSync8(path)) return;
|
|
5247
5350
|
let parsed;
|
|
5248
5351
|
try {
|
|
5249
|
-
parsed = JSON.parse(
|
|
5352
|
+
parsed = JSON.parse(readFileSync19(path, "utf-8"));
|
|
5250
5353
|
} catch (err) {
|
|
5251
5354
|
log2?.(
|
|
5252
5355
|
`[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
|
|
@@ -5295,8 +5398,8 @@ function saveSenderPolicyBaseline(source, configDir, log2) {
|
|
|
5295
5398
|
}
|
|
5296
5399
|
|
|
5297
5400
|
// src/lib/stuck-streak-store.ts
|
|
5298
|
-
import { existsSync as
|
|
5299
|
-
import { join as
|
|
5401
|
+
import { existsSync as existsSync9, readFileSync as readFileSync20 } from "fs";
|
|
5402
|
+
import { join as join26 } from "path";
|
|
5300
5403
|
var STORE_FILENAME = "stuck-streaks.json";
|
|
5301
5404
|
var STUCK_STREAK_STORE_VERSION = 1;
|
|
5302
5405
|
var STUCK_STREAK_CONCERNS = ["channelSync", "realtimeRebind"];
|
|
@@ -5304,7 +5407,7 @@ function createStuckStreakMaps() {
|
|
|
5304
5407
|
return { channelSync: /* @__PURE__ */ new Map(), realtimeRebind: /* @__PURE__ */ new Map() };
|
|
5305
5408
|
}
|
|
5306
5409
|
function getStuckStreakStoreFile(configDir) {
|
|
5307
|
-
return
|
|
5410
|
+
return join26(configDir, STORE_FILENAME);
|
|
5308
5411
|
}
|
|
5309
5412
|
function isValidPersistedStreak(value) {
|
|
5310
5413
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -5343,10 +5446,10 @@ function buildStuckStreakPayload(source) {
|
|
|
5343
5446
|
}
|
|
5344
5447
|
function loadStuckStreaks(target, configDir, log2) {
|
|
5345
5448
|
const path = getStuckStreakStoreFile(configDir);
|
|
5346
|
-
if (!
|
|
5449
|
+
if (!existsSync9(path)) return;
|
|
5347
5450
|
let parsed;
|
|
5348
5451
|
try {
|
|
5349
|
-
parsed = JSON.parse(
|
|
5452
|
+
parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
5350
5453
|
} catch (err) {
|
|
5351
5454
|
log2?.(
|
|
5352
5455
|
`[stuck-streaks] discarding corrupt ${STORE_FILENAME} (${err.message}) \u2014 stuck-streak ages restart from zero and one spurious "recovered" close may follow`
|
|
@@ -5863,7 +5966,7 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
5863
5966
|
}
|
|
5864
5967
|
|
|
5865
5968
|
// src/lib/manager/integration-skill-cache.ts
|
|
5866
|
-
import { join as
|
|
5969
|
+
import { join as join27 } from "path";
|
|
5867
5970
|
function integrationSkillHashKey(agentId, skillId) {
|
|
5868
5971
|
return `plugin-skill:${agentId}:${skillId}`;
|
|
5869
5972
|
}
|
|
@@ -5879,21 +5982,21 @@ function forgetIntegrationSkill(cache2, agentId, skillId) {
|
|
|
5879
5982
|
function removeIntegrationSkillFolder(opts) {
|
|
5880
5983
|
forgetIntegrationSkill(opts.cache, opts.agentId, opts.entry);
|
|
5881
5984
|
for (const dir of opts.dirs) {
|
|
5882
|
-
opts.removeDir(
|
|
5985
|
+
opts.removeDir(join27(dir, opts.entry));
|
|
5883
5986
|
}
|
|
5884
5987
|
}
|
|
5885
5988
|
|
|
5886
5989
|
// src/lib/manager/managed-skill-manifest.ts
|
|
5887
|
-
import { existsSync as
|
|
5888
|
-
import { dirname as dirname7, join as
|
|
5990
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync21, writeFileSync as writeFileSync10 } from "fs";
|
|
5991
|
+
import { dirname as dirname7, join as join28 } from "path";
|
|
5889
5992
|
var MANIFEST_VERSION = 1;
|
|
5890
5993
|
function managedSkillManifestPath(agentRootDir) {
|
|
5891
|
-
return
|
|
5994
|
+
return join28(agentRootDir, "managed-skills.json");
|
|
5892
5995
|
}
|
|
5893
5996
|
function readManagedSkillManifest(path) {
|
|
5894
5997
|
try {
|
|
5895
|
-
if (!
|
|
5896
|
-
const parsed = JSON.parse(
|
|
5998
|
+
if (!existsSync10(path)) return /* @__PURE__ */ new Set();
|
|
5999
|
+
const parsed = JSON.parse(readFileSync21(path, "utf-8"));
|
|
5897
6000
|
const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
|
|
5898
6001
|
return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
|
|
5899
6002
|
} catch {
|
|
@@ -5902,12 +6005,12 @@ function readManagedSkillManifest(path) {
|
|
|
5902
6005
|
}
|
|
5903
6006
|
function writeManagedSkillManifest(path, ids) {
|
|
5904
6007
|
try {
|
|
5905
|
-
|
|
6008
|
+
mkdirSync7(dirname7(path), { recursive: true });
|
|
5906
6009
|
const body = {
|
|
5907
6010
|
version: MANIFEST_VERSION,
|
|
5908
6011
|
globalSkillIds: [...ids].sort()
|
|
5909
6012
|
};
|
|
5910
|
-
|
|
6013
|
+
writeFileSync10(path, JSON.stringify(body, null, 2));
|
|
5911
6014
|
} catch {
|
|
5912
6015
|
}
|
|
5913
6016
|
}
|
|
@@ -6019,8 +6122,8 @@ function resolveModelChain(refreshData) {
|
|
|
6019
6122
|
}
|
|
6020
6123
|
|
|
6021
6124
|
// src/lib/manager/claude-auth.ts
|
|
6022
|
-
import { existsSync as
|
|
6023
|
-
import { join as
|
|
6125
|
+
import { existsSync as existsSync11, rmSync as rmSync4 } from "fs";
|
|
6126
|
+
import { join as join29 } from "path";
|
|
6024
6127
|
import { homedir as homedir13 } from "os";
|
|
6025
6128
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
6026
6129
|
const apiKey = getApiKey();
|
|
@@ -6033,12 +6136,12 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
6033
6136
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
6034
6137
|
}
|
|
6035
6138
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
6036
|
-
const claudeDir =
|
|
6139
|
+
const claudeDir = join29(homedir13(), ".claude");
|
|
6037
6140
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
6038
|
-
const p =
|
|
6039
|
-
if (
|
|
6141
|
+
const p = join29(claudeDir, filename);
|
|
6142
|
+
if (existsSync11(p)) {
|
|
6040
6143
|
try {
|
|
6041
|
-
|
|
6144
|
+
rmSync4(p, { force: true });
|
|
6042
6145
|
log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
|
|
6043
6146
|
} catch {
|
|
6044
6147
|
}
|
|
@@ -6117,8 +6220,8 @@ function heartbeatRuntimeAuthFields(probeVerdict) {
|
|
|
6117
6220
|
}
|
|
6118
6221
|
|
|
6119
6222
|
// src/lib/manager/kanban/parsers.ts
|
|
6120
|
-
import { existsSync as
|
|
6121
|
-
import { join as
|
|
6223
|
+
import { existsSync as existsSync12, readFileSync as readFileSync22 } from "fs";
|
|
6224
|
+
import { join as join30 } from "path";
|
|
6122
6225
|
var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
|
|
6123
6226
|
var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
|
|
6124
6227
|
var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
|
|
@@ -6270,12 +6373,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
6270
6373
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
6271
6374
|
try {
|
|
6272
6375
|
const candidates = [
|
|
6273
|
-
|
|
6274
|
-
|
|
6376
|
+
join30(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
6377
|
+
join30(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
6275
6378
|
];
|
|
6276
6379
|
for (const candidate of candidates) {
|
|
6277
|
-
if (
|
|
6278
|
-
const content =
|
|
6380
|
+
if (existsSync12(candidate)) {
|
|
6381
|
+
const content = readFileSync22(candidate, "utf-8");
|
|
6279
6382
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
6280
6383
|
builtInSkillCache.set(skillId, files);
|
|
6281
6384
|
return files;
|
|
@@ -6416,19 +6519,19 @@ function formatBoardForPrompt(items, template) {
|
|
|
6416
6519
|
}
|
|
6417
6520
|
|
|
6418
6521
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
6419
|
-
import { existsSync as
|
|
6420
|
-
import { join as
|
|
6522
|
+
import { existsSync as existsSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync11 } from "fs";
|
|
6523
|
+
import { join as join31 } from "path";
|
|
6421
6524
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
6422
6525
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
6423
6526
|
function getKanbanNudgeStateFile(configDir) {
|
|
6424
|
-
return
|
|
6527
|
+
return join31(configDir, CACHE_FILENAME2);
|
|
6425
6528
|
}
|
|
6426
6529
|
function loadKanbanNudgeState(target, configDir) {
|
|
6427
6530
|
const path = getKanbanNudgeStateFile(configDir);
|
|
6428
|
-
if (!
|
|
6531
|
+
if (!existsSync13(path)) return;
|
|
6429
6532
|
let parsed;
|
|
6430
6533
|
try {
|
|
6431
|
-
parsed = JSON.parse(
|
|
6534
|
+
parsed = JSON.parse(readFileSync23(path, "utf-8"));
|
|
6432
6535
|
} catch {
|
|
6433
6536
|
return;
|
|
6434
6537
|
}
|
|
@@ -6460,13 +6563,13 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
6460
6563
|
const agents = {};
|
|
6461
6564
|
for (const [codeName, state9] of source) agents[codeName] = state9;
|
|
6462
6565
|
try {
|
|
6463
|
-
|
|
6566
|
+
writeFileSync11(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
6464
6567
|
} catch {
|
|
6465
6568
|
}
|
|
6466
6569
|
}
|
|
6467
6570
|
|
|
6468
6571
|
// src/lib/manager/kanban/notify.ts
|
|
6469
|
-
import { createHash as
|
|
6572
|
+
import { createHash as createHash10 } from "crypto";
|
|
6470
6573
|
async function enqueueKanbanNotice(opts) {
|
|
6471
6574
|
try {
|
|
6472
6575
|
const res = await api.post(
|
|
@@ -6481,7 +6584,7 @@ async function enqueueKanbanNotice(opts) {
|
|
|
6481
6584
|
return res.ok === true;
|
|
6482
6585
|
} catch (err) {
|
|
6483
6586
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6484
|
-
const errId =
|
|
6587
|
+
const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6485
6588
|
log(`[kanban] notice enqueue failed for agent_id=${opts.agentId} error_id=${errId}`);
|
|
6486
6589
|
return false;
|
|
6487
6590
|
}
|
|
@@ -6496,7 +6599,7 @@ async function cancelKanbanNotice(agentId) {
|
|
|
6496
6599
|
return typeof res.cancelled === "number" ? res.cancelled : 0;
|
|
6497
6600
|
} catch (err) {
|
|
6498
6601
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6499
|
-
const errId =
|
|
6602
|
+
const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6500
6603
|
log(`[kanban] notice cancel failed for agent_id=${agentId} error_id=${errId}`);
|
|
6501
6604
|
return null;
|
|
6502
6605
|
}
|
|
@@ -6902,7 +7005,7 @@ function deriveScheduledTaskNotify(task) {
|
|
|
6902
7005
|
}
|
|
6903
7006
|
|
|
6904
7007
|
// src/lib/manager/scheduler/runs.ts
|
|
6905
|
-
import { createHash as
|
|
7008
|
+
import { createHash as createHash11 } from "crypto";
|
|
6906
7009
|
async function startRun(opts) {
|
|
6907
7010
|
try {
|
|
6908
7011
|
const res = await api.post(
|
|
@@ -6917,7 +7020,7 @@ async function startRun(opts) {
|
|
|
6917
7020
|
};
|
|
6918
7021
|
} catch (err) {
|
|
6919
7022
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6920
|
-
const errId =
|
|
7023
|
+
const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6921
7024
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
6922
7025
|
return { run_id: null, kanban_item_id: null };
|
|
6923
7026
|
}
|
|
@@ -6956,7 +7059,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
6956
7059
|
return;
|
|
6957
7060
|
} catch (err) {
|
|
6958
7061
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6959
|
-
const errId =
|
|
7062
|
+
const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6960
7063
|
const status = err instanceof ApiError ? err.status : 0;
|
|
6961
7064
|
if (isRetryableFinishError(err) && attempt < maxRetries) {
|
|
6962
7065
|
log(
|
|
@@ -6985,7 +7088,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
6985
7088
|
return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
|
|
6986
7089
|
} catch (err) {
|
|
6987
7090
|
const errText = err instanceof Error ? err.message : String(err);
|
|
6988
|
-
const errId =
|
|
7091
|
+
const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
|
|
6989
7092
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
6990
7093
|
return [];
|
|
6991
7094
|
}
|
|
@@ -7045,13 +7148,13 @@ function closeSessionRunForCode(codeName, outcome, reason) {
|
|
|
7045
7148
|
}
|
|
7046
7149
|
|
|
7047
7150
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
7048
|
-
import { createHash as
|
|
7049
|
-
import { writeFileSync as
|
|
7151
|
+
import { createHash as createHash13 } from "crypto";
|
|
7152
|
+
import { writeFileSync as writeFileSync12, renameSync as renameSync6, mkdirSync as mkdirSync8, readFileSync as readFileSync24, unlinkSync as unlinkSync3 } from "fs";
|
|
7050
7153
|
import { homedir as homedir14 } from "os";
|
|
7051
|
-
import { join as
|
|
7154
|
+
import { join as join32, dirname as dirname8 } from "path";
|
|
7052
7155
|
|
|
7053
7156
|
// src/lib/manager/scheduler/notify.ts
|
|
7054
|
-
import { createHash as
|
|
7157
|
+
import { createHash as createHash12 } from "crypto";
|
|
7055
7158
|
async function enqueueScheduledTaskNotice(opts) {
|
|
7056
7159
|
try {
|
|
7057
7160
|
const res = await api.post(
|
|
@@ -7068,7 +7171,7 @@ async function enqueueScheduledTaskNotice(opts) {
|
|
|
7068
7171
|
return res.ok === true;
|
|
7069
7172
|
} catch (err) {
|
|
7070
7173
|
const errText = err instanceof Error ? err.message : String(err);
|
|
7071
|
-
const errId =
|
|
7174
|
+
const errId = createHash12("sha256").update(errText).digest("hex").slice(0, 12);
|
|
7072
7175
|
log(
|
|
7073
7176
|
`[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
|
|
7074
7177
|
);
|
|
@@ -7407,19 +7510,19 @@ function resolveScheduledSlackTarget(task) {
|
|
|
7407
7510
|
}
|
|
7408
7511
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
7409
7512
|
try {
|
|
7410
|
-
const file =
|
|
7513
|
+
const file = join32(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
7411
7514
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
7412
7515
|
const tmp = `${file}.tmp`;
|
|
7413
|
-
|
|
7414
|
-
|
|
7516
|
+
writeFileSync12(tmp, JSON.stringify(marker), "utf8");
|
|
7517
|
+
renameSync6(tmp, file);
|
|
7415
7518
|
} catch (err) {
|
|
7416
7519
|
log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
|
|
7417
7520
|
}
|
|
7418
7521
|
}
|
|
7419
7522
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
7420
|
-
const file =
|
|
7523
|
+
const file = join32(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
7421
7524
|
try {
|
|
7422
|
-
const raw = JSON.parse(
|
|
7525
|
+
const raw = JSON.parse(readFileSync24(file, "utf8"));
|
|
7423
7526
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
7424
7527
|
unlinkSync3(file);
|
|
7425
7528
|
log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
|
|
@@ -7480,8 +7583,8 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt, dura
|
|
|
7480
7583
|
}
|
|
7481
7584
|
try {
|
|
7482
7585
|
const doorbell = directChatDoorbellPath(agentId, homedir14());
|
|
7483
|
-
|
|
7484
|
-
|
|
7586
|
+
mkdirSync8(dirname8(doorbell), { recursive: true });
|
|
7587
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
7485
7588
|
} catch (err) {
|
|
7486
7589
|
log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
7487
7590
|
}
|
|
@@ -7547,24 +7650,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
7547
7650
|
const assertion = parseDeliverAssertion(rawOutput);
|
|
7548
7651
|
if (!assertion.deliver) {
|
|
7549
7652
|
const trimmed = (rawOutput ?? "").trim();
|
|
7550
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
7653
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash13("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
7551
7654
|
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}`);
|
|
7552
7655
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
7553
7656
|
await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
|
|
7554
7657
|
}
|
|
7555
7658
|
return { ok: true };
|
|
7556
7659
|
}
|
|
7557
|
-
const reasonHash =
|
|
7660
|
+
const reasonHash = createHash13("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
|
|
7558
7661
|
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})`);
|
|
7559
7662
|
rawOutput = assertion.deliverable;
|
|
7560
7663
|
}
|
|
7561
7664
|
const classification = classifyOutput(rawOutput);
|
|
7562
7665
|
if (classification.action === "suppress") {
|
|
7563
7666
|
const trimmed = (rawOutput ?? "").trim();
|
|
7564
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
7667
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash13("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
7565
7668
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
7566
7669
|
if (classification.suppressedNotes) {
|
|
7567
|
-
const notesHash =
|
|
7670
|
+
const notesHash = createHash13("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
7568
7671
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
7569
7672
|
}
|
|
7570
7673
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -7630,13 +7733,13 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
7630
7733
|
}
|
|
7631
7734
|
|
|
7632
7735
|
// src/lib/manager/scheduler/execution.ts
|
|
7633
|
-
import { createHash as
|
|
7736
|
+
import { createHash as createHash14 } from "crypto";
|
|
7634
7737
|
import { homedir as homedir15 } from "os";
|
|
7635
|
-
import { join as
|
|
7738
|
+
import { join as join34 } from "path";
|
|
7636
7739
|
|
|
7637
7740
|
// src/lib/agent-serving-probe.ts
|
|
7638
|
-
import { readFileSync as
|
|
7639
|
-
import { join as
|
|
7741
|
+
import { readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
|
|
7742
|
+
import { join as join33 } from "path";
|
|
7640
7743
|
var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
|
|
7641
7744
|
function probeRateLimit(args) {
|
|
7642
7745
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
@@ -7645,23 +7748,23 @@ function probeRateLimit(args) {
|
|
|
7645
7748
|
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
7646
7749
|
let entries;
|
|
7647
7750
|
try {
|
|
7648
|
-
entries =
|
|
7751
|
+
entries = readdirSync6(dir);
|
|
7649
7752
|
} catch {
|
|
7650
7753
|
return UNKNOWN_RATE_LIMIT;
|
|
7651
7754
|
}
|
|
7652
7755
|
let newest = UNKNOWN_RATE_LIMIT;
|
|
7653
7756
|
for (const name of entries) {
|
|
7654
7757
|
if (!name.endsWith(".jsonl")) continue;
|
|
7655
|
-
const path =
|
|
7758
|
+
const path = join33(dir, name);
|
|
7656
7759
|
try {
|
|
7657
|
-
const st =
|
|
7760
|
+
const st = statSync6(path);
|
|
7658
7761
|
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
7659
7762
|
} catch {
|
|
7660
7763
|
continue;
|
|
7661
7764
|
}
|
|
7662
7765
|
let content;
|
|
7663
7766
|
try {
|
|
7664
|
-
content =
|
|
7767
|
+
content = readFileSync25(path, "utf-8");
|
|
7665
7768
|
} catch {
|
|
7666
7769
|
continue;
|
|
7667
7770
|
}
|
|
@@ -7723,7 +7826,7 @@ function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
|
|
|
7723
7826
|
|
|
7724
7827
|
// src/lib/manager/scheduler/execution.ts
|
|
7725
7828
|
function claudePidFilePath() {
|
|
7726
|
-
return
|
|
7829
|
+
return join34(homedir15(), ".augmented", "manager-claude-pids.json");
|
|
7727
7830
|
}
|
|
7728
7831
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
7729
7832
|
function registerClaudeSpawn(record) {
|
|
@@ -7743,10 +7846,10 @@ function unregisterClaudeSpawn(pid) {
|
|
|
7743
7846
|
}
|
|
7744
7847
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData, durableScheduledNudge = false) {
|
|
7745
7848
|
const codeName = agent.code_name;
|
|
7746
|
-
const stableTasksHash =
|
|
7747
|
-
const boardHash = boardItems.length > 0 ?
|
|
7849
|
+
const stableTasksHash = createHash14("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
7850
|
+
const boardHash = boardItems.length > 0 ? createHash14("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";
|
|
7748
7851
|
const resolvedModels = resolveModelChain(refreshData);
|
|
7749
|
-
const modelsHash =
|
|
7852
|
+
const modelsHash = createHash14("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
7750
7853
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
7751
7854
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
7752
7855
|
if (combinedHash !== prevHash) {
|
|
@@ -7793,8 +7896,8 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
7793
7896
|
}
|
|
7794
7897
|
|
|
7795
7898
|
// src/lib/occupancy-gate.ts
|
|
7796
|
-
import { closeSync as closeSync2, openSync as openSync2, readdirSync as
|
|
7797
|
-
import { join as
|
|
7899
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync7, readSync as readSync2, statSync as statSync7 } from "fs";
|
|
7900
|
+
import { join as join35 } from "path";
|
|
7798
7901
|
function rostersMeasuredZero(mode, attested, runtimeRunning) {
|
|
7799
7902
|
return mode === "enforce" && attested && runtimeRunning;
|
|
7800
7903
|
}
|
|
@@ -7808,7 +7911,7 @@ var brackets = /* @__PURE__ */ new Map();
|
|
|
7808
7911
|
function readAlignedTail(path, tailBytes, maxAlignBytes) {
|
|
7809
7912
|
let fd = null;
|
|
7810
7913
|
try {
|
|
7811
|
-
const size =
|
|
7914
|
+
const size = statSync7(path).size;
|
|
7812
7915
|
if (size <= 0) return { content: "", complete: true, truncated: false };
|
|
7813
7916
|
fd = openSync2(path, "r");
|
|
7814
7917
|
let readStart = Math.max(0, size - tailBytes);
|
|
@@ -7878,26 +7981,26 @@ function candidateTranscriptPaths(dir) {
|
|
|
7878
7981
|
const paths = [];
|
|
7879
7982
|
let top;
|
|
7880
7983
|
try {
|
|
7881
|
-
top =
|
|
7984
|
+
top = readdirSync7(dir);
|
|
7882
7985
|
} catch {
|
|
7883
7986
|
return { paths, complete: false };
|
|
7884
7987
|
}
|
|
7885
7988
|
let complete = true;
|
|
7886
7989
|
for (const name of top) {
|
|
7887
7990
|
if (name.endsWith(".jsonl")) {
|
|
7888
|
-
paths.push(
|
|
7991
|
+
paths.push(join35(dir, name));
|
|
7889
7992
|
continue;
|
|
7890
7993
|
}
|
|
7891
|
-
const subDir =
|
|
7994
|
+
const subDir = join35(dir, name, "subagents");
|
|
7892
7995
|
let subs;
|
|
7893
7996
|
try {
|
|
7894
|
-
subs =
|
|
7997
|
+
subs = readdirSync7(subDir);
|
|
7895
7998
|
} catch (err) {
|
|
7896
7999
|
if (!isAbsentDirError(err)) complete = false;
|
|
7897
8000
|
continue;
|
|
7898
8001
|
}
|
|
7899
8002
|
for (const sub of subs) {
|
|
7900
|
-
if (sub.endsWith(".jsonl")) paths.push(
|
|
8003
|
+
if (sub.endsWith(".jsonl")) paths.push(join35(subDir, sub));
|
|
7901
8004
|
}
|
|
7902
8005
|
}
|
|
7903
8006
|
return { paths, complete };
|
|
@@ -7952,7 +8055,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
|
|
|
7952
8055
|
for (const path of paths) {
|
|
7953
8056
|
let st;
|
|
7954
8057
|
try {
|
|
7955
|
-
st =
|
|
8058
|
+
st = statSync7(path);
|
|
7956
8059
|
} catch (err) {
|
|
7957
8060
|
if (!isAbsentDirError(err)) complete = false;
|
|
7958
8061
|
continue;
|
|
@@ -8058,7 +8161,7 @@ function qualifyBuckets(buckets, qualifying, mode, nowMs, neighbourhoodMs = DEFA
|
|
|
8058
8161
|
}
|
|
8059
8162
|
|
|
8060
8163
|
// src/lib/pane-occupancy-sampler.ts
|
|
8061
|
-
import { statSync as
|
|
8164
|
+
import { statSync as statSync8 } from "fs";
|
|
8062
8165
|
var SAMPLE_INTERVAL_MS = 1e4;
|
|
8063
8166
|
var IDLE_GAP_MS = 12e4;
|
|
8064
8167
|
var POST_IDLE_CREDIT_MS = 6e4;
|
|
@@ -8072,7 +8175,7 @@ function hasFreshPaneObservation(codeName, nowMs, maxAgeMs = OBSERVATION_FRESH_M
|
|
|
8072
8175
|
}
|
|
8073
8176
|
function paneMtimeMs(codeName) {
|
|
8074
8177
|
try {
|
|
8075
|
-
return
|
|
8178
|
+
return statSync8(paneLogPath(codeName)).mtimeMs;
|
|
8076
8179
|
} catch {
|
|
8077
8180
|
return null;
|
|
8078
8181
|
}
|
|
@@ -8124,7 +8227,7 @@ function stopPaneOccupancySampler() {
|
|
|
8124
8227
|
|
|
8125
8228
|
// src/lib/pid-pressure-sampler.ts
|
|
8126
8229
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
8127
|
-
import { existsSync as
|
|
8230
|
+
import { existsSync as existsSync14, readFileSync as readFileSync26 } from "fs";
|
|
8128
8231
|
var SAMPLE_INTERVAL_MS2 = 3e4;
|
|
8129
8232
|
function warnFraction() {
|
|
8130
8233
|
const raw = Number(process.env.AGT_PID_PRESSURE_WARN_FRACTION);
|
|
@@ -8137,7 +8240,7 @@ function configuredCeiling() {
|
|
|
8137
8240
|
}
|
|
8138
8241
|
function readTextReal(path) {
|
|
8139
8242
|
try {
|
|
8140
|
-
return
|
|
8243
|
+
return readFileSync26(path, "utf-8");
|
|
8141
8244
|
} catch {
|
|
8142
8245
|
return null;
|
|
8143
8246
|
}
|
|
@@ -8146,7 +8249,7 @@ var cgroupDirCache = /* @__PURE__ */ new Map();
|
|
|
8146
8249
|
var resolveRetryAfter = /* @__PURE__ */ new Map();
|
|
8147
8250
|
var RESOLVE_RETRY_BACKOFF_MS = 5 * 6e4;
|
|
8148
8251
|
function resolveCgroupDirReal(codeName, deps = {}) {
|
|
8149
|
-
const exists = deps.exists ??
|
|
8252
|
+
const exists = deps.exists ?? existsSync14;
|
|
8150
8253
|
const inspectId = deps.inspectId ?? inspectContainerId;
|
|
8151
8254
|
const now = deps.now ?? Date.now;
|
|
8152
8255
|
const cached = cgroupDirCache.get(codeName);
|
|
@@ -8264,7 +8367,7 @@ function stopPidPressureSampler() {
|
|
|
8264
8367
|
}
|
|
8265
8368
|
|
|
8266
8369
|
// src/lib/opencode-slack-ingest.ts
|
|
8267
|
-
import { createHash as
|
|
8370
|
+
import { createHash as createHash15 } from "crypto";
|
|
8268
8371
|
|
|
8269
8372
|
// ../../packages/core/dist/channels/slack-rich-text.js
|
|
8270
8373
|
var MAX_DEPTH = 12;
|
|
@@ -9271,7 +9374,7 @@ function startSlackIngest(config2) {
|
|
|
9271
9374
|
// src/lib/opencode-slack-ingest.ts
|
|
9272
9375
|
var ingests = /* @__PURE__ */ new Map();
|
|
9273
9376
|
function fingerprint(params) {
|
|
9274
|
-
return
|
|
9377
|
+
return createHash15("sha256").update(
|
|
9275
9378
|
JSON.stringify({
|
|
9276
9379
|
appToken: params.appToken,
|
|
9277
9380
|
botToken: params.botToken,
|
|
@@ -9352,7 +9455,7 @@ function stopAllOpencodeSlackIngests(log2) {
|
|
|
9352
9455
|
}
|
|
9353
9456
|
|
|
9354
9457
|
// src/lib/manager/opencode-scheduler.ts
|
|
9355
|
-
import { createHash as
|
|
9458
|
+
import { createHash as createHash16 } from "crypto";
|
|
9356
9459
|
var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
|
|
9357
9460
|
var opencodeSchedulerStates = /* @__PURE__ */ new Map();
|
|
9358
9461
|
var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
|
|
@@ -9366,7 +9469,7 @@ function shouldDeliver(task, reply) {
|
|
|
9366
9469
|
}
|
|
9367
9470
|
async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
9368
9471
|
const codeName = agent.code_name;
|
|
9369
|
-
const tasksHash =
|
|
9472
|
+
const tasksHash = createHash16("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
9370
9473
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
9371
9474
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
9372
9475
|
const state10 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
@@ -9444,10 +9547,10 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
9444
9547
|
}
|
|
9445
9548
|
|
|
9446
9549
|
// src/lib/opencode-telegram-ingest.ts
|
|
9447
|
-
import { createHash as
|
|
9448
|
-
import { existsSync as
|
|
9550
|
+
import { createHash as createHash17 } from "crypto";
|
|
9551
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync27, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
9449
9552
|
import { randomUUID } from "crypto";
|
|
9450
|
-
import { join as
|
|
9553
|
+
import { join as join36 } from "path";
|
|
9451
9554
|
|
|
9452
9555
|
// src/lib/telegram-ingest.ts
|
|
9453
9556
|
import https2 from "https";
|
|
@@ -9980,7 +10083,7 @@ function anySignal(signals) {
|
|
|
9980
10083
|
// src/lib/opencode-telegram-ingest.ts
|
|
9981
10084
|
var ingests2 = /* @__PURE__ */ new Map();
|
|
9982
10085
|
function fingerprint2(params) {
|
|
9983
|
-
return
|
|
10086
|
+
return createHash17("sha256").update(
|
|
9984
10087
|
JSON.stringify({
|
|
9985
10088
|
botToken: params.botToken,
|
|
9986
10089
|
allowedChats: [...params.allowedChats].sort(),
|
|
@@ -9995,7 +10098,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
9995
10098
|
let filePath;
|
|
9996
10099
|
try {
|
|
9997
10100
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
9998
|
-
filePath =
|
|
10101
|
+
filePath = join36(dir, "telegram-getupdates-offset-opencode.json");
|
|
9999
10102
|
} catch {
|
|
10000
10103
|
dir = null;
|
|
10001
10104
|
filePath = null;
|
|
@@ -10004,7 +10107,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10004
10107
|
load() {
|
|
10005
10108
|
if (!filePath) return 0;
|
|
10006
10109
|
try {
|
|
10007
|
-
const parsed = JSON.parse(
|
|
10110
|
+
const parsed = JSON.parse(readFileSync27(filePath, "utf-8"));
|
|
10008
10111
|
if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
|
|
10009
10112
|
log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
|
|
10010
10113
|
return 0;
|
|
@@ -10022,8 +10125,8 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10022
10125
|
if (!filePath || !dir) return;
|
|
10023
10126
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
10024
10127
|
try {
|
|
10025
|
-
|
|
10026
|
-
|
|
10128
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
10129
|
+
writeFileSync13(
|
|
10027
10130
|
tmpPath,
|
|
10028
10131
|
JSON.stringify({
|
|
10029
10132
|
offset,
|
|
@@ -10033,11 +10136,11 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
10033
10136
|
}),
|
|
10034
10137
|
{ mode: 384 }
|
|
10035
10138
|
);
|
|
10036
|
-
|
|
10139
|
+
renameSync7(tmpPath, filePath);
|
|
10037
10140
|
} catch (err) {
|
|
10038
10141
|
log2(`[telegram-ingest:${codeName}] offset persist failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10039
10142
|
try {
|
|
10040
|
-
if (
|
|
10143
|
+
if (existsSync15(tmpPath)) unlinkSync4(tmpPath);
|
|
10041
10144
|
} catch {
|
|
10042
10145
|
}
|
|
10043
10146
|
}
|
|
@@ -10274,24 +10377,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
10274
10377
|
}
|
|
10275
10378
|
|
|
10276
10379
|
// src/lib/restart-flags.ts
|
|
10277
|
-
import { existsSync as
|
|
10380
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readdirSync as readdirSync8, readFileSync as readFileSync28, renameSync as renameSync8, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "fs";
|
|
10278
10381
|
import { homedir as homedir16 } from "os";
|
|
10279
|
-
import { join as
|
|
10382
|
+
import { join as join37 } from "path";
|
|
10280
10383
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
10281
10384
|
function restartFlagsDir() {
|
|
10282
|
-
return
|
|
10385
|
+
return join37(homedir16(), ".augmented", "restart-flags");
|
|
10283
10386
|
}
|
|
10284
10387
|
function flagPath(codeName) {
|
|
10285
|
-
return
|
|
10388
|
+
return join37(restartFlagsDir(), `${codeName}.flag`);
|
|
10286
10389
|
}
|
|
10287
10390
|
function readRestartFlags() {
|
|
10288
10391
|
const dir = restartFlagsDir();
|
|
10289
|
-
if (!
|
|
10392
|
+
if (!existsSync16(dir)) return [];
|
|
10290
10393
|
const out = [];
|
|
10291
|
-
for (const entry of
|
|
10394
|
+
for (const entry of readdirSync8(dir)) {
|
|
10292
10395
|
if (!entry.endsWith(".flag")) continue;
|
|
10293
10396
|
try {
|
|
10294
|
-
const raw =
|
|
10397
|
+
const raw = readFileSync28(join37(dir, entry), "utf8");
|
|
10295
10398
|
const parsed = JSON.parse(raw);
|
|
10296
10399
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
10297
10400
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -10309,8 +10412,8 @@ function readRestartFlags() {
|
|
|
10309
10412
|
}
|
|
10310
10413
|
function deleteRestartFlag(codeName) {
|
|
10311
10414
|
const path = flagPath(codeName);
|
|
10312
|
-
if (
|
|
10313
|
-
|
|
10415
|
+
if (existsSync16(path)) {
|
|
10416
|
+
rmSync5(path, { force: true });
|
|
10314
10417
|
}
|
|
10315
10418
|
}
|
|
10316
10419
|
|
|
@@ -10409,8 +10512,8 @@ async function sendError(flag, opts, text) {
|
|
|
10409
10512
|
}
|
|
10410
10513
|
|
|
10411
10514
|
// src/lib/restart-context.ts
|
|
10412
|
-
import { readdirSync as
|
|
10413
|
-
import { dirname as dirname9, join as
|
|
10515
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync29, writeFileSync as writeFileSync15, mkdirSync as mkdirSync11, unlinkSync as unlinkSync5 } from "fs";
|
|
10516
|
+
import { dirname as dirname9, join as join38 } from "path";
|
|
10414
10517
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
10415
10518
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
10416
10519
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -10422,10 +10525,10 @@ function augmentedAgentDir(codeName) {
|
|
|
10422
10525
|
return dirname9(getProjectDir(codeName));
|
|
10423
10526
|
}
|
|
10424
10527
|
function slackPendingInboundDir(codeName) {
|
|
10425
|
-
return
|
|
10528
|
+
return join38(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
10426
10529
|
}
|
|
10427
10530
|
function slackRestartContextDir(codeName) {
|
|
10428
|
-
return
|
|
10531
|
+
return join38(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
10429
10532
|
}
|
|
10430
10533
|
function sanitizeTopic(raw) {
|
|
10431
10534
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -10460,14 +10563,14 @@ function computeRestartContextHints(markers, allTurns, nowMs, reconstruct = reco
|
|
|
10460
10563
|
}
|
|
10461
10564
|
function safeReaddir(dir) {
|
|
10462
10565
|
try {
|
|
10463
|
-
return
|
|
10566
|
+
return readdirSync9(dir);
|
|
10464
10567
|
} catch {
|
|
10465
10568
|
return [];
|
|
10466
10569
|
}
|
|
10467
10570
|
}
|
|
10468
10571
|
function readStrandedMarker(path) {
|
|
10469
10572
|
try {
|
|
10470
|
-
const parsed = JSON.parse(
|
|
10573
|
+
const parsed = JSON.parse(readFileSync29(path, "utf-8"));
|
|
10471
10574
|
if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
|
|
10472
10575
|
return { channel: parsed.channel, thread_ts: parsed.thread_ts };
|
|
10473
10576
|
}
|
|
@@ -10476,8 +10579,8 @@ function readStrandedMarker(path) {
|
|
|
10476
10579
|
return null;
|
|
10477
10580
|
}
|
|
10478
10581
|
function writeHintFile(path, dir, hint) {
|
|
10479
|
-
|
|
10480
|
-
|
|
10582
|
+
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
10583
|
+
writeFileSync15(path, JSON.stringify(hint), { mode: 384 });
|
|
10481
10584
|
}
|
|
10482
10585
|
function pruneHintsExcept(codeName, freshFilenames) {
|
|
10483
10586
|
const ctxDir = slackRestartContextDir(codeName);
|
|
@@ -10485,7 +10588,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
10485
10588
|
if (!filename.endsWith(".json")) continue;
|
|
10486
10589
|
if (freshFilenames.has(filename)) continue;
|
|
10487
10590
|
try {
|
|
10488
|
-
unlinkSync5(
|
|
10591
|
+
unlinkSync5(join38(ctxDir, filename));
|
|
10489
10592
|
} catch {
|
|
10490
10593
|
}
|
|
10491
10594
|
}
|
|
@@ -10506,7 +10609,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
10506
10609
|
}
|
|
10507
10610
|
const markers = [];
|
|
10508
10611
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
10509
|
-
const parsed = readStrandedMarker(
|
|
10612
|
+
const parsed = readStrandedMarker(join38(markerDir, filename));
|
|
10510
10613
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
10511
10614
|
}
|
|
10512
10615
|
if (markers.length === 0) {
|
|
@@ -10520,7 +10623,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
10520
10623
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
10521
10624
|
for (const { filename, hint } of hints) {
|
|
10522
10625
|
try {
|
|
10523
|
-
writeHintFile(
|
|
10626
|
+
writeHintFile(join38(ctxDir, filename), ctxDir, hint);
|
|
10524
10627
|
freshFilenames.add(filename);
|
|
10525
10628
|
} catch (err) {
|
|
10526
10629
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -11898,7 +12001,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
|
|
|
11898
12001
|
var dayRolloverInboundHold = /* @__PURE__ */ new Map();
|
|
11899
12002
|
var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
|
|
11900
12003
|
async function channelInboundActivityAgeSecondsFor(codeName) {
|
|
11901
|
-
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-
|
|
12004
|
+
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-TDZDQXBU.js");
|
|
11902
12005
|
const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
|
|
11903
12006
|
if (newest === null) return null;
|
|
11904
12007
|
return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
|
|
@@ -11998,7 +12101,7 @@ function performLazyDayRolloverReset(codeName, agentTimezone) {
|
|
|
11998
12101
|
}
|
|
11999
12102
|
function paneLogAgeSecondsFor(codeName) {
|
|
12000
12103
|
try {
|
|
12001
|
-
const mtimeMs =
|
|
12104
|
+
const mtimeMs = statSync9(paneLogPath(codeName)).mtimeMs;
|
|
12002
12105
|
return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
|
|
12003
12106
|
} catch (err) {
|
|
12004
12107
|
if (err?.code === "ENOENT") return null;
|
|
@@ -12148,15 +12251,15 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
12148
12251
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
12149
12252
|
function projectMcpHash(_codeName, projectDir) {
|
|
12150
12253
|
try {
|
|
12151
|
-
const raw =
|
|
12152
|
-
return
|
|
12254
|
+
const raw = readFileSync30(join39(projectDir, ".mcp.json"), "utf-8");
|
|
12255
|
+
return createHash18("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
12153
12256
|
} catch {
|
|
12154
12257
|
return null;
|
|
12155
12258
|
}
|
|
12156
12259
|
}
|
|
12157
12260
|
function projectMcpKeys(_codeName, projectDir) {
|
|
12158
12261
|
try {
|
|
12159
|
-
const raw =
|
|
12262
|
+
const raw = readFileSync30(join39(projectDir, ".mcp.json"), "utf-8");
|
|
12160
12263
|
const parsed = JSON.parse(raw);
|
|
12161
12264
|
const servers = parsed.mcpServers;
|
|
12162
12265
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -12174,7 +12277,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
12174
12277
|
else runningMcpServerKeys.delete(codeName);
|
|
12175
12278
|
let launchStructure = null;
|
|
12176
12279
|
try {
|
|
12177
|
-
const raw =
|
|
12280
|
+
const raw = readFileSync30(join39(projectDir, ".mcp.json"), "utf-8");
|
|
12178
12281
|
launchStructure = managedMcpStructureHashFromFile(
|
|
12179
12282
|
JSON.parse(raw),
|
|
12180
12283
|
isManagedMcpServerKey
|
|
@@ -12300,7 +12403,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
12300
12403
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
12301
12404
|
let mcpJsonForRebind = null;
|
|
12302
12405
|
try {
|
|
12303
|
-
mcpJsonForRebind = JSON.parse(
|
|
12406
|
+
mcpJsonForRebind = JSON.parse(readFileSync30(join39(projectDir, ".mcp.json"), "utf-8"));
|
|
12304
12407
|
} catch {
|
|
12305
12408
|
mcpJsonForRebind = null;
|
|
12306
12409
|
}
|
|
@@ -12448,7 +12551,7 @@ function shouldInjectChannelSecrets(agentId) {
|
|
|
12448
12551
|
function projectChannelSecretHash(projectDir) {
|
|
12449
12552
|
try {
|
|
12450
12553
|
const entries = parseEnvIntegrations(
|
|
12451
|
-
|
|
12554
|
+
readFileSync30(join39(projectDir, ".env.integrations"), "utf-8")
|
|
12452
12555
|
);
|
|
12453
12556
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
12454
12557
|
} catch {
|
|
@@ -12546,7 +12649,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
12546
12649
|
var lastVersionCheckAt = 0;
|
|
12547
12650
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
12548
12651
|
var lastResponsivenessProbeAt = 0;
|
|
12549
|
-
var agtCliVersion = true ? "0.28.
|
|
12652
|
+
var agtCliVersion = true ? "0.28.717" : "dev";
|
|
12550
12653
|
function resolveBrewPath(execFileSync3) {
|
|
12551
12654
|
try {
|
|
12552
12655
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -12559,7 +12662,7 @@ function resolveBrewPath(execFileSync3) {
|
|
|
12559
12662
|
"/usr/local/bin/brew"
|
|
12560
12663
|
];
|
|
12561
12664
|
for (const path of fallbacks) {
|
|
12562
|
-
if (
|
|
12665
|
+
if (existsSync17(path)) return path;
|
|
12563
12666
|
}
|
|
12564
12667
|
return null;
|
|
12565
12668
|
}
|
|
@@ -12569,7 +12672,7 @@ function claudeBinaryInstalled(execFileSync3) {
|
|
|
12569
12672
|
"/opt/homebrew/bin/claude",
|
|
12570
12673
|
"/usr/local/bin/claude"
|
|
12571
12674
|
];
|
|
12572
|
-
if (canonical.some((path) =>
|
|
12675
|
+
if (canonical.some((path) => existsSync17(path))) return true;
|
|
12573
12676
|
try {
|
|
12574
12677
|
execFileSync3("which", ["claude"], { timeout: 5e3 });
|
|
12575
12678
|
return true;
|
|
@@ -12879,8 +12982,8 @@ var MANAGED_SETTINGS_KEYS = ["channelsEnabled", "enableAllProjectMcpServers"];
|
|
|
12879
12982
|
function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
12880
12983
|
try {
|
|
12881
12984
|
let settings = {};
|
|
12882
|
-
if (
|
|
12883
|
-
const raw =
|
|
12985
|
+
if (existsSync17(path)) {
|
|
12986
|
+
const raw = readFileSync30(path, "utf-8").trim();
|
|
12884
12987
|
if (raw) {
|
|
12885
12988
|
let parsed;
|
|
12886
12989
|
try {
|
|
@@ -12897,8 +13000,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
12897
13000
|
const missing = MANAGED_SETTINGS_KEYS.filter((key) => settings[key] !== true);
|
|
12898
13001
|
if (missing.length === 0) return "ok";
|
|
12899
13002
|
for (const key of missing) settings[key] = true;
|
|
12900
|
-
|
|
12901
|
-
|
|
13003
|
+
mkdirSync12(dirname10(path), { recursive: true });
|
|
13004
|
+
writeFileSync16(path, `${JSON.stringify(settings, null, 2)}
|
|
12902
13005
|
`);
|
|
12903
13006
|
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)`);
|
|
12904
13007
|
return "ok";
|
|
@@ -12936,7 +13039,7 @@ async function ensureOpencodeBinary() {
|
|
|
12936
13039
|
try {
|
|
12937
13040
|
const prefix = execFileSync3("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
12938
13041
|
if (prefix) {
|
|
12939
|
-
const npmBin =
|
|
13042
|
+
const npmBin = join39(prefix, "bin");
|
|
12940
13043
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
12941
13044
|
if (!current.includes(npmBin)) {
|
|
12942
13045
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -12997,7 +13100,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
12997
13100
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
12998
13101
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
12999
13102
|
}
|
|
13000
|
-
if (
|
|
13103
|
+
if (existsSync17("/home/linuxbrew/.linuxbrew/bin/claude")) {
|
|
13001
13104
|
log("Claude Code installed successfully");
|
|
13002
13105
|
} else {
|
|
13003
13106
|
log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
|
|
@@ -13053,7 +13156,7 @@ ${r.stderr}`;
|
|
|
13053
13156
|
}
|
|
13054
13157
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
13055
13158
|
function selfUpdateAppliedMarkerPath() {
|
|
13056
|
-
return
|
|
13159
|
+
return join39(homedir17(), ".augmented", ".last-self-update-applied");
|
|
13057
13160
|
}
|
|
13058
13161
|
var selfUpdateUpToDateLogged = false;
|
|
13059
13162
|
var selfUpdatePinnedLogged = false;
|
|
@@ -13104,7 +13207,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
13104
13207
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
13105
13208
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
13106
13209
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
13107
|
-
const markerPath =
|
|
13210
|
+
const markerPath = join39(homedir17(), ".augmented", ".last-update-check");
|
|
13108
13211
|
if (!force) {
|
|
13109
13212
|
try {
|
|
13110
13213
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -13597,14 +13700,14 @@ async function checkClaudeAuth() {
|
|
|
13597
13700
|
}
|
|
13598
13701
|
var evalEmptyMcpConfigPath = null;
|
|
13599
13702
|
function ensureEvalEmptyMcpConfig() {
|
|
13600
|
-
if (evalEmptyMcpConfigPath &&
|
|
13601
|
-
const dir =
|
|
13703
|
+
if (evalEmptyMcpConfigPath && existsSync17(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
13704
|
+
const dir = join39(homedir17(), ".augmented");
|
|
13602
13705
|
try {
|
|
13603
|
-
|
|
13706
|
+
mkdirSync12(dir, { recursive: true });
|
|
13604
13707
|
} catch {
|
|
13605
13708
|
}
|
|
13606
|
-
const p =
|
|
13607
|
-
|
|
13709
|
+
const p = join39(dir, ".eval-empty-mcp.json");
|
|
13710
|
+
writeFileSync16(p, JSON.stringify({ mcpServers: {} }));
|
|
13608
13711
|
evalEmptyMcpConfigPath = p;
|
|
13609
13712
|
return p;
|
|
13610
13713
|
}
|
|
@@ -13698,10 +13801,10 @@ function resolveConversationEvalBackend() {
|
|
|
13698
13801
|
return conversationEvalBackend;
|
|
13699
13802
|
}
|
|
13700
13803
|
function getStateFile() {
|
|
13701
|
-
return
|
|
13804
|
+
return join39(config?.configDir ?? join39(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
13702
13805
|
}
|
|
13703
13806
|
function channelHashCacheDir() {
|
|
13704
|
-
return config?.configDir ??
|
|
13807
|
+
return config?.configDir ?? join39(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
13705
13808
|
}
|
|
13706
13809
|
function loadChannelHashCache2() {
|
|
13707
13810
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -13906,7 +14009,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
13906
14009
|
var _channelQuarantineStore = null;
|
|
13907
14010
|
function channelQuarantineStore() {
|
|
13908
14011
|
if (!_channelQuarantineStore) {
|
|
13909
|
-
const dir = config?.configDir ??
|
|
14012
|
+
const dir = config?.configDir ?? join39(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
13910
14013
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
13911
14014
|
}
|
|
13912
14015
|
return _channelQuarantineStore;
|
|
@@ -13922,12 +14025,12 @@ function claudeMdSizeFor(codeName) {
|
|
|
13922
14025
|
}
|
|
13923
14026
|
function forwardedToolsFor(codeName) {
|
|
13924
14027
|
if (!config?.configDir) return null;
|
|
13925
|
-
return readForwardedToolsReport(
|
|
14028
|
+
return readForwardedToolsReport(join39(config.configDir, codeName));
|
|
13926
14029
|
}
|
|
13927
14030
|
var _hostFlagStore = null;
|
|
13928
14031
|
function hostFlagStore() {
|
|
13929
14032
|
if (!_hostFlagStore) {
|
|
13930
|
-
const dir = config?.configDir ??
|
|
14033
|
+
const dir = config?.configDir ?? join39(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
13931
14034
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
13932
14035
|
}
|
|
13933
14036
|
return _hostFlagStore;
|
|
@@ -14000,13 +14103,13 @@ function parseSkillFrontmatter(content) {
|
|
|
14000
14103
|
return out;
|
|
14001
14104
|
}
|
|
14002
14105
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
14003
|
-
const { readdirSync:
|
|
14004
|
-
const skillsDir =
|
|
14005
|
-
const claudeMdPath =
|
|
14106
|
+
const { readdirSync: readdirSync11, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync17 } = await import("fs");
|
|
14107
|
+
const skillsDir = join39(configDir, codeName, "project", ".claude", "skills");
|
|
14108
|
+
const claudeMdPath = join39(configDir, codeName, "project", "CLAUDE.md");
|
|
14006
14109
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
14007
14110
|
const entries = [];
|
|
14008
|
-
for (const dir of
|
|
14009
|
-
const skillFile =
|
|
14111
|
+
for (const dir of readdirSync11(skillsDir).sort()) {
|
|
14112
|
+
const skillFile = join39(skillsDir, dir, "SKILL.md");
|
|
14010
14113
|
if (!ex(skillFile)) continue;
|
|
14011
14114
|
try {
|
|
14012
14115
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -14050,7 +14153,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
14050
14153
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
14051
14154
|
}
|
|
14052
14155
|
if (next !== current) {
|
|
14053
|
-
|
|
14156
|
+
writeFileSync17(claudeMdPath, next, "utf-8");
|
|
14054
14157
|
log2(
|
|
14055
14158
|
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)`
|
|
14056
14159
|
);
|
|
@@ -14073,7 +14176,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
14073
14176
|
if (codeNames.length === 0) return;
|
|
14074
14177
|
void (async () => {
|
|
14075
14178
|
try {
|
|
14076
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14179
|
+
const { collectDiagnostics } = await import("../persistent-session-GB3D5OIA.js");
|
|
14077
14180
|
await api.post("/host/heartbeat", {
|
|
14078
14181
|
host_id: hostId,
|
|
14079
14182
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
|
|
@@ -14191,7 +14294,7 @@ async function pollCycleInner() {
|
|
|
14191
14294
|
}
|
|
14192
14295
|
try {
|
|
14193
14296
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
14194
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14297
|
+
const { collectDiagnostics } = await import("../persistent-session-GB3D5OIA.js");
|
|
14195
14298
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
14196
14299
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
|
|
14197
14300
|
let tailscaleHostname;
|
|
@@ -14221,7 +14324,7 @@ async function pollCycleInner() {
|
|
|
14221
14324
|
claudeAuth = await detectClaudeAuth();
|
|
14222
14325
|
} catch (err) {
|
|
14223
14326
|
const errText = err instanceof Error ? err.message : String(err);
|
|
14224
|
-
const errId =
|
|
14327
|
+
const errId = createHash18("sha256").update(errText).digest("hex").slice(0, 12);
|
|
14225
14328
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
14226
14329
|
}
|
|
14227
14330
|
const hostHasClaudeCode = state8.agents.some(
|
|
@@ -14360,7 +14463,7 @@ async function pollCycleInner() {
|
|
|
14360
14463
|
collectPanelessActivityProbes,
|
|
14361
14464
|
getResponsivenessIntervalMs,
|
|
14362
14465
|
occupancyQualificationClassifications
|
|
14363
|
-
} = await import("../responsiveness-probe-
|
|
14466
|
+
} = await import("../responsiveness-probe-TDZDQXBU.js");
|
|
14364
14467
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
14365
14468
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
14366
14469
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -14470,7 +14573,7 @@ async function pollCycleInner() {
|
|
|
14470
14573
|
collectResponsivenessProbes,
|
|
14471
14574
|
livePendingInboundOldestAgeSeconds,
|
|
14472
14575
|
parkPendingInbound
|
|
14473
|
-
} = await import("../responsiveness-probe-
|
|
14576
|
+
} = await import("../responsiveness-probe-TDZDQXBU.js");
|
|
14474
14577
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
14475
14578
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
14476
14579
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -14559,13 +14662,13 @@ async function pollCycleInner() {
|
|
|
14559
14662
|
);
|
|
14560
14663
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
14561
14664
|
try {
|
|
14562
|
-
const paneTail =
|
|
14665
|
+
const paneTail = readFileSync30(paneLogPath(codeName), "utf8").slice(-65536);
|
|
14563
14666
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
14564
14667
|
if (transient) {
|
|
14565
|
-
const wedgeHome =
|
|
14566
|
-
if (
|
|
14668
|
+
const wedgeHome = join39(homedir17(), ".augmented", codeName);
|
|
14669
|
+
if (existsSync17(wedgeHome)) {
|
|
14567
14670
|
atomicWriteFileSync(
|
|
14568
|
-
|
|
14671
|
+
join39(wedgeHome, "watchdog-give-up.json"),
|
|
14569
14672
|
JSON.stringify({
|
|
14570
14673
|
gave_up_at: wedgeNow.toISOString(),
|
|
14571
14674
|
reason: "transient_overload"
|
|
@@ -14626,7 +14729,7 @@ async function pollCycleInner() {
|
|
|
14626
14729
|
}
|
|
14627
14730
|
try {
|
|
14628
14731
|
const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
|
|
14629
|
-
const { probeSessionAuth } = await import("../session-auth-dead-
|
|
14732
|
+
const { probeSessionAuth } = await import("../session-auth-dead-CPY4UZI7.js");
|
|
14630
14733
|
const observations = [];
|
|
14631
14734
|
const pendingCacheCommits = [];
|
|
14632
14735
|
const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
|
|
@@ -14881,7 +14984,7 @@ async function pollCycleInner() {
|
|
|
14881
14984
|
`[drain-flush] FAILED for '${prev.codeName}': ${err.message} \u2014 proceeding to teardown; this session was NOT shipped (ENG-9491)`
|
|
14882
14985
|
);
|
|
14883
14986
|
}
|
|
14884
|
-
const agentDir =
|
|
14987
|
+
const agentDir = join39(adapter.getAgentDir(prev.codeName), "provision");
|
|
14885
14988
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
14886
14989
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
14887
14990
|
}
|
|
@@ -14968,10 +15071,10 @@ async function pollCycleInner() {
|
|
|
14968
15071
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
14969
15072
|
// the watchdog, never fails the poll cycle.
|
|
14970
15073
|
signalGiveUp: (codeName) => {
|
|
14971
|
-
const dir =
|
|
14972
|
-
if (!
|
|
15074
|
+
const dir = join39(homedir17(), ".augmented", codeName);
|
|
15075
|
+
if (!existsSync17(dir)) return;
|
|
14973
15076
|
atomicWriteFileSync(
|
|
14974
|
-
|
|
15077
|
+
join39(dir, "watchdog-give-up.json"),
|
|
14975
15078
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
14976
15079
|
);
|
|
14977
15080
|
},
|
|
@@ -14990,9 +15093,9 @@ async function pollCycleInner() {
|
|
|
14990
15093
|
// parser elsewhere can only reconstruct an hour (ENG-8901).
|
|
14991
15094
|
signalUsageLimit: (codeName, resetsHint) => {
|
|
14992
15095
|
const dir = getFramework("claude-code").getAgentDir(codeName);
|
|
14993
|
-
if (!
|
|
15096
|
+
if (!existsSync17(dir)) return;
|
|
14994
15097
|
atomicWriteFileSync(
|
|
14995
|
-
|
|
15098
|
+
join39(dir, "watchdog-give-up.json"),
|
|
14996
15099
|
JSON.stringify({
|
|
14997
15100
|
gave_up_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14998
15101
|
reason: "usage_limit",
|
|
@@ -15254,7 +15357,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15254
15357
|
}
|
|
15255
15358
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15256
15359
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
15257
|
-
let agentDir =
|
|
15360
|
+
let agentDir = join39(adapter.getAgentDir(agent.code_name), "provision");
|
|
15258
15361
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
15259
15362
|
forgetChannelSyncState(agent.agent_id);
|
|
15260
15363
|
if (previousKnownStatus !== agent.status) {
|
|
@@ -15295,7 +15398,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15295
15398
|
const residuals = {
|
|
15296
15399
|
gatewayRunning: false,
|
|
15297
15400
|
portAllocated: false,
|
|
15298
|
-
provisionDirExists:
|
|
15401
|
+
provisionDirExists: existsSync17(agentDir)
|
|
15299
15402
|
};
|
|
15300
15403
|
if (!hasRevokedResiduals(residuals)) {
|
|
15301
15404
|
agentStates.push({
|
|
@@ -15383,8 +15486,28 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15383
15486
|
let refreshData;
|
|
15384
15487
|
try {
|
|
15385
15488
|
refreshData = await api.post("/host/refresh", {
|
|
15386
|
-
agent_id: agent.agent_id
|
|
15489
|
+
agent_id: agent.agent_id,
|
|
15490
|
+
// ENG-9585: ask for hashes instead of knowledge bodies. An API build that
|
|
15491
|
+
// predates the manifest ignores this and answers with `knowledge` as
|
|
15492
|
+
// before, which the resolution below handles without a version check.
|
|
15493
|
+
knowledge_manifest: true
|
|
15387
15494
|
});
|
|
15495
|
+
if (refreshData.knowledge_manifest) {
|
|
15496
|
+
const resolved = await resolveKnowledgeFromManifest({
|
|
15497
|
+
manifest: refreshData.knowledge_manifest,
|
|
15498
|
+
cacheDir: join39(config.configDir, "_knowledge"),
|
|
15499
|
+
delivery: refreshData.agent?.knowledge_delivery ?? "both",
|
|
15500
|
+
fetchContents: async (hashes) => {
|
|
15501
|
+
const res = await api.post(
|
|
15502
|
+
"/host/knowledge/contents",
|
|
15503
|
+
{ agent_id: agent.agent_id, hashes }
|
|
15504
|
+
);
|
|
15505
|
+
return res.contents ?? [];
|
|
15506
|
+
},
|
|
15507
|
+
log
|
|
15508
|
+
});
|
|
15509
|
+
refreshData.knowledge = resolved;
|
|
15510
|
+
}
|
|
15388
15511
|
} catch (err) {
|
|
15389
15512
|
log(`Refresh failed for '${agent.code_name}': ${err.message}`);
|
|
15390
15513
|
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
@@ -15429,7 +15552,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15429
15552
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
15430
15553
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
15431
15554
|
const frameworkAdapter = getFramework(frameworkId);
|
|
15432
|
-
agentDir =
|
|
15555
|
+
agentDir = join39(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
15433
15556
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
15434
15557
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
15435
15558
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -15485,9 +15608,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15485
15608
|
try {
|
|
15486
15609
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter, renderIntegrationsSection);
|
|
15487
15610
|
const changedFiles = [];
|
|
15488
|
-
|
|
15611
|
+
mkdirSync12(agentDir, { recursive: true });
|
|
15489
15612
|
for (const artifact of artifacts) {
|
|
15490
|
-
const filePath =
|
|
15613
|
+
const filePath = join39(agentDir, artifact.relativePath);
|
|
15491
15614
|
let existingHash;
|
|
15492
15615
|
let newHash;
|
|
15493
15616
|
let writeContent = artifact.content;
|
|
@@ -15506,8 +15629,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15506
15629
|
};
|
|
15507
15630
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
15508
15631
|
try {
|
|
15509
|
-
const projectClaudeMd =
|
|
15510
|
-
const existing =
|
|
15632
|
+
const projectClaudeMd = join39(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
15633
|
+
const existing = readFileSync30(projectClaudeMd, "utf-8");
|
|
15511
15634
|
existingHash = sha256(stripDynamicSections(existing));
|
|
15512
15635
|
} catch {
|
|
15513
15636
|
existingHash = null;
|
|
@@ -15525,7 +15648,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15525
15648
|
const generatorKeys = Object.keys(generatorServers);
|
|
15526
15649
|
let existingRaw = "";
|
|
15527
15650
|
try {
|
|
15528
|
-
existingRaw =
|
|
15651
|
+
existingRaw = readFileSync30(filePath, "utf-8");
|
|
15529
15652
|
} catch {
|
|
15530
15653
|
}
|
|
15531
15654
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -15541,7 +15664,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15541
15664
|
} else if (artifact.relativePath === "opencode.json") {
|
|
15542
15665
|
let existingRaw = null;
|
|
15543
15666
|
try {
|
|
15544
|
-
existingRaw =
|
|
15667
|
+
existingRaw = readFileSync30(filePath, "utf-8");
|
|
15545
15668
|
} catch {
|
|
15546
15669
|
}
|
|
15547
15670
|
const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
|
|
@@ -15557,26 +15680,26 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15557
15680
|
}
|
|
15558
15681
|
}
|
|
15559
15682
|
if (changedFiles.length > 0) {
|
|
15560
|
-
const isFirst = !
|
|
15683
|
+
const isFirst = !existsSync17(join39(agentDir, "CHARTER.md"));
|
|
15561
15684
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
15562
15685
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
15563
15686
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
15564
15687
|
for (const file of changedFiles) {
|
|
15565
|
-
const filePath =
|
|
15566
|
-
|
|
15688
|
+
const filePath = join39(agentDir, file.relativePath);
|
|
15689
|
+
mkdirSync12(dirname10(filePath), { recursive: true });
|
|
15567
15690
|
if (file.relativePath === ".mcp.json") {
|
|
15568
15691
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
15569
15692
|
} else {
|
|
15570
|
-
|
|
15693
|
+
writeFileSync16(filePath, file.content);
|
|
15571
15694
|
}
|
|
15572
15695
|
}
|
|
15573
15696
|
try {
|
|
15574
|
-
const provSkillsDir =
|
|
15575
|
-
if (
|
|
15576
|
-
for (const folder of
|
|
15697
|
+
const provSkillsDir = join39(agentDir, ".claude", "skills");
|
|
15698
|
+
if (existsSync17(provSkillsDir)) {
|
|
15699
|
+
for (const folder of readdirSync10(provSkillsDir)) {
|
|
15577
15700
|
if (folder.startsWith("knowledge-")) {
|
|
15578
15701
|
try {
|
|
15579
|
-
|
|
15702
|
+
rmSync6(join39(provSkillsDir, folder), { recursive: true });
|
|
15580
15703
|
} catch {
|
|
15581
15704
|
}
|
|
15582
15705
|
}
|
|
@@ -15589,7 +15712,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15589
15712
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
15590
15713
|
const hashes = /* @__PURE__ */ new Map();
|
|
15591
15714
|
for (const file of trackedFiles2) {
|
|
15592
|
-
const h = hashFile(
|
|
15715
|
+
const h = hashFile(join39(agentDir, file));
|
|
15593
15716
|
if (h) hashes.set(file, h);
|
|
15594
15717
|
}
|
|
15595
15718
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -15607,14 +15730,14 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15607
15730
|
}
|
|
15608
15731
|
if (Array.isArray(refreshData.workflows)) {
|
|
15609
15732
|
try {
|
|
15610
|
-
const provWorkflowsDir =
|
|
15611
|
-
if (
|
|
15733
|
+
const provWorkflowsDir = join39(agentDir, ".claude", "workflows");
|
|
15734
|
+
if (existsSync17(provWorkflowsDir)) {
|
|
15612
15735
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
15613
|
-
for (const file of
|
|
15736
|
+
for (const file of readdirSync10(provWorkflowsDir)) {
|
|
15614
15737
|
if (!file.endsWith(".js")) continue;
|
|
15615
15738
|
if (expected.has(file)) continue;
|
|
15616
15739
|
try {
|
|
15617
|
-
|
|
15740
|
+
rmSync6(join39(provWorkflowsDir, file));
|
|
15618
15741
|
} catch {
|
|
15619
15742
|
}
|
|
15620
15743
|
}
|
|
@@ -15693,10 +15816,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15693
15816
|
}
|
|
15694
15817
|
let lastDriftCheckAt = now;
|
|
15695
15818
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
15696
|
-
if (written &&
|
|
15819
|
+
if (written && existsSync17(agentDir)) {
|
|
15697
15820
|
const driftedFiles = [];
|
|
15698
15821
|
for (const [file, expectedHash] of written) {
|
|
15699
|
-
const localHash = hashFile(
|
|
15822
|
+
const localHash = hashFile(join39(agentDir, file));
|
|
15700
15823
|
if (localHash && localHash !== expectedHash) {
|
|
15701
15824
|
driftedFiles.push(file);
|
|
15702
15825
|
}
|
|
@@ -15707,7 +15830,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15707
15830
|
try {
|
|
15708
15831
|
const localHashes = {};
|
|
15709
15832
|
for (const file of driftedFiles) {
|
|
15710
|
-
localHashes[file] = hashFile(
|
|
15833
|
+
localHashes[file] = hashFile(join39(agentDir, file));
|
|
15711
15834
|
}
|
|
15712
15835
|
await api.post("/host/drift", {
|
|
15713
15836
|
agent_id: agent.agent_id,
|
|
@@ -15975,15 +16098,15 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15975
16098
|
const addedChannels = [...restartDecision.added];
|
|
15976
16099
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
15977
16100
|
try {
|
|
15978
|
-
const agentAugmentedDir =
|
|
15979
|
-
|
|
16101
|
+
const agentAugmentedDir = join39(homedir17(), ".augmented", agent.code_name);
|
|
16102
|
+
mkdirSync12(agentAugmentedDir, { recursive: true });
|
|
15980
16103
|
const markerJson = JSON.stringify({
|
|
15981
16104
|
version: 1,
|
|
15982
16105
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15983
16106
|
added: addedChannels
|
|
15984
16107
|
});
|
|
15985
16108
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
15986
|
-
atomicWriteFileSync(
|
|
16109
|
+
atomicWriteFileSync(join39(agentAugmentedDir, file), markerJson);
|
|
15987
16110
|
}
|
|
15988
16111
|
} catch (err) {
|
|
15989
16112
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -16059,7 +16182,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16059
16182
|
const behaviourSubset = extractMsTeamsBehaviourSubset(
|
|
16060
16183
|
msteamsEntry?.config
|
|
16061
16184
|
);
|
|
16062
|
-
const behaviourHash =
|
|
16185
|
+
const behaviourHash = createHash18("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
|
|
16063
16186
|
const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
|
|
16064
16187
|
const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
|
|
16065
16188
|
const behaviourDecision = decideSenderPolicyRestart({
|
|
@@ -16115,7 +16238,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16115
16238
|
const slackBehaviourSubset = extractSlackBehaviourSubset(
|
|
16116
16239
|
slackEntry?.config
|
|
16117
16240
|
);
|
|
16118
|
-
const slackBehaviourHash =
|
|
16241
|
+
const slackBehaviourHash = createHash18("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
|
|
16119
16242
|
const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
|
|
16120
16243
|
const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
|
|
16121
16244
|
const slackBehaviourDecision = decideSenderPolicyRestart({
|
|
@@ -16172,24 +16295,24 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16172
16295
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
16173
16296
|
try {
|
|
16174
16297
|
const agentProvisionDir = agentDir;
|
|
16175
|
-
const projectDir =
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
const provisionMcpPath =
|
|
16179
|
-
const projectMcpPath =
|
|
16298
|
+
const projectDir = join39(homedir17(), ".augmented", agent.code_name, "project");
|
|
16299
|
+
mkdirSync12(agentProvisionDir, { recursive: true });
|
|
16300
|
+
mkdirSync12(projectDir, { recursive: true });
|
|
16301
|
+
const provisionMcpPath = join39(agentProvisionDir, ".mcp.json");
|
|
16302
|
+
const projectMcpPath = join39(projectDir, ".mcp.json");
|
|
16180
16303
|
let mcpConfig = { mcpServers: {} };
|
|
16181
16304
|
try {
|
|
16182
|
-
mcpConfig = JSON.parse(
|
|
16305
|
+
mcpConfig = JSON.parse(readFileSync30(provisionMcpPath, "utf-8"));
|
|
16183
16306
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
16184
16307
|
} catch {
|
|
16185
16308
|
}
|
|
16186
|
-
const localDirectChatChannel =
|
|
16309
|
+
const localDirectChatChannel = join39(homedir17(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
16187
16310
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
16188
16311
|
const directChatTz = (() => {
|
|
16189
16312
|
const tz = directChatTeamSettings?.["timezone"];
|
|
16190
16313
|
return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
|
|
16191
16314
|
})();
|
|
16192
|
-
if (
|
|
16315
|
+
if (existsSync17(localDirectChatChannel)) {
|
|
16193
16316
|
const directChatEnv = {
|
|
16194
16317
|
AGT_HOST: requireHost(),
|
|
16195
16318
|
// ENG-5901 Track D: templated — the manager exports the real
|
|
@@ -16209,7 +16332,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16209
16332
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
16210
16333
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
16211
16334
|
// so it byte-matches the broker readers' path.
|
|
16212
|
-
AGT_TURN_INITIATOR_FILE:
|
|
16335
|
+
AGT_TURN_INITIATOR_FILE: join39(
|
|
16213
16336
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
16214
16337
|
".current-turn-initiator.json"
|
|
16215
16338
|
)
|
|
@@ -16229,10 +16352,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16229
16352
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
16230
16353
|
}
|
|
16231
16354
|
}
|
|
16232
|
-
const staleChannelsPath =
|
|
16233
|
-
if (
|
|
16355
|
+
const staleChannelsPath = join39(projectDir, ".mcp-channels.json");
|
|
16356
|
+
if (existsSync17(staleChannelsPath)) {
|
|
16234
16357
|
try {
|
|
16235
|
-
|
|
16358
|
+
rmSync6(staleChannelsPath, { force: true });
|
|
16236
16359
|
} catch {
|
|
16237
16360
|
}
|
|
16238
16361
|
}
|
|
@@ -16319,7 +16442,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16319
16442
|
}
|
|
16320
16443
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
16321
16444
|
try {
|
|
16322
|
-
const probeProjectDir =
|
|
16445
|
+
const probeProjectDir = join39(homedir17(), ".augmented", agent.code_name, "project");
|
|
16323
16446
|
let probeSet = integrations;
|
|
16324
16447
|
try {
|
|
16325
16448
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -16365,7 +16488,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16365
16488
|
const forceDue = attemptsLeft > 0;
|
|
16366
16489
|
let probeRan = false;
|
|
16367
16490
|
try {
|
|
16368
|
-
const probeProjectDir =
|
|
16491
|
+
const probeProjectDir = join39(homedir17(), ".augmented", agent.code_name, "project");
|
|
16369
16492
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
16370
16493
|
} catch (err) {
|
|
16371
16494
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -16442,11 +16565,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16442
16565
|
const intHash = computeIntegrationsHash(integrations);
|
|
16443
16566
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
16444
16567
|
if (intHash !== prevIntHash) {
|
|
16445
|
-
const projectDir =
|
|
16446
|
-
const envIntPath =
|
|
16568
|
+
const projectDir = join39(homedir17(), ".augmented", agent.code_name, "project");
|
|
16569
|
+
const envIntPath = join39(projectDir, ".env.integrations");
|
|
16447
16570
|
let preWriteEnv;
|
|
16448
16571
|
try {
|
|
16449
|
-
preWriteEnv =
|
|
16572
|
+
preWriteEnv = readFileSync30(envIntPath, "utf-8");
|
|
16450
16573
|
} catch {
|
|
16451
16574
|
preWriteEnv = void 0;
|
|
16452
16575
|
}
|
|
@@ -16465,9 +16588,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16465
16588
|
}
|
|
16466
16589
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
16467
16590
|
try {
|
|
16468
|
-
const projectMcpPath =
|
|
16469
|
-
const postWriteEnv =
|
|
16470
|
-
const mcpContent =
|
|
16591
|
+
const projectMcpPath = join39(projectDir, ".mcp.json");
|
|
16592
|
+
const postWriteEnv = readFileSync30(envIntPath, "utf-8");
|
|
16593
|
+
const mcpContent = readFileSync30(projectMcpPath, "utf-8");
|
|
16471
16594
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
16472
16595
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
16473
16596
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -16557,10 +16680,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16557
16680
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
16558
16681
|
}
|
|
16559
16682
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
16560
|
-
const headersHash =
|
|
16683
|
+
const headersHash = createHash18("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
16561
16684
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
16562
16685
|
}).join("\n");
|
|
16563
|
-
const mcpHash =
|
|
16686
|
+
const mcpHash = createHash18("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
16564
16687
|
const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
|
|
16565
16688
|
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
16566
16689
|
const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
|
|
@@ -16575,7 +16698,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16575
16698
|
if (mcpHash !== prevMcpHash) {
|
|
16576
16699
|
for (const e of desiredEntries) {
|
|
16577
16700
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
16578
|
-
const urlHash =
|
|
16701
|
+
const urlHash = createHash18("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
16579
16702
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
16580
16703
|
}
|
|
16581
16704
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.readMcpServers) {
|
|
@@ -16655,7 +16778,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16655
16778
|
if (missing.length > 0) {
|
|
16656
16779
|
log(`Auto-provisioned ${missing.length} default schedule(s) for '${agent.code_name}': ${missing.map((s) => s.template_id).join(", ")}`);
|
|
16657
16780
|
}
|
|
16658
|
-
const freshData = await api.post("/host/refresh", {
|
|
16781
|
+
const freshData = await api.post("/host/refresh", {
|
|
16782
|
+
agent_id: agent.agent_id,
|
|
16783
|
+
knowledge_manifest: true
|
|
16784
|
+
});
|
|
16659
16785
|
tasks = freshData.scheduled_tasks ?? tasks;
|
|
16660
16786
|
}
|
|
16661
16787
|
} catch (err) {
|
|
@@ -16678,7 +16804,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16678
16804
|
if (frameworkAdapter.installSkillFiles) {
|
|
16679
16805
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
16680
16806
|
const installedIntegrationSkills = [];
|
|
16681
|
-
const { createHash:
|
|
16807
|
+
const { createHash: createHash19 } = await import("crypto");
|
|
16682
16808
|
const refreshAny = refreshData;
|
|
16683
16809
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
16684
16810
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -16707,7 +16833,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16707
16833
|
)
|
|
16708
16834
|
}));
|
|
16709
16835
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
16710
|
-
const contentHash =
|
|
16836
|
+
const contentHash = createHash19("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
16711
16837
|
if (!shouldWriteIntegrationSkill(
|
|
16712
16838
|
agentState.knownSkillHashes,
|
|
16713
16839
|
agent.agent_id,
|
|
@@ -16730,23 +16856,23 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16730
16856
|
}
|
|
16731
16857
|
}
|
|
16732
16858
|
try {
|
|
16733
|
-
const { readdirSync:
|
|
16859
|
+
const { readdirSync: readdirSync11, rmSync: rmSync7 } = await import("fs");
|
|
16734
16860
|
const { homedir: homedir18 } = await import("os");
|
|
16735
16861
|
const frameworkId2 = frameworkAdapter.id;
|
|
16736
16862
|
const candidateSkillDirs = [
|
|
16737
16863
|
// Claude Code — framework runtime tree
|
|
16738
|
-
|
|
16864
|
+
join39(homedir18(), ".augmented", agent.code_name, "skills"),
|
|
16739
16865
|
// Claude Code — project tree
|
|
16740
|
-
|
|
16866
|
+
join39(homedir18(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
16741
16867
|
// Defensive: legacy provision-side path, not currently an
|
|
16742
16868
|
// install target but cheap to sweep.
|
|
16743
|
-
|
|
16869
|
+
join39(agentDir, ".claude", "skills")
|
|
16744
16870
|
];
|
|
16745
|
-
const existingDirs = candidateSkillDirs.filter((d) =>
|
|
16871
|
+
const existingDirs = candidateSkillDirs.filter((d) => existsSync17(d));
|
|
16746
16872
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
16747
16873
|
for (const dir of existingDirs) {
|
|
16748
16874
|
try {
|
|
16749
|
-
for (const entry of
|
|
16875
|
+
for (const entry of readdirSync11(dir)) {
|
|
16750
16876
|
if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
|
|
16751
16877
|
discoveredEntries.add(entry);
|
|
16752
16878
|
}
|
|
@@ -16761,8 +16887,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16761
16887
|
entry,
|
|
16762
16888
|
dirs: existingDirs,
|
|
16763
16889
|
removeDir: (p) => {
|
|
16764
|
-
if (
|
|
16765
|
-
|
|
16890
|
+
if (existsSync17(p)) {
|
|
16891
|
+
rmSync7(p, { recursive: true, force: true });
|
|
16766
16892
|
}
|
|
16767
16893
|
}
|
|
16768
16894
|
});
|
|
@@ -16781,7 +16907,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16781
16907
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
16782
16908
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
16783
16909
|
const manifestPath = managedSkillManifestPath(
|
|
16784
|
-
|
|
16910
|
+
join39(homedir17(), ".augmented", agent.code_name)
|
|
16785
16911
|
);
|
|
16786
16912
|
const prevIds = /* @__PURE__ */ new Set([
|
|
16787
16913
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -16790,7 +16916,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16790
16916
|
const plan = planGlobalSkillSync(
|
|
16791
16917
|
[...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
|
|
16792
16918
|
prevIds,
|
|
16793
|
-
(content) =>
|
|
16919
|
+
(content) => createHash19("sha256").update(content).digest("hex").slice(0, 12),
|
|
16794
16920
|
(skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
|
|
16795
16921
|
{ desiredResolved }
|
|
16796
16922
|
);
|
|
@@ -16801,16 +16927,16 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16801
16927
|
}
|
|
16802
16928
|
if (plan.removes.length) {
|
|
16803
16929
|
const globalSkillDirs = [
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16930
|
+
join39(homedir17(), ".augmented", agent.code_name, "skills"),
|
|
16931
|
+
join39(homedir17(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
16932
|
+
join39(agentDir, ".claude", "skills")
|
|
16807
16933
|
];
|
|
16808
16934
|
for (const id of plan.removes) {
|
|
16809
16935
|
let prunedAny = false;
|
|
16810
16936
|
for (const dir of globalSkillDirs) {
|
|
16811
|
-
const p =
|
|
16812
|
-
if (
|
|
16813
|
-
|
|
16937
|
+
const p = join39(dir, id);
|
|
16938
|
+
if (existsSync17(p) && existsSync17(join39(p, "SKILL.md"))) {
|
|
16939
|
+
rmSync6(p, { recursive: true, force: true });
|
|
16814
16940
|
prunedAny = true;
|
|
16815
16941
|
}
|
|
16816
16942
|
}
|
|
@@ -16841,7 +16967,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16841
16967
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
16842
16968
|
if (!slug) continue;
|
|
16843
16969
|
try {
|
|
16844
|
-
const scriptHash =
|
|
16970
|
+
const scriptHash = createHash19("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
16845
16971
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
16846
16972
|
if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
16847
16973
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -16856,9 +16982,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16856
16982
|
} else if (result.timedOut) {
|
|
16857
16983
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
16858
16984
|
} else {
|
|
16859
|
-
const stderrHash =
|
|
16985
|
+
const stderrHash = createHash19("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
16860
16986
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
16861
|
-
const missingCmdHash = missingCmd ?
|
|
16987
|
+
const missingCmdHash = missingCmd ? createHash19("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
16862
16988
|
log(
|
|
16863
16989
|
`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}]`
|
|
16864
16990
|
);
|
|
@@ -17045,8 +17171,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17045
17171
|
const sess = getSessionState(agent.code_name);
|
|
17046
17172
|
let mcpJsonParsed = null;
|
|
17047
17173
|
try {
|
|
17048
|
-
const mcpPath =
|
|
17049
|
-
mcpJsonParsed = JSON.parse(
|
|
17174
|
+
const mcpPath = join39(getProjectDir(agent.code_name), ".mcp.json");
|
|
17175
|
+
mcpJsonParsed = JSON.parse(readFileSync30(mcpPath, "utf-8"));
|
|
17050
17176
|
} catch {
|
|
17051
17177
|
}
|
|
17052
17178
|
reapMissingMcpSessions({
|
|
@@ -17429,7 +17555,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17429
17555
|
freshDoneIds.add(item.id);
|
|
17430
17556
|
}
|
|
17431
17557
|
} catch (err) {
|
|
17432
|
-
const errId =
|
|
17558
|
+
const errId = createHash18("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
|
|
17433
17559
|
log(`Reap API error for item_id=${item.id} error_id=${errId}`);
|
|
17434
17560
|
}
|
|
17435
17561
|
if (reapAction === "dead_letter") {
|
|
@@ -17477,10 +17603,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
17477
17603
|
}
|
|
17478
17604
|
}
|
|
17479
17605
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
17480
|
-
if (trackedFiles.length > 0 &&
|
|
17606
|
+
if (trackedFiles.length > 0 && existsSync17(agentDir)) {
|
|
17481
17607
|
const hashes = /* @__PURE__ */ new Map();
|
|
17482
17608
|
for (const file of trackedFiles) {
|
|
17483
|
-
const h = hashFile(
|
|
17609
|
+
const h = hashFile(join39(agentDir, file));
|
|
17484
17610
|
if (h) hashes.set(file, h);
|
|
17485
17611
|
}
|
|
17486
17612
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -17495,7 +17621,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
17495
17621
|
refreshData.agent.onboarding_state
|
|
17496
17622
|
);
|
|
17497
17623
|
const obStep = obState.step;
|
|
17498
|
-
const markerPath =
|
|
17624
|
+
const markerPath = join39(homedir17(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
17499
17625
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
17500
17626
|
const obContactRaw = refreshData.agent.manager_last_contacted_at;
|
|
17501
17627
|
const obContact = typeof obContactRaw === "string" && obContactRaw ? obContactRaw : null;
|
|
@@ -17597,7 +17723,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
17597
17723
|
}
|
|
17598
17724
|
stopOpencodeSlackIngest(codeName, log);
|
|
17599
17725
|
stopOpencodeTelegramIngest(codeName, log);
|
|
17600
|
-
const opencodeProjectDir =
|
|
17726
|
+
const opencodeProjectDir = join39(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
17601
17727
|
const serveEnv = {
|
|
17602
17728
|
AGT_HOST: requireHost(),
|
|
17603
17729
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -17652,8 +17778,8 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
17652
17778
|
});
|
|
17653
17779
|
}
|
|
17654
17780
|
const projectDir = getProjectDir(codeName);
|
|
17655
|
-
const mcpConfigPath =
|
|
17656
|
-
const claudeMdPath =
|
|
17781
|
+
const mcpConfigPath = join39(projectDir, ".mcp.json");
|
|
17782
|
+
const claudeMdPath = join39(projectDir, "CLAUDE.md");
|
|
17657
17783
|
if (restartBreaker.isTripped(codeName)) {
|
|
17658
17784
|
const trip = restartBreaker.getTrip(codeName);
|
|
17659
17785
|
return {
|
|
@@ -17902,7 +18028,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
17902
18028
|
const ctx = getLastFailureContext(codeName);
|
|
17903
18029
|
const recovery = prepareForRespawn(codeName);
|
|
17904
18030
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
17905
|
-
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${
|
|
18031
|
+
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash18("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
|
|
17906
18032
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
17907
18033
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
17908
18034
|
log(
|
|
@@ -17916,7 +18042,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash17("sha256")
|
|
|
17916
18042
|
);
|
|
17917
18043
|
getHostId().then((hostId) => {
|
|
17918
18044
|
if (!hostId) return;
|
|
17919
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
18045
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash18("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
17920
18046
|
return api.post("/host/events", {
|
|
17921
18047
|
host_id: hostId,
|
|
17922
18048
|
agent_code_name: codeName,
|
|
@@ -18113,7 +18239,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash17("sha256")
|
|
|
18113
18239
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
18114
18240
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
18115
18241
|
}
|
|
18116
|
-
const stableTasksHash =
|
|
18242
|
+
const stableTasksHash = createHash18("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
18117
18243
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
18118
18244
|
if (stableTasksHash !== prevHash) {
|
|
18119
18245
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
@@ -18428,7 +18554,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
18428
18554
|
void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
|
|
18429
18555
|
void (async () => {
|
|
18430
18556
|
try {
|
|
18431
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
18557
|
+
const { collectDiagnostics } = await import("../persistent-session-GB3D5OIA.js");
|
|
18432
18558
|
await api.post("/host/heartbeat", {
|
|
18433
18559
|
host_id: hostId,
|
|
18434
18560
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
|
|
@@ -18479,7 +18605,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
18479
18605
|
}
|
|
18480
18606
|
try {
|
|
18481
18607
|
const hostId = await getHostId();
|
|
18482
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
18608
|
+
const { collectDiagnostics } = await import("../persistent-session-GB3D5OIA.js");
|
|
18483
18609
|
await api.post("/host/heartbeat", {
|
|
18484
18610
|
host_id: hostId,
|
|
18485
18611
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
|
|
@@ -18587,7 +18713,7 @@ function ensureRealtimeKanbanStarted(agentStates) {
|
|
|
18587
18713
|
);
|
|
18588
18714
|
}
|
|
18589
18715
|
}).catch((err) => {
|
|
18590
|
-
const errId =
|
|
18716
|
+
const errId = createHash18("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
|
|
18591
18717
|
log(
|
|
18592
18718
|
`[realtime] Work trigger enqueue threw for '${agent.codeName}' item_id=${item.id} error_id=${errId} \u2014 hybrid nudge will retry`
|
|
18593
18719
|
);
|
|
@@ -18877,8 +19003,8 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
18877
19003
|
if (useDoorbell) {
|
|
18878
19004
|
try {
|
|
18879
19005
|
const doorbell = directChatDoorbellPath(agent.agentId, homedir17());
|
|
18880
|
-
|
|
18881
|
-
|
|
19006
|
+
mkdirSync12(dirname10(doorbell), { recursive: true });
|
|
19007
|
+
writeFileSync16(doorbell, String(Date.now()));
|
|
18882
19008
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
18883
19009
|
return;
|
|
18884
19010
|
} catch (err) {
|
|
@@ -19006,8 +19132,8 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
19006
19132
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
19007
19133
|
try {
|
|
19008
19134
|
const doorbell = directChatDoorbellPath(agentId, homedir17());
|
|
19009
|
-
|
|
19010
|
-
|
|
19135
|
+
mkdirSync12(dirname10(doorbell), { recursive: true });
|
|
19136
|
+
writeFileSync16(doorbell, String(Date.now()));
|
|
19011
19137
|
} catch (err) {
|
|
19012
19138
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
19013
19139
|
}
|
|
@@ -19111,7 +19237,7 @@ async function processClaudePairSessions(agents) {
|
|
|
19111
19237
|
killPairSession,
|
|
19112
19238
|
pairTmuxSession,
|
|
19113
19239
|
finalizeClaudePairOnboarding
|
|
19114
|
-
} = await import("../claude-pair-runtime-
|
|
19240
|
+
} = await import("../claude-pair-runtime-KWBCSCZO.js");
|
|
19115
19241
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
19116
19242
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
19117
19243
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -19336,17 +19462,17 @@ var lastDownloadHash = /* @__PURE__ */ new Map();
|
|
|
19336
19462
|
var lastLocalFileHash = /* @__PURE__ */ new Map();
|
|
19337
19463
|
var memoryManifests = /* @__PURE__ */ new Map();
|
|
19338
19464
|
function memoryRetirementDir(configDir, codeName) {
|
|
19339
|
-
return
|
|
19465
|
+
return join39(configDir, "_memory-retirement", codeName);
|
|
19340
19466
|
}
|
|
19341
19467
|
function memoryManifestPath(configDir, codeName) {
|
|
19342
|
-
return
|
|
19468
|
+
return join39(memoryRetirementDir(configDir, codeName), "manifest.json");
|
|
19343
19469
|
}
|
|
19344
19470
|
function loadMemoryManifest(agentId, configDir, codeName) {
|
|
19345
19471
|
const cached = memoryManifests.get(agentId);
|
|
19346
19472
|
if (cached) return cached;
|
|
19347
19473
|
let manifest = {};
|
|
19348
19474
|
try {
|
|
19349
|
-
const raw =
|
|
19475
|
+
const raw = readFileSync30(memoryManifestPath(configDir, codeName), "utf-8");
|
|
19350
19476
|
const parsed = JSON.parse(raw);
|
|
19351
19477
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
19352
19478
|
for (const [name, entry] of Object.entries(parsed)) {
|
|
@@ -19366,15 +19492,15 @@ function saveMemoryManifest(agentId, configDir, codeName) {
|
|
|
19366
19492
|
if (!manifest) return;
|
|
19367
19493
|
try {
|
|
19368
19494
|
const path = memoryManifestPath(configDir, codeName);
|
|
19369
|
-
|
|
19495
|
+
mkdirSync12(memoryRetirementDir(configDir, codeName), { recursive: true });
|
|
19370
19496
|
const tmp = `${path}.tmp`;
|
|
19371
|
-
|
|
19372
|
-
|
|
19497
|
+
writeFileSync16(tmp, JSON.stringify(manifest, null, 2));
|
|
19498
|
+
renameSync9(tmp, path);
|
|
19373
19499
|
} catch {
|
|
19374
19500
|
}
|
|
19375
19501
|
}
|
|
19376
19502
|
function retiredMemoryDir(configDir, codeName) {
|
|
19377
|
-
return
|
|
19503
|
+
return join39(memoryRetirementDir(configDir, codeName), "retired");
|
|
19378
19504
|
}
|
|
19379
19505
|
var RETIRED_MEMORY_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
19380
19506
|
var lastRetirementReport = /* @__PURE__ */ new Map();
|
|
@@ -19452,15 +19578,15 @@ function applyMemoryTombstones(opts) {
|
|
|
19452
19578
|
log2(`[memory-retire] ${agent.code_name}: KEPT '${tomb.name}' \u2014 no write record, not ours to remove`);
|
|
19453
19579
|
continue;
|
|
19454
19580
|
}
|
|
19455
|
-
const filePath =
|
|
19456
|
-
if (!
|
|
19581
|
+
const filePath = join39(memoryDir, entry.file);
|
|
19582
|
+
if (!existsSync17(filePath)) {
|
|
19457
19583
|
outcomes.already_gone++;
|
|
19458
19584
|
delete manifest[tomb.name];
|
|
19459
19585
|
manifestDirty = true;
|
|
19460
19586
|
continue;
|
|
19461
19587
|
}
|
|
19462
19588
|
try {
|
|
19463
|
-
const actual =
|
|
19589
|
+
const actual = createHash18("sha256").update(readFileSync30(filePath)).digest("hex");
|
|
19464
19590
|
if (actual !== entry.sha) {
|
|
19465
19591
|
outcomes.kept_modified++;
|
|
19466
19592
|
outcomes.unapplied.push({ name: tomb.name, reason: "kept_modified" });
|
|
@@ -19470,16 +19596,16 @@ function applyMemoryTombstones(opts) {
|
|
|
19470
19596
|
continue;
|
|
19471
19597
|
}
|
|
19472
19598
|
const destDir = retiredMemoryDir(configDir, agent.code_name);
|
|
19473
|
-
|
|
19599
|
+
mkdirSync12(destDir, { recursive: true });
|
|
19474
19600
|
const stamp = Date.now();
|
|
19475
|
-
let dest =
|
|
19476
|
-
for (let n = 1;
|
|
19477
|
-
dest =
|
|
19601
|
+
let dest = join39(destDir, `${entry.file}.${stamp}.retired`);
|
|
19602
|
+
for (let n = 1; existsSync17(dest); n++) {
|
|
19603
|
+
dest = join39(destDir, `${entry.file}.${stamp}-${n}.retired`);
|
|
19478
19604
|
}
|
|
19479
|
-
|
|
19605
|
+
renameSync9(filePath, dest);
|
|
19480
19606
|
try {
|
|
19481
19607
|
const now = Date.now() / 1e3;
|
|
19482
|
-
|
|
19608
|
+
utimesSync2(dest, now, now);
|
|
19483
19609
|
} catch {
|
|
19484
19610
|
}
|
|
19485
19611
|
delete manifest[tomb.name];
|
|
@@ -19507,15 +19633,15 @@ function applyMemoryTombstones(opts) {
|
|
|
19507
19633
|
}
|
|
19508
19634
|
function reapRetiredMemories(configDir, codeName, log2) {
|
|
19509
19635
|
const dir = retiredMemoryDir(configDir, codeName);
|
|
19510
|
-
if (!
|
|
19636
|
+
if (!existsSync17(dir)) return;
|
|
19511
19637
|
const cutoff = Date.now() - RETIRED_MEMORY_TTL_MS;
|
|
19512
19638
|
let reaped = 0;
|
|
19513
19639
|
try {
|
|
19514
|
-
for (const file of
|
|
19640
|
+
for (const file of readdirSync10(dir)) {
|
|
19515
19641
|
if (!file.endsWith(".retired")) continue;
|
|
19516
|
-
const path =
|
|
19642
|
+
const path = join39(dir, file);
|
|
19517
19643
|
try {
|
|
19518
|
-
if (
|
|
19644
|
+
if (statSync9(path).mtimeMs < cutoff) {
|
|
19519
19645
|
unlinkSync6(path);
|
|
19520
19646
|
reaped++;
|
|
19521
19647
|
}
|
|
@@ -19528,8 +19654,8 @@ function reapRetiredMemories(configDir, codeName, log2) {
|
|
|
19528
19654
|
if (reaped > 0) log2(`[memory-retire] ${codeName}: reaped ${reaped} retired memory file(s) past TTL`);
|
|
19529
19655
|
}
|
|
19530
19656
|
async function syncMemories(agent, configDir, log2) {
|
|
19531
|
-
const projectDir =
|
|
19532
|
-
const memoryDir =
|
|
19657
|
+
const projectDir = join39(configDir, agent.code_name, "project");
|
|
19658
|
+
const memoryDir = join39(projectDir, "memory");
|
|
19533
19659
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
19534
19660
|
if (isFreshSync) {
|
|
19535
19661
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -19553,15 +19679,15 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19553
19679
|
}
|
|
19554
19680
|
pendingFreshMemorySync.delete(agent.agent_id);
|
|
19555
19681
|
}
|
|
19556
|
-
if (
|
|
19682
|
+
if (existsSync17(memoryDir)) {
|
|
19557
19683
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
19558
19684
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
19559
19685
|
const changedMemories = [];
|
|
19560
|
-
for (const file of
|
|
19686
|
+
for (const file of readdirSync10(memoryDir)) {
|
|
19561
19687
|
if (!file.endsWith(".md")) continue;
|
|
19562
19688
|
try {
|
|
19563
|
-
const raw =
|
|
19564
|
-
const fileHash =
|
|
19689
|
+
const raw = readFileSync30(join39(memoryDir, file), "utf-8");
|
|
19690
|
+
const fileHash = createHash18("sha256").update(raw).digest("hex").slice(0, 16);
|
|
19565
19691
|
currentHashes.set(file, fileHash);
|
|
19566
19692
|
if (prevHashes.get(file) === fileHash) continue;
|
|
19567
19693
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -19585,7 +19711,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19585
19711
|
} catch (err) {
|
|
19586
19712
|
for (const mem of changedMemories) {
|
|
19587
19713
|
for (const [file] of currentHashes) {
|
|
19588
|
-
const parsed = parseMemoryFile(
|
|
19714
|
+
const parsed = parseMemoryFile(readFileSync30(join39(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
19589
19715
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
19590
19716
|
}
|
|
19591
19717
|
}
|
|
@@ -19611,8 +19737,8 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
19611
19737
|
}
|
|
19612
19738
|
}
|
|
19613
19739
|
async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
19614
|
-
const localFiles =
|
|
19615
|
-
const localListHash =
|
|
19740
|
+
const localFiles = existsSync17(memoryDir) ? readdirSync10(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
19741
|
+
const localListHash = createHash18("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
19616
19742
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
19617
19743
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
19618
19744
|
try {
|
|
@@ -19620,14 +19746,14 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
19620
19746
|
agent_id: agent.agent_id
|
|
19621
19747
|
});
|
|
19622
19748
|
const tombstones = Array.isArray(dbMemories.tombstones) ? dbMemories.tombstones : null;
|
|
19623
|
-
const responseHash =
|
|
19749
|
+
const responseHash = createHash18("sha256").update(JSON.stringify({ m: dbMemories.memories ?? [], t: tombstones })).digest("hex").slice(0, 16);
|
|
19624
19750
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
19625
19751
|
return { status: "skipped", tombstones, truncated: dbMemories.tombstones_truncated === true };
|
|
19626
19752
|
}
|
|
19627
19753
|
lastDownloadHash.set(agent.agent_id, responseHash);
|
|
19628
19754
|
lastLocalFileHash.set(agent.agent_id, localListHash);
|
|
19629
19755
|
if (dbMemories.memories?.length) {
|
|
19630
|
-
|
|
19756
|
+
mkdirSync12(memoryDir, { recursive: true });
|
|
19631
19757
|
const manifest = loadMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19632
19758
|
let written = 0;
|
|
19633
19759
|
let overwritten = 0;
|
|
@@ -19636,7 +19762,7 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
19636
19762
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
19637
19763
|
const slug = rawSlug || `memory-${i}`;
|
|
19638
19764
|
const fileName = `${slug}.md`;
|
|
19639
|
-
const filePath =
|
|
19765
|
+
const filePath = join39(memoryDir, fileName);
|
|
19640
19766
|
const desired = `---
|
|
19641
19767
|
name: ${JSON.stringify(mem.name)}
|
|
19642
19768
|
type: ${mem.type}
|
|
@@ -19646,17 +19772,17 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
|
|
|
19646
19772
|
${mem.content}
|
|
19647
19773
|
`;
|
|
19648
19774
|
const record = () => {
|
|
19649
|
-
const sha =
|
|
19775
|
+
const sha = createHash18("sha256").update(desired).digest("hex");
|
|
19650
19776
|
const prev = manifest[mem.name];
|
|
19651
19777
|
if (prev?.file === fileName && prev.sha === sha) return false;
|
|
19652
19778
|
manifest[mem.name] = { file: fileName, sha };
|
|
19653
19779
|
return true;
|
|
19654
19780
|
};
|
|
19655
19781
|
let manifestDirty = false;
|
|
19656
|
-
if (
|
|
19782
|
+
if (existsSync17(filePath)) {
|
|
19657
19783
|
let existing = "";
|
|
19658
19784
|
try {
|
|
19659
|
-
existing =
|
|
19785
|
+
existing = readFileSync30(filePath, "utf-8");
|
|
19660
19786
|
} catch {
|
|
19661
19787
|
}
|
|
19662
19788
|
if (existing === desired) {
|
|
@@ -19664,18 +19790,18 @@ ${mem.content}
|
|
|
19664
19790
|
if (manifestDirty) saveMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19665
19791
|
continue;
|
|
19666
19792
|
}
|
|
19667
|
-
|
|
19793
|
+
writeFileSync16(filePath, desired);
|
|
19668
19794
|
overwritten++;
|
|
19669
19795
|
} else {
|
|
19670
|
-
|
|
19796
|
+
writeFileSync16(filePath, desired);
|
|
19671
19797
|
written++;
|
|
19672
19798
|
}
|
|
19673
19799
|
if (record()) manifestDirty = true;
|
|
19674
19800
|
if (manifestDirty) saveMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
19675
19801
|
}
|
|
19676
19802
|
if (written > 0 || overwritten > 0) {
|
|
19677
|
-
const updatedFiles =
|
|
19678
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
19803
|
+
const updatedFiles = readdirSync10(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
19804
|
+
lastLocalFileHash.set(agent.agent_id, createHash18("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
19679
19805
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
19680
19806
|
}
|
|
19681
19807
|
}
|
|
@@ -19686,9 +19812,9 @@ ${mem.content}
|
|
|
19686
19812
|
}
|
|
19687
19813
|
}
|
|
19688
19814
|
async function cleanupAgentFiles(codeName, agentDir) {
|
|
19689
|
-
if (
|
|
19815
|
+
if (existsSync17(agentDir)) {
|
|
19690
19816
|
try {
|
|
19691
|
-
|
|
19817
|
+
rmSync6(agentDir, { recursive: true, force: true });
|
|
19692
19818
|
log(`Removed provision directory for '${codeName}'`);
|
|
19693
19819
|
} catch (err) {
|
|
19694
19820
|
log(`Failed to remove provision dir for '${codeName}': ${err.message}`);
|
|
@@ -19956,8 +20082,8 @@ function startManager(opts) {
|
|
|
19956
20082
|
config = opts;
|
|
19957
20083
|
try {
|
|
19958
20084
|
const stateFile = getStateFile();
|
|
19959
|
-
if (
|
|
19960
|
-
const raw =
|
|
20085
|
+
if (existsSync17(stateFile)) {
|
|
20086
|
+
const raw = readFileSync30(stateFile, "utf-8");
|
|
19961
20087
|
const parsed = JSON.parse(raw);
|
|
19962
20088
|
if (Array.isArray(parsed.agents)) {
|
|
19963
20089
|
state8.agents = parsed.agents;
|
|
@@ -19984,7 +20110,7 @@ function startManager(opts) {
|
|
|
19984
20110
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
19985
20111
|
}
|
|
19986
20112
|
log(
|
|
19987
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
20113
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join39(homedir17(), ".augmented", "manager.log")}`
|
|
19988
20114
|
);
|
|
19989
20115
|
deployMcpAssets();
|
|
19990
20116
|
reapOrphanChannelMcps({ log });
|
|
@@ -20013,7 +20139,7 @@ async function reapOrphanedClaudePids() {
|
|
|
20013
20139
|
const looksLikeClaude = (pid) => {
|
|
20014
20140
|
if (process.platform !== "linux") return true;
|
|
20015
20141
|
try {
|
|
20016
|
-
const comm =
|
|
20142
|
+
const comm = readFileSync30(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
20017
20143
|
return comm.includes("claude");
|
|
20018
20144
|
} catch {
|
|
20019
20145
|
return false;
|
|
@@ -20110,14 +20236,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
20110
20236
|
}
|
|
20111
20237
|
}
|
|
20112
20238
|
function deployMcpAssets() {
|
|
20113
|
-
const targetDir =
|
|
20114
|
-
|
|
20239
|
+
const targetDir = join39(homedir17(), ".augmented", "_mcp");
|
|
20240
|
+
mkdirSync12(targetDir, { recursive: true });
|
|
20115
20241
|
const moduleDir = dirname10(fileURLToPath(import.meta.url));
|
|
20116
20242
|
let mcpSourceDir = "";
|
|
20117
20243
|
let dir = moduleDir;
|
|
20118
20244
|
for (let i = 0; i < 6; i++) {
|
|
20119
|
-
const candidate =
|
|
20120
|
-
if (
|
|
20245
|
+
const candidate = join39(dir, "dist", "mcp");
|
|
20246
|
+
if (existsSync17(join39(candidate, "index.js"))) {
|
|
20121
20247
|
mcpSourceDir = candidate;
|
|
20122
20248
|
break;
|
|
20123
20249
|
}
|
|
@@ -20134,8 +20260,8 @@ function deployMcpAssets() {
|
|
|
20134
20260
|
const failedFiles = [];
|
|
20135
20261
|
const fileHash = (p) => {
|
|
20136
20262
|
try {
|
|
20137
|
-
if (!
|
|
20138
|
-
return
|
|
20263
|
+
if (!existsSync17(p)) return null;
|
|
20264
|
+
return createHash18("sha256").update(readFileSync30(p)).digest("hex");
|
|
20139
20265
|
} catch {
|
|
20140
20266
|
return null;
|
|
20141
20267
|
}
|
|
@@ -20206,9 +20332,9 @@ function deployMcpAssets() {
|
|
|
20206
20332
|
// needs restarting to pick up a token rotation.
|
|
20207
20333
|
"xero.js"
|
|
20208
20334
|
]) {
|
|
20209
|
-
const src =
|
|
20210
|
-
const dst =
|
|
20211
|
-
if (!
|
|
20335
|
+
const src = join39(mcpSourceDir, file);
|
|
20336
|
+
const dst = join39(targetDir, file);
|
|
20337
|
+
if (!existsSync17(src)) continue;
|
|
20212
20338
|
attemptedFiles.push(file);
|
|
20213
20339
|
const before = fileHash(dst);
|
|
20214
20340
|
try {
|
|
@@ -20233,23 +20359,23 @@ function deployMcpAssets() {
|
|
|
20233
20359
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
20234
20360
|
restartRunningChannelMcps(changedBasenames);
|
|
20235
20361
|
}
|
|
20236
|
-
const localMcpPath =
|
|
20362
|
+
const localMcpPath = join39(targetDir, "index.js");
|
|
20237
20363
|
try {
|
|
20238
|
-
const agentsDir =
|
|
20239
|
-
if (
|
|
20240
|
-
for (const entry of
|
|
20364
|
+
const agentsDir = join39(homedir17(), ".augmented", "agents");
|
|
20365
|
+
if (existsSync17(agentsDir)) {
|
|
20366
|
+
for (const entry of readdirSync10(agentsDir, { withFileTypes: true })) {
|
|
20241
20367
|
if (!entry.isDirectory()) continue;
|
|
20242
20368
|
for (const subdir of ["provision", "project"]) {
|
|
20243
|
-
const mcpJsonPath =
|
|
20369
|
+
const mcpJsonPath = join39(agentsDir, entry.name, subdir, ".mcp.json");
|
|
20244
20370
|
try {
|
|
20245
|
-
const raw =
|
|
20371
|
+
const raw = readFileSync30(mcpJsonPath, "utf-8");
|
|
20246
20372
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
20247
20373
|
const mcpConfig = JSON.parse(raw);
|
|
20248
20374
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
20249
20375
|
if (!augServer) continue;
|
|
20250
20376
|
augServer.command = "node";
|
|
20251
20377
|
augServer.args = [localMcpPath];
|
|
20252
|
-
|
|
20378
|
+
writeFileSync16(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
20253
20379
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
20254
20380
|
} catch {
|
|
20255
20381
|
}
|