@integrity-labs/agt-cli 0.28.474 → 0.28.475
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +4 -4
- package/dist/{chunk-YR6ESOCM.js → chunk-LGBI4P2P.js} +3 -87
- package/dist/chunk-LGBI4P2P.js.map +1 -0
- package/dist/{chunk-C47UJ5QI.js → chunk-Q53LFQVD.js} +3 -3
- package/dist/{claude-pair-runtime-62G3PXXX.js → claude-pair-runtime-IIQ6O7QX.js} +2 -2
- package/dist/lib/manager-worker.js +368 -426
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +46 -185
- package/dist/mcp/origami.js +4 -36
- package/dist/mcp/slack-channel.js +160 -309
- package/dist/mcp/telegram-channel.js +123 -264
- package/dist/{persistent-session-Y77TKSL6.js → persistent-session-BBWEPY24.js} +2 -2
- package/dist/{responsiveness-probe-KIPMD2UJ.js → responsiveness-probe-5AG6X2BN.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-YR6ESOCM.js.map +0 -1
- /package/dist/{chunk-C47UJ5QI.js.map → chunk-Q53LFQVD.js.map} +0 -0
- /package/dist/{claude-pair-runtime-62G3PXXX.js.map → claude-pair-runtime-IIQ6O7QX.js.map} +0 -0
- /package/dist/{persistent-session-Y77TKSL6.js.map → persistent-session-BBWEPY24.js.map} +0 -0
- /package/dist/{responsiveness-probe-KIPMD2UJ.js.map → responsiveness-probe-5AG6X2BN.js.map} +0 -0
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
resolveEffectivePinRaw,
|
|
45
45
|
safeWriteJsonAtomic,
|
|
46
46
|
setConfigHash
|
|
47
|
-
} from "../chunk-
|
|
47
|
+
} from "../chunk-Q53LFQVD.js";
|
|
48
48
|
import {
|
|
49
49
|
getProjectDir as getProjectDir2,
|
|
50
50
|
getReadyTasks,
|
|
@@ -73,7 +73,6 @@ import {
|
|
|
73
73
|
SUPPRESS_SENTINEL,
|
|
74
74
|
StreamEncoder,
|
|
75
75
|
UNKNOWN_RATE_LIMIT,
|
|
76
|
-
USAGE_LIMIT_MARKER_FILENAME,
|
|
77
76
|
appendDmFooter,
|
|
78
77
|
attributeTranscriptUsageByRun,
|
|
79
78
|
buildEgressAllowlist,
|
|
@@ -130,7 +129,6 @@ import {
|
|
|
130
129
|
parseEnvIntegrations,
|
|
131
130
|
parseTranscriptUsage,
|
|
132
131
|
parseUsageBanner,
|
|
133
|
-
parseUsageLimitMarker,
|
|
134
132
|
peekCurrentSession,
|
|
135
133
|
pickNewerClassification,
|
|
136
134
|
prepareForRespawn,
|
|
@@ -146,11 +144,9 @@ import {
|
|
|
146
144
|
resolveChannels,
|
|
147
145
|
resolveClaudeBinary,
|
|
148
146
|
resolveDmTarget,
|
|
149
|
-
resolveUsageLimitUntil,
|
|
150
147
|
restartEgressSidecar,
|
|
151
148
|
rotateSessionForWedge,
|
|
152
149
|
serializeAccountEnforcementMarker,
|
|
153
|
-
serializeUsageLimitMarker,
|
|
154
150
|
sessionTranscriptDir,
|
|
155
151
|
sha256,
|
|
156
152
|
sharedBusyBuckets,
|
|
@@ -166,17 +162,17 @@ import {
|
|
|
166
162
|
toOpencodeModel,
|
|
167
163
|
transcriptActivityAgeSeconds,
|
|
168
164
|
writeEgressAllowlist
|
|
169
|
-
} from "../chunk-
|
|
165
|
+
} from "../chunk-LGBI4P2P.js";
|
|
170
166
|
import {
|
|
171
167
|
reapOrphanChannelMcps
|
|
172
168
|
} from "../chunk-XWVM4KPK.js";
|
|
173
169
|
|
|
174
170
|
// src/lib/manager-worker.ts
|
|
175
171
|
import { createHash as createHash16 } from "crypto";
|
|
176
|
-
import { readFileSync as
|
|
172
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, existsSync as existsSync11, rmSync as rmSync5, readdirSync as readdirSync7, statSync as statSync6, copyFileSync } from "fs";
|
|
177
173
|
import { execFileSync as syncExecFile } from "child_process";
|
|
178
|
-
import { join as
|
|
179
|
-
import { homedir as
|
|
174
|
+
import { join as join25, dirname as dirname8, delimiter as pathDelimiter } from "path";
|
|
175
|
+
import { homedir as homedir11 } from "os";
|
|
180
176
|
import { fileURLToPath } from "url";
|
|
181
177
|
|
|
182
178
|
// src/lib/claude-code-upgrade-throttle.ts
|
|
@@ -2203,119 +2199,7 @@ var nodeArtifactFs = {
|
|
|
2203
2199
|
}
|
|
2204
2200
|
};
|
|
2205
2201
|
|
|
2206
|
-
// src/lib/usage-limit-marker-file.ts
|
|
2207
|
-
import { mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
2208
|
-
import { homedir as homedir3 } from "os";
|
|
2209
|
-
import { join as join6 } from "path";
|
|
2210
|
-
function agentDir(codeName) {
|
|
2211
|
-
return join6(homedir3(), ".augmented", codeName);
|
|
2212
|
-
}
|
|
2213
|
-
function usageLimitMarkerPath(codeName) {
|
|
2214
|
-
return join6(agentDir(codeName), USAGE_LIMIT_MARKER_FILENAME);
|
|
2215
|
-
}
|
|
2216
|
-
function writeUsageLimitMarker(codeName, limitedUntil, log2) {
|
|
2217
|
-
try {
|
|
2218
|
-
mkdirSync4(agentDir(codeName), { recursive: true });
|
|
2219
|
-
writeFileSync4(usageLimitMarkerPath(codeName), serializeUsageLimitMarker(limitedUntil), "utf-8");
|
|
2220
|
-
} catch (err) {
|
|
2221
|
-
log2(`[usage-banner] usage-limit marker sync failed for '${codeName}': ${err.message}`);
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
function clearUsageLimitMarker(codeName, log2) {
|
|
2225
|
-
try {
|
|
2226
|
-
rmSync2(usageLimitMarkerPath(codeName), { force: true });
|
|
2227
|
-
} catch (err) {
|
|
2228
|
-
log2(`[usage-banner] usage-limit marker clear failed for '${codeName}': ${err.message}`);
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
function readUsageLimitUntil(opts) {
|
|
2232
|
-
const path = opts.filePath ?? (opts.codeName ? usageLimitMarkerPath(opts.codeName) : null);
|
|
2233
|
-
if (!path) return null;
|
|
2234
|
-
let raw;
|
|
2235
|
-
try {
|
|
2236
|
-
raw = readFileSync7(path, "utf-8");
|
|
2237
|
-
} catch {
|
|
2238
|
-
return null;
|
|
2239
|
-
}
|
|
2240
|
-
return resolveUsageLimitUntil(parseUsageLimitMarker(raw), opts.now ?? /* @__PURE__ */ new Date());
|
|
2241
|
-
}
|
|
2242
|
-
var loggedUsageCapDeferral = /* @__PURE__ */ new Map();
|
|
2243
|
-
function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
|
|
2244
|
-
const key = `${site}:${codeName}`;
|
|
2245
|
-
const at = limitedUntil.getTime();
|
|
2246
|
-
if (loggedUsageCapDeferral.get(key) === at) return false;
|
|
2247
|
-
loggedUsageCapDeferral.set(key, at);
|
|
2248
|
-
return true;
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
// src/lib/agent-serving-probe.ts
|
|
2252
|
-
import { readFileSync as readFileSync8, readdirSync, statSync } from "fs";
|
|
2253
|
-
import { join as join7 } from "path";
|
|
2254
|
-
var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
|
|
2255
|
-
function probeRateLimit(args) {
|
|
2256
|
-
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
2257
|
-
const endMs = now.getTime();
|
|
2258
|
-
const startMs = endMs - (args.windowMs ?? RATE_LIMIT_WINDOW_MS);
|
|
2259
|
-
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
2260
|
-
let entries;
|
|
2261
|
-
try {
|
|
2262
|
-
entries = readdirSync(dir);
|
|
2263
|
-
} catch {
|
|
2264
|
-
return UNKNOWN_RATE_LIMIT;
|
|
2265
|
-
}
|
|
2266
|
-
let newest = UNKNOWN_RATE_LIMIT;
|
|
2267
|
-
for (const name of entries) {
|
|
2268
|
-
if (!name.endsWith(".jsonl")) continue;
|
|
2269
|
-
const path = join7(dir, name);
|
|
2270
|
-
try {
|
|
2271
|
-
const st = statSync(path);
|
|
2272
|
-
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
2273
|
-
} catch {
|
|
2274
|
-
continue;
|
|
2275
|
-
}
|
|
2276
|
-
let content;
|
|
2277
|
-
try {
|
|
2278
|
-
content = readFileSync8(path, "utf-8");
|
|
2279
|
-
} catch {
|
|
2280
|
-
continue;
|
|
2281
|
-
}
|
|
2282
|
-
newest = pickNewerClassification(
|
|
2283
|
-
newest,
|
|
2284
|
-
classifyTranscriptRateLimit(content, startMs, endMs, now)
|
|
2285
|
-
);
|
|
2286
|
-
}
|
|
2287
|
-
return newest;
|
|
2288
|
-
}
|
|
2289
|
-
function probeRateLimitState(args) {
|
|
2290
|
-
return probeRateLimit(args).verdict;
|
|
2291
|
-
}
|
|
2292
|
-
|
|
2293
2202
|
// src/lib/usage-banner-monitor.ts
|
|
2294
|
-
function syncUsageLimitMarker(args) {
|
|
2295
|
-
if (args.pct < 100) {
|
|
2296
|
-
clearUsageLimitMarker(args.codeName, args.log);
|
|
2297
|
-
return;
|
|
2298
|
-
}
|
|
2299
|
-
const verdict = args.verdict ?? probeRateLimitState({
|
|
2300
|
-
codeName: args.codeName,
|
|
2301
|
-
projectDir: getProjectDir(args.codeName),
|
|
2302
|
-
now: args.now
|
|
2303
|
-
});
|
|
2304
|
-
if (verdict === "serving") {
|
|
2305
|
-
args.log(
|
|
2306
|
-
`[usage-banner] saturated banner for '${args.codeName}' NOT armed - a turn completed, so the agent is serving (ENG-8198)`
|
|
2307
|
-
);
|
|
2308
|
-
clearUsageLimitMarker(args.codeName, args.log);
|
|
2309
|
-
return;
|
|
2310
|
-
}
|
|
2311
|
-
if (verdict === "unknown") {
|
|
2312
|
-
args.log(
|
|
2313
|
-
`[usage-banner] saturated banner for '${args.codeName}' NOT armed - no classifiable turn in the transcript; leaving any existing marker untouched (ENG-8198)`
|
|
2314
|
-
);
|
|
2315
|
-
return;
|
|
2316
|
-
}
|
|
2317
|
-
writeUsageLimitMarker(args.codeName, args.weekResetsAt, args.log);
|
|
2318
|
-
}
|
|
2319
2203
|
var SPAWN_MARKER = /--- spawn \S+ \(session [^)]*\) ---/g;
|
|
2320
2204
|
function scopeToCurrentPaneEpoch(tail) {
|
|
2321
2205
|
SPAWN_MARKER.lastIndex = 0;
|
|
@@ -2324,8 +2208,8 @@ function scopeToCurrentPaneEpoch(tail) {
|
|
|
2324
2208
|
while ((match = SPAWN_MARKER.exec(tail)) !== null) {
|
|
2325
2209
|
lastIndex = match.index;
|
|
2326
2210
|
}
|
|
2327
|
-
if (lastIndex < 0) return
|
|
2328
|
-
return
|
|
2211
|
+
if (lastIndex < 0) return tail;
|
|
2212
|
+
return tail.slice(lastIndex);
|
|
2329
2213
|
}
|
|
2330
2214
|
var MIN_CHECK_INTERVAL_MS = 6e4;
|
|
2331
2215
|
var PANE_TAIL_LINES_FOR_BANNER = 5e3;
|
|
@@ -2354,22 +2238,12 @@ async function maybeReportUsageBanner(args) {
|
|
|
2354
2238
|
state.set(codeName, next);
|
|
2355
2239
|
return;
|
|
2356
2240
|
}
|
|
2357
|
-
const
|
|
2241
|
+
const epochText = scopeToCurrentPaneEpoch(tail);
|
|
2358
2242
|
const observation = parseUsageBanner(epochText, now);
|
|
2359
2243
|
if (!observation) {
|
|
2360
|
-
if (sawSpawnMarker) {
|
|
2361
|
-
clearUsageLimitMarker(codeName, log2);
|
|
2362
|
-
}
|
|
2363
2244
|
state.set(codeName, next);
|
|
2364
2245
|
return;
|
|
2365
2246
|
}
|
|
2366
|
-
syncUsageLimitMarker({
|
|
2367
|
-
codeName,
|
|
2368
|
-
pct: observation.pct,
|
|
2369
|
-
weekResetsAt: observation.weekResetsAt,
|
|
2370
|
-
log: log2,
|
|
2371
|
-
now
|
|
2372
|
-
});
|
|
2373
2247
|
const observedAtIso = next.lastWeekResetsAt;
|
|
2374
2248
|
const weekResetsAtIso = observation.weekResetsAt.toISOString();
|
|
2375
2249
|
if (existing && existing.lastPct === observation.pct && observedAtIso === weekResetsAtIso) {
|
|
@@ -2395,13 +2269,13 @@ async function maybeReportUsageBanner(args) {
|
|
|
2395
2269
|
// src/lib/claude-account-fingerprint.ts
|
|
2396
2270
|
import { createHash as createHash6 } from "crypto";
|
|
2397
2271
|
import { readFile as readFile3, readdir as readdir3 } from "fs/promises";
|
|
2398
|
-
import { homedir as
|
|
2399
|
-
import { dirname as dirname4, join as
|
|
2272
|
+
import { homedir as homedir4, platform as platform2 } from "os";
|
|
2273
|
+
import { dirname as dirname4, join as join7 } from "path";
|
|
2400
2274
|
|
|
2401
2275
|
// src/lib/claude-auth-detect.ts
|
|
2402
2276
|
import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
2403
|
-
import { homedir as
|
|
2404
|
-
import { join as
|
|
2277
|
+
import { homedir as homedir3, platform } from "os";
|
|
2278
|
+
import { join as join6 } from "path";
|
|
2405
2279
|
import { execFile } from "child_process";
|
|
2406
2280
|
import { promisify } from "util";
|
|
2407
2281
|
var execFileAsync = promisify(execFile);
|
|
@@ -2416,16 +2290,16 @@ async function detectClaudeAuth() {
|
|
|
2416
2290
|
}
|
|
2417
2291
|
async function findClaudeCredentialsPaths() {
|
|
2418
2292
|
const candidates = [
|
|
2419
|
-
|
|
2420
|
-
|
|
2293
|
+
join6(homedir3(), ".claude", ".credentials.json"),
|
|
2294
|
+
join6(homedir3(), ".claude", "credentials.json")
|
|
2421
2295
|
];
|
|
2422
2296
|
const isLinuxRoot = platform() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
|
|
2423
2297
|
if (isLinuxRoot) {
|
|
2424
2298
|
try {
|
|
2425
2299
|
const entries = await readdir2("/home", { withFileTypes: true });
|
|
2426
2300
|
for (const entry of entries.filter((entry2) => entry2.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2427
|
-
candidates.push(
|
|
2428
|
-
candidates.push(
|
|
2301
|
+
candidates.push(join6("/home", entry.name, ".claude", ".credentials.json"));
|
|
2302
|
+
candidates.push(join6("/home", entry.name, ".claude", "credentials.json"));
|
|
2429
2303
|
}
|
|
2430
2304
|
} catch {
|
|
2431
2305
|
}
|
|
@@ -2503,13 +2377,13 @@ function parseExpiresAt(raw) {
|
|
|
2503
2377
|
|
|
2504
2378
|
// src/lib/claude-account-fingerprint.ts
|
|
2505
2379
|
async function candidateHomes() {
|
|
2506
|
-
const homes = [
|
|
2380
|
+
const homes = [homedir4()];
|
|
2507
2381
|
const isLinuxRoot = platform2() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
|
|
2508
2382
|
if (isLinuxRoot) {
|
|
2509
2383
|
try {
|
|
2510
2384
|
const entries = await readdir3("/home", { withFileTypes: true });
|
|
2511
2385
|
for (const entry of entries.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2512
|
-
homes.push(
|
|
2386
|
+
homes.push(join7("/home", entry.name));
|
|
2513
2387
|
}
|
|
2514
2388
|
} catch {
|
|
2515
2389
|
}
|
|
@@ -2529,11 +2403,11 @@ async function homeOfActiveCredentials() {
|
|
|
2529
2403
|
async function claudeConfigCandidatePaths() {
|
|
2530
2404
|
const paths = [];
|
|
2531
2405
|
const configDir = process.env["CLAUDE_CONFIG_DIR"]?.trim();
|
|
2532
|
-
if (configDir) paths.push(
|
|
2406
|
+
if (configDir) paths.push(join7(configDir, ".claude.json"));
|
|
2533
2407
|
const activeHome = await homeOfActiveCredentials();
|
|
2534
|
-
if (activeHome) paths.push(
|
|
2408
|
+
if (activeHome) paths.push(join7(activeHome, ".claude.json"));
|
|
2535
2409
|
for (const home of await candidateHomes()) {
|
|
2536
|
-
const path =
|
|
2410
|
+
const path = join7(home, ".claude.json");
|
|
2537
2411
|
if (!paths.includes(path)) paths.push(path);
|
|
2538
2412
|
}
|
|
2539
2413
|
return paths;
|
|
@@ -2630,11 +2504,11 @@ function diffAuthTuples(recorded, current) {
|
|
|
2630
2504
|
}
|
|
2631
2505
|
|
|
2632
2506
|
// src/lib/account-enforcement-marker.ts
|
|
2633
|
-
import { mkdirSync as
|
|
2634
|
-
import { homedir as
|
|
2635
|
-
import { join as
|
|
2507
|
+
import { mkdirSync as mkdirSync4, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
2508
|
+
import { homedir as homedir5 } from "os";
|
|
2509
|
+
import { join as join8 } from "path";
|
|
2636
2510
|
function accountEnforcementMarkerPath(codeName) {
|
|
2637
|
-
return
|
|
2511
|
+
return join8(homedir5(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2638
2512
|
}
|
|
2639
2513
|
function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.stderr.write(`${m}
|
|
2640
2514
|
`)) {
|
|
@@ -2642,16 +2516,16 @@ function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.std
|
|
|
2642
2516
|
clearAccountEnforcementMarker(codeName, log2);
|
|
2643
2517
|
return;
|
|
2644
2518
|
}
|
|
2645
|
-
const dir =
|
|
2646
|
-
const path =
|
|
2519
|
+
const dir = join8(homedir5(), ".augmented", codeName);
|
|
2520
|
+
const path = join8(dir, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2647
2521
|
const tempPath = `${path}.${process.pid}.tmp`;
|
|
2648
2522
|
try {
|
|
2649
|
-
|
|
2650
|
-
|
|
2523
|
+
mkdirSync4(dir, { recursive: true });
|
|
2524
|
+
writeFileSync4(tempPath, serializeAccountEnforcementMarker(level), "utf-8");
|
|
2651
2525
|
renameSync(tempPath, path);
|
|
2652
2526
|
} catch (err) {
|
|
2653
2527
|
try {
|
|
2654
|
-
|
|
2528
|
+
rmSync2(tempPath, { force: true });
|
|
2655
2529
|
} catch {
|
|
2656
2530
|
}
|
|
2657
2531
|
log2(`[account-enforcement] marker sync failed for '${codeName}': ${err.message}`);
|
|
@@ -2661,15 +2535,15 @@ function clearAccountEnforcementMarker(codeName, log2 = (m) => process.stderr.wr
|
|
|
2661
2535
|
`)) {
|
|
2662
2536
|
const path = accountEnforcementMarkerPath(codeName);
|
|
2663
2537
|
try {
|
|
2664
|
-
|
|
2538
|
+
rmSync2(path, { force: true });
|
|
2665
2539
|
} catch (err) {
|
|
2666
2540
|
log2(`[account-enforcement] marker clear failed for '${codeName}': ${err.message}`);
|
|
2667
2541
|
}
|
|
2668
2542
|
}
|
|
2669
2543
|
|
|
2670
2544
|
// src/lib/token-usage-monitor.ts
|
|
2671
|
-
import { readdirSync
|
|
2672
|
-
import { join as
|
|
2545
|
+
import { readdirSync, readFileSync as readFileSync7, statSync } from "fs";
|
|
2546
|
+
import { join as join9 } from "path";
|
|
2673
2547
|
var MIN_CHECK_INTERVAL_MS2 = 6e4;
|
|
2674
2548
|
var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
2675
2549
|
var MAX_ENTRIES_PER_POST = 200;
|
|
@@ -2687,7 +2561,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2687
2561
|
const next = { files, lastCheckedAt: nowMs };
|
|
2688
2562
|
let dirEntries;
|
|
2689
2563
|
try {
|
|
2690
|
-
dirEntries =
|
|
2564
|
+
dirEntries = readdirSync(dir);
|
|
2691
2565
|
} catch {
|
|
2692
2566
|
state2.set(codeName, next);
|
|
2693
2567
|
return;
|
|
@@ -2698,10 +2572,10 @@ async function maybeReportTokenUsage(args) {
|
|
|
2698
2572
|
if (!name.endsWith(".jsonl")) continue;
|
|
2699
2573
|
const sessionId = name.slice(0, -".jsonl".length);
|
|
2700
2574
|
if (!sessionId) continue;
|
|
2701
|
-
const path =
|
|
2575
|
+
const path = join9(dir, name);
|
|
2702
2576
|
let st;
|
|
2703
2577
|
try {
|
|
2704
|
-
st =
|
|
2578
|
+
st = statSync(path);
|
|
2705
2579
|
} catch {
|
|
2706
2580
|
continue;
|
|
2707
2581
|
}
|
|
@@ -2714,7 +2588,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2714
2588
|
}
|
|
2715
2589
|
let content;
|
|
2716
2590
|
try {
|
|
2717
|
-
content =
|
|
2591
|
+
content = readFileSync7(path, "utf-8");
|
|
2718
2592
|
} catch (err) {
|
|
2719
2593
|
log2(`[token-usage] read failed for '${codeName}/${name}': ${err.message}`);
|
|
2720
2594
|
continue;
|
|
@@ -2795,8 +2669,8 @@ async function maybeReportTokenUsage(args) {
|
|
|
2795
2669
|
}
|
|
2796
2670
|
|
|
2797
2671
|
// src/lib/workflow-run-reconciler.ts
|
|
2798
|
-
import { readdirSync as
|
|
2799
|
-
import { join as
|
|
2672
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
2673
|
+
import { join as join10 } from "path";
|
|
2800
2674
|
var MIN_CHECK_INTERVAL_MS3 = 5 * 6e4;
|
|
2801
2675
|
var SETTLE_MS = 3e4;
|
|
2802
2676
|
var TRANSCRIPT_MTIME_WINDOW_MS2 = 2 * 24 * 60 * 60 * 1e3;
|
|
@@ -2810,15 +2684,15 @@ function collectJsonlRecursive(dir, minMtimeMs, out, depth) {
|
|
|
2810
2684
|
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
2811
2685
|
let entries;
|
|
2812
2686
|
try {
|
|
2813
|
-
entries =
|
|
2687
|
+
entries = readdirSync2(dir);
|
|
2814
2688
|
} catch {
|
|
2815
2689
|
return;
|
|
2816
2690
|
}
|
|
2817
2691
|
for (const name of entries) {
|
|
2818
|
-
const p =
|
|
2692
|
+
const p = join10(dir, name);
|
|
2819
2693
|
let st;
|
|
2820
2694
|
try {
|
|
2821
|
-
st =
|
|
2695
|
+
st = statSync2(p);
|
|
2822
2696
|
} catch {
|
|
2823
2697
|
continue;
|
|
2824
2698
|
}
|
|
@@ -2833,15 +2707,15 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2833
2707
|
const out = [];
|
|
2834
2708
|
let entries;
|
|
2835
2709
|
try {
|
|
2836
|
-
entries =
|
|
2710
|
+
entries = readdirSync2(transcriptDir);
|
|
2837
2711
|
} catch {
|
|
2838
2712
|
return out;
|
|
2839
2713
|
}
|
|
2840
2714
|
for (const name of entries) {
|
|
2841
|
-
const path =
|
|
2715
|
+
const path = join10(transcriptDir, name);
|
|
2842
2716
|
let st;
|
|
2843
2717
|
try {
|
|
2844
|
-
st =
|
|
2718
|
+
st = statSync2(path);
|
|
2845
2719
|
} catch {
|
|
2846
2720
|
continue;
|
|
2847
2721
|
}
|
|
@@ -2850,7 +2724,7 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2850
2724
|
continue;
|
|
2851
2725
|
}
|
|
2852
2726
|
if (st.isDirectory()) {
|
|
2853
|
-
collectJsonlRecursive(
|
|
2727
|
+
collectJsonlRecursive(join10(path, "subagents"), minMtimeMs, out, 0);
|
|
2854
2728
|
}
|
|
2855
2729
|
}
|
|
2856
2730
|
return out;
|
|
@@ -2895,7 +2769,7 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2895
2769
|
const contents = [];
|
|
2896
2770
|
for (const path of files) {
|
|
2897
2771
|
try {
|
|
2898
|
-
contents.push(
|
|
2772
|
+
contents.push(readFileSync8(path, "utf-8"));
|
|
2899
2773
|
} catch {
|
|
2900
2774
|
}
|
|
2901
2775
|
}
|
|
@@ -2940,8 +2814,8 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2940
2814
|
}
|
|
2941
2815
|
|
|
2942
2816
|
// src/lib/conversation-evaluator.ts
|
|
2943
|
-
import { readdirSync as
|
|
2944
|
-
import { join as
|
|
2817
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
|
|
2818
|
+
import { join as join11 } from "path";
|
|
2945
2819
|
var MIN_CHECK_INTERVAL_MS4 = 5 * 6e4;
|
|
2946
2820
|
var TRANSCRIPT_MTIME_WINDOW_MS3 = 7 * 24 * 60 * 60 * 1e3;
|
|
2947
2821
|
var WINDOW_PAD_MS = 5 * 6e4;
|
|
@@ -3372,12 +3246,12 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3372
3246
|
const visit = (d) => {
|
|
3373
3247
|
let entries;
|
|
3374
3248
|
try {
|
|
3375
|
-
entries =
|
|
3249
|
+
entries = readdirSync3(d, { withFileTypes: true });
|
|
3376
3250
|
} catch {
|
|
3377
3251
|
return;
|
|
3378
3252
|
}
|
|
3379
3253
|
for (const ent of entries) {
|
|
3380
|
-
const full =
|
|
3254
|
+
const full = join11(d, ent.name);
|
|
3381
3255
|
if (ent.isDirectory()) {
|
|
3382
3256
|
visit(full);
|
|
3383
3257
|
continue;
|
|
@@ -3385,14 +3259,14 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3385
3259
|
if (!ent.isFile() || !ent.name.endsWith(".jsonl")) continue;
|
|
3386
3260
|
let mtimeMs;
|
|
3387
3261
|
try {
|
|
3388
|
-
mtimeMs =
|
|
3262
|
+
mtimeMs = statSync3(full).mtimeMs;
|
|
3389
3263
|
} catch {
|
|
3390
3264
|
continue;
|
|
3391
3265
|
}
|
|
3392
3266
|
if (nowMs - mtimeMs > TRANSCRIPT_MTIME_WINDOW_MS3) continue;
|
|
3393
3267
|
let content;
|
|
3394
3268
|
try {
|
|
3395
|
-
content =
|
|
3269
|
+
content = readFileSync9(full, "utf8");
|
|
3396
3270
|
} catch {
|
|
3397
3271
|
continue;
|
|
3398
3272
|
}
|
|
@@ -3682,11 +3556,11 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
|
|
|
3682
3556
|
}
|
|
3683
3557
|
|
|
3684
3558
|
// src/lib/activity-cache-monitor.ts
|
|
3685
|
-
import { existsSync as existsSync2, readFileSync as
|
|
3686
|
-
import { homedir as
|
|
3687
|
-
import { join as
|
|
3559
|
+
import { existsSync as existsSync2, readFileSync as readFileSync10 } from "fs";
|
|
3560
|
+
import { homedir as homedir6 } from "os";
|
|
3561
|
+
import { join as join12 } from "path";
|
|
3688
3562
|
var MIN_CHECK_INTERVAL_MS6 = 6e4;
|
|
3689
|
-
var STATS_CACHE_PATH =
|
|
3563
|
+
var STATS_CACHE_PATH = join12(homedir6(), ".claude", "stats-cache.json");
|
|
3690
3564
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
3691
3565
|
var state5 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
3692
3566
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
@@ -3734,7 +3608,7 @@ async function maybeReportActivityCache(args) {
|
|
|
3734
3608
|
}
|
|
3735
3609
|
let raw;
|
|
3736
3610
|
try {
|
|
3737
|
-
raw =
|
|
3611
|
+
raw = readFileSync10(STATS_CACHE_PATH, "utf-8");
|
|
3738
3612
|
} catch (err) {
|
|
3739
3613
|
log2(`[activity-cache] readFileSync failed: ${err.message}`);
|
|
3740
3614
|
return;
|
|
@@ -3938,18 +3812,18 @@ function computeChannelConfigHash(input) {
|
|
|
3938
3812
|
}
|
|
3939
3813
|
|
|
3940
3814
|
// src/lib/channel-hash-cache.ts
|
|
3941
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3942
|
-
import { join as
|
|
3815
|
+
import { existsSync as existsSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "fs";
|
|
3816
|
+
import { join as join13 } from "path";
|
|
3943
3817
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
3944
3818
|
function getChannelHashCacheFile(configDir) {
|
|
3945
|
-
return
|
|
3819
|
+
return join13(configDir, CACHE_FILENAME);
|
|
3946
3820
|
}
|
|
3947
3821
|
function loadChannelHashCache(target, configDir) {
|
|
3948
3822
|
const path = getChannelHashCacheFile(configDir);
|
|
3949
3823
|
if (!existsSync3(path)) return;
|
|
3950
3824
|
let parsed;
|
|
3951
3825
|
try {
|
|
3952
|
-
parsed = JSON.parse(
|
|
3826
|
+
parsed = JSON.parse(readFileSync11(path, "utf-8"));
|
|
3953
3827
|
} catch {
|
|
3954
3828
|
return;
|
|
3955
3829
|
}
|
|
@@ -3963,14 +3837,14 @@ function saveChannelHashCache(source, configDir) {
|
|
|
3963
3837
|
const obj = {};
|
|
3964
3838
|
for (const [key, value] of source) obj[key] = value;
|
|
3965
3839
|
try {
|
|
3966
|
-
|
|
3840
|
+
writeFileSync5(path, JSON.stringify(obj, null, 2));
|
|
3967
3841
|
} catch {
|
|
3968
3842
|
}
|
|
3969
3843
|
}
|
|
3970
3844
|
|
|
3971
3845
|
// src/lib/sender-policy-baseline.ts
|
|
3972
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3973
|
-
import { join as
|
|
3846
|
+
import { existsSync as existsSync4, readFileSync as readFileSync12 } from "fs";
|
|
3847
|
+
import { join as join14 } from "path";
|
|
3974
3848
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
3975
3849
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
3976
3850
|
var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
|
|
@@ -3982,14 +3856,14 @@ function createDeliveryBaselineMaps() {
|
|
|
3982
3856
|
};
|
|
3983
3857
|
}
|
|
3984
3858
|
function getSenderPolicyBaselineFile(configDir) {
|
|
3985
|
-
return
|
|
3859
|
+
return join14(configDir, BASELINE_FILENAME);
|
|
3986
3860
|
}
|
|
3987
3861
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
3988
3862
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
3989
3863
|
if (!existsSync4(path)) return;
|
|
3990
3864
|
let parsed;
|
|
3991
3865
|
try {
|
|
3992
|
-
parsed = JSON.parse(
|
|
3866
|
+
parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
3993
3867
|
} catch (err) {
|
|
3994
3868
|
log2?.(
|
|
3995
3869
|
`[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
|
|
@@ -4512,16 +4386,16 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
4512
4386
|
}
|
|
4513
4387
|
|
|
4514
4388
|
// src/lib/manager/managed-skill-manifest.ts
|
|
4515
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
4516
|
-
import { dirname as dirname5, join as
|
|
4389
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
|
|
4390
|
+
import { dirname as dirname5, join as join15 } from "path";
|
|
4517
4391
|
var MANIFEST_VERSION = 1;
|
|
4518
4392
|
function managedSkillManifestPath(agentRootDir) {
|
|
4519
|
-
return
|
|
4393
|
+
return join15(agentRootDir, "managed-skills.json");
|
|
4520
4394
|
}
|
|
4521
4395
|
function readManagedSkillManifest(path) {
|
|
4522
4396
|
try {
|
|
4523
4397
|
if (!existsSync5(path)) return /* @__PURE__ */ new Set();
|
|
4524
|
-
const parsed = JSON.parse(
|
|
4398
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
4525
4399
|
const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
|
|
4526
4400
|
return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
|
|
4527
4401
|
} catch {
|
|
@@ -4530,12 +4404,12 @@ function readManagedSkillManifest(path) {
|
|
|
4530
4404
|
}
|
|
4531
4405
|
function writeManagedSkillManifest(path, ids) {
|
|
4532
4406
|
try {
|
|
4533
|
-
|
|
4407
|
+
mkdirSync5(dirname5(path), { recursive: true });
|
|
4534
4408
|
const body = {
|
|
4535
4409
|
version: MANIFEST_VERSION,
|
|
4536
4410
|
globalSkillIds: [...ids].sort()
|
|
4537
4411
|
};
|
|
4538
|
-
|
|
4412
|
+
writeFileSync6(path, JSON.stringify(body, null, 2));
|
|
4539
4413
|
} catch {
|
|
4540
4414
|
}
|
|
4541
4415
|
}
|
|
@@ -4633,9 +4507,9 @@ function resolveModelChain(refreshData) {
|
|
|
4633
4507
|
}
|
|
4634
4508
|
|
|
4635
4509
|
// src/lib/manager/claude-auth.ts
|
|
4636
|
-
import { existsSync as existsSync6, rmSync as
|
|
4637
|
-
import { join as
|
|
4638
|
-
import { homedir as
|
|
4510
|
+
import { existsSync as existsSync6, rmSync as rmSync3 } from "fs";
|
|
4511
|
+
import { join as join16 } from "path";
|
|
4512
|
+
import { homedir as homedir7 } from "os";
|
|
4639
4513
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
4640
4514
|
const apiKey = getApiKey();
|
|
4641
4515
|
if (!apiKey) {
|
|
@@ -4647,12 +4521,12 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4647
4521
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
4648
4522
|
}
|
|
4649
4523
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
4650
|
-
const claudeDir =
|
|
4524
|
+
const claudeDir = join16(homedir7(), ".claude");
|
|
4651
4525
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
4652
|
-
const p =
|
|
4526
|
+
const p = join16(claudeDir, filename);
|
|
4653
4527
|
if (existsSync6(p)) {
|
|
4654
4528
|
try {
|
|
4655
|
-
|
|
4529
|
+
rmSync3(p, { force: true });
|
|
4656
4530
|
log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
|
|
4657
4531
|
} catch {
|
|
4658
4532
|
}
|
|
@@ -4664,8 +4538,8 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4664
4538
|
}
|
|
4665
4539
|
|
|
4666
4540
|
// src/lib/manager/kanban/parsers.ts
|
|
4667
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4668
|
-
import { join as
|
|
4541
|
+
import { existsSync as existsSync7, readFileSync as readFileSync14 } from "fs";
|
|
4542
|
+
import { join as join17 } from "path";
|
|
4669
4543
|
var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
|
|
4670
4544
|
var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
|
|
4671
4545
|
var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
|
|
@@ -4804,12 +4678,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
4804
4678
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
4805
4679
|
try {
|
|
4806
4680
|
const candidates = [
|
|
4807
|
-
|
|
4808
|
-
|
|
4681
|
+
join17(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
4682
|
+
join17(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
4809
4683
|
];
|
|
4810
4684
|
for (const candidate of candidates) {
|
|
4811
4685
|
if (existsSync7(candidate)) {
|
|
4812
|
-
const content =
|
|
4686
|
+
const content = readFileSync14(candidate, "utf-8");
|
|
4813
4687
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
4814
4688
|
builtInSkillCache.set(skillId, files);
|
|
4815
4689
|
return files;
|
|
@@ -4950,19 +4824,19 @@ function formatBoardForPrompt(items, template) {
|
|
|
4950
4824
|
}
|
|
4951
4825
|
|
|
4952
4826
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
4953
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4954
|
-
import { join as
|
|
4827
|
+
import { existsSync as existsSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "fs";
|
|
4828
|
+
import { join as join18 } from "path";
|
|
4955
4829
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
4956
4830
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
4957
4831
|
function getKanbanNudgeStateFile(configDir) {
|
|
4958
|
-
return
|
|
4832
|
+
return join18(configDir, CACHE_FILENAME2);
|
|
4959
4833
|
}
|
|
4960
4834
|
function loadKanbanNudgeState(target, configDir) {
|
|
4961
4835
|
const path = getKanbanNudgeStateFile(configDir);
|
|
4962
4836
|
if (!existsSync8(path)) return;
|
|
4963
4837
|
let parsed;
|
|
4964
4838
|
try {
|
|
4965
|
-
parsed = JSON.parse(
|
|
4839
|
+
parsed = JSON.parse(readFileSync15(path, "utf-8"));
|
|
4966
4840
|
} catch {
|
|
4967
4841
|
return;
|
|
4968
4842
|
}
|
|
@@ -4987,7 +4861,7 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
4987
4861
|
const agents = {};
|
|
4988
4862
|
for (const [codeName, state7] of source) agents[codeName] = state7;
|
|
4989
4863
|
try {
|
|
4990
|
-
|
|
4864
|
+
writeFileSync7(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
4991
4865
|
} catch {
|
|
4992
4866
|
}
|
|
4993
4867
|
}
|
|
@@ -5562,9 +5436,9 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
5562
5436
|
|
|
5563
5437
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
5564
5438
|
import { createHash as createHash11 } from "crypto";
|
|
5565
|
-
import { writeFileSync as
|
|
5566
|
-
import { homedir as
|
|
5567
|
-
import { join as
|
|
5439
|
+
import { writeFileSync as writeFileSync8, renameSync as renameSync2, mkdirSync as mkdirSync6, readFileSync as readFileSync16, unlinkSync } from "fs";
|
|
5440
|
+
import { homedir as homedir8 } from "os";
|
|
5441
|
+
import { join as join19, dirname as dirname6 } from "path";
|
|
5568
5442
|
|
|
5569
5443
|
// src/lib/manager/scheduler/notify.ts
|
|
5570
5444
|
import { createHash as createHash10 } from "crypto";
|
|
@@ -5904,19 +5778,19 @@ function resolveScheduledSlackTarget(task) {
|
|
|
5904
5778
|
}
|
|
5905
5779
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
5906
5780
|
try {
|
|
5907
|
-
const file =
|
|
5781
|
+
const file = join19(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5908
5782
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
5909
5783
|
const tmp = `${file}.tmp`;
|
|
5910
|
-
|
|
5784
|
+
writeFileSync8(tmp, JSON.stringify(marker), "utf8");
|
|
5911
5785
|
renameSync2(tmp, file);
|
|
5912
5786
|
} catch (err) {
|
|
5913
5787
|
log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
|
|
5914
5788
|
}
|
|
5915
5789
|
}
|
|
5916
5790
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
5917
|
-
const file =
|
|
5791
|
+
const file = join19(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5918
5792
|
try {
|
|
5919
|
-
const raw = JSON.parse(
|
|
5793
|
+
const raw = JSON.parse(readFileSync16(file, "utf8"));
|
|
5920
5794
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
5921
5795
|
unlinkSync(file);
|
|
5922
5796
|
log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
|
|
@@ -5970,9 +5844,9 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt, dura
|
|
|
5970
5844
|
return false;
|
|
5971
5845
|
}
|
|
5972
5846
|
try {
|
|
5973
|
-
const doorbell = directChatDoorbellPath(agentId,
|
|
5974
|
-
|
|
5975
|
-
|
|
5847
|
+
const doorbell = directChatDoorbellPath(agentId, homedir8());
|
|
5848
|
+
mkdirSync6(dirname6(doorbell), { recursive: true });
|
|
5849
|
+
writeFileSync8(doorbell, String(Date.now()));
|
|
5976
5850
|
} catch (err) {
|
|
5977
5851
|
log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
5978
5852
|
}
|
|
@@ -6122,10 +5996,99 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
6122
5996
|
|
|
6123
5997
|
// src/lib/manager/scheduler/execution.ts
|
|
6124
5998
|
import { createHash as createHash12 } from "crypto";
|
|
6125
|
-
import { homedir as
|
|
6126
|
-
import { join as
|
|
5999
|
+
import { homedir as homedir9 } from "os";
|
|
6000
|
+
import { join as join21 } from "path";
|
|
6001
|
+
|
|
6002
|
+
// src/lib/agent-serving-probe.ts
|
|
6003
|
+
import { readFileSync as readFileSync17, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
|
|
6004
|
+
import { join as join20 } from "path";
|
|
6005
|
+
var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
|
|
6006
|
+
function probeRateLimit(args) {
|
|
6007
|
+
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
6008
|
+
const endMs = now.getTime();
|
|
6009
|
+
const startMs = endMs - (args.windowMs ?? RATE_LIMIT_WINDOW_MS);
|
|
6010
|
+
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
6011
|
+
let entries;
|
|
6012
|
+
try {
|
|
6013
|
+
entries = readdirSync4(dir);
|
|
6014
|
+
} catch {
|
|
6015
|
+
return UNKNOWN_RATE_LIMIT;
|
|
6016
|
+
}
|
|
6017
|
+
let newest = UNKNOWN_RATE_LIMIT;
|
|
6018
|
+
for (const name of entries) {
|
|
6019
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
6020
|
+
const path = join20(dir, name);
|
|
6021
|
+
try {
|
|
6022
|
+
const st = statSync4(path);
|
|
6023
|
+
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
6024
|
+
} catch {
|
|
6025
|
+
continue;
|
|
6026
|
+
}
|
|
6027
|
+
let content;
|
|
6028
|
+
try {
|
|
6029
|
+
content = readFileSync17(path, "utf-8");
|
|
6030
|
+
} catch {
|
|
6031
|
+
continue;
|
|
6032
|
+
}
|
|
6033
|
+
newest = pickNewerClassification(
|
|
6034
|
+
newest,
|
|
6035
|
+
classifyTranscriptRateLimit(content, startMs, endMs, now)
|
|
6036
|
+
);
|
|
6037
|
+
}
|
|
6038
|
+
return newest;
|
|
6039
|
+
}
|
|
6040
|
+
var USAGE_CAP_PROBE_TTL_MS = 6e4;
|
|
6041
|
+
var usageCapProbeCache = /* @__PURE__ */ new Map();
|
|
6042
|
+
var claudeAccountByAgent = /* @__PURE__ */ new Map();
|
|
6043
|
+
var usageCapEvidenceFloorMs = /* @__PURE__ */ new Map();
|
|
6044
|
+
var loggedUsageCapDeferral = /* @__PURE__ */ new Map();
|
|
6045
|
+
function noteClaudeAccountChange(codeName, fingerprint3, log2, now) {
|
|
6046
|
+
if (!fingerprint3) return;
|
|
6047
|
+
const previous = claudeAccountByAgent.get(codeName);
|
|
6048
|
+
claudeAccountByAgent.set(codeName, fingerprint3);
|
|
6049
|
+
if (previous === void 0 || previous === fingerprint3) return;
|
|
6050
|
+
usageCapEvidenceFloorMs.set(codeName, (now ?? /* @__PURE__ */ new Date()).getTime());
|
|
6051
|
+
usageCapProbeCache.delete(codeName);
|
|
6052
|
+
log2(
|
|
6053
|
+
`[usage-cap] signed-in Claude account changed for '${codeName}' (${previous} \u2192 ${fingerprint3}) \u2014 disregarding rate-limit evidence recorded before now; the cap belonged to the previous account (ENG-8202)`
|
|
6054
|
+
);
|
|
6055
|
+
}
|
|
6056
|
+
function readUsageCapUntil(args) {
|
|
6057
|
+
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
6058
|
+
const nowMs = now.getTime();
|
|
6059
|
+
const floorMs = usageCapEvidenceFloorMs.get(args.codeName);
|
|
6060
|
+
const requestedWindowMs = args.windowMs ?? RATE_LIMIT_WINDOW_MS;
|
|
6061
|
+
const windowMs = floorMs === void 0 ? requestedWindowMs : Math.max(0, Math.min(requestedWindowMs, nowMs - floorMs));
|
|
6062
|
+
const cached = usageCapProbeCache.get(args.codeName);
|
|
6063
|
+
let classification;
|
|
6064
|
+
if (cached && nowMs - cached.at < (args.ttlMs ?? USAGE_CAP_PROBE_TTL_MS)) {
|
|
6065
|
+
classification = cached.classification;
|
|
6066
|
+
} else {
|
|
6067
|
+
classification = probeRateLimit({
|
|
6068
|
+
codeName: args.codeName,
|
|
6069
|
+
projectDir: args.projectDir,
|
|
6070
|
+
now,
|
|
6071
|
+
windowMs,
|
|
6072
|
+
transcriptDir: args.transcriptDir
|
|
6073
|
+
});
|
|
6074
|
+
usageCapProbeCache.set(args.codeName, { at: nowMs, classification });
|
|
6075
|
+
}
|
|
6076
|
+
if (classification.verdict !== "capped") return null;
|
|
6077
|
+
const resetsAt = classification.resetsAt;
|
|
6078
|
+
if (!resetsAt) return null;
|
|
6079
|
+
return resetsAt.getTime() > nowMs ? resetsAt : null;
|
|
6080
|
+
}
|
|
6081
|
+
function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
|
|
6082
|
+
const key = `${site}:${codeName}`;
|
|
6083
|
+
const at = limitedUntil.getTime();
|
|
6084
|
+
if (loggedUsageCapDeferral.get(key) === at) return false;
|
|
6085
|
+
loggedUsageCapDeferral.set(key, at);
|
|
6086
|
+
return true;
|
|
6087
|
+
}
|
|
6088
|
+
|
|
6089
|
+
// src/lib/manager/scheduler/execution.ts
|
|
6127
6090
|
function claudePidFilePath() {
|
|
6128
|
-
return
|
|
6091
|
+
return join21(homedir9(), ".augmented", "manager-claude-pids.json");
|
|
6129
6092
|
}
|
|
6130
6093
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
6131
6094
|
function registerClaudeSpawn(record) {
|
|
@@ -6164,7 +6127,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
6164
6127
|
const state7 = claudeSchedulerStates.get(codeName);
|
|
6165
6128
|
const ready = getReadyTasks(state7, inFlightClaudeTasks);
|
|
6166
6129
|
if (ready.length === 0) return;
|
|
6167
|
-
const limitedUntil =
|
|
6130
|
+
const limitedUntil = readUsageCapUntil({ codeName, projectDir: getProjectDir(codeName) });
|
|
6168
6131
|
if (limitedUntil) {
|
|
6169
6132
|
if (shouldLogUsageCapDeferral("claude-scheduler", codeName, limitedUntil)) {
|
|
6170
6133
|
log(
|
|
@@ -7358,9 +7321,9 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
7358
7321
|
|
|
7359
7322
|
// src/lib/opencode-telegram-ingest.ts
|
|
7360
7323
|
import { createHash as createHash15 } from "crypto";
|
|
7361
|
-
import { existsSync as existsSync9, mkdirSync as
|
|
7324
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
7362
7325
|
import { randomUUID } from "crypto";
|
|
7363
|
-
import { join as
|
|
7326
|
+
import { join as join22 } from "path";
|
|
7364
7327
|
|
|
7365
7328
|
// src/lib/telegram-ingest.ts
|
|
7366
7329
|
import https2 from "https";
|
|
@@ -7908,7 +7871,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7908
7871
|
let filePath;
|
|
7909
7872
|
try {
|
|
7910
7873
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
7911
|
-
filePath =
|
|
7874
|
+
filePath = join22(dir, "telegram-getupdates-offset-opencode.json");
|
|
7912
7875
|
} catch {
|
|
7913
7876
|
dir = null;
|
|
7914
7877
|
filePath = null;
|
|
@@ -7917,7 +7880,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7917
7880
|
load() {
|
|
7918
7881
|
if (!filePath) return 0;
|
|
7919
7882
|
try {
|
|
7920
|
-
const parsed = JSON.parse(
|
|
7883
|
+
const parsed = JSON.parse(readFileSync18(filePath, "utf-8"));
|
|
7921
7884
|
if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
|
|
7922
7885
|
log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
|
|
7923
7886
|
return 0;
|
|
@@ -7935,8 +7898,8 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7935
7898
|
if (!filePath || !dir) return;
|
|
7936
7899
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
7937
7900
|
try {
|
|
7938
|
-
|
|
7939
|
-
|
|
7901
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
7902
|
+
writeFileSync9(
|
|
7940
7903
|
tmpPath,
|
|
7941
7904
|
JSON.stringify({
|
|
7942
7905
|
offset,
|
|
@@ -8187,15 +8150,15 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
8187
8150
|
}
|
|
8188
8151
|
|
|
8189
8152
|
// src/lib/restart-flags.ts
|
|
8190
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
8191
|
-
import { homedir as
|
|
8192
|
-
import { join as
|
|
8153
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync19, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
8154
|
+
import { homedir as homedir10 } from "os";
|
|
8155
|
+
import { join as join23 } from "path";
|
|
8193
8156
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
8194
8157
|
function restartFlagsDir() {
|
|
8195
|
-
return
|
|
8158
|
+
return join23(homedir10(), ".augmented", "restart-flags");
|
|
8196
8159
|
}
|
|
8197
8160
|
function flagPath(codeName) {
|
|
8198
|
-
return
|
|
8161
|
+
return join23(restartFlagsDir(), `${codeName}.flag`);
|
|
8199
8162
|
}
|
|
8200
8163
|
function readRestartFlags() {
|
|
8201
8164
|
const dir = restartFlagsDir();
|
|
@@ -8204,7 +8167,7 @@ function readRestartFlags() {
|
|
|
8204
8167
|
for (const entry of readdirSync5(dir)) {
|
|
8205
8168
|
if (!entry.endsWith(".flag")) continue;
|
|
8206
8169
|
try {
|
|
8207
|
-
const raw =
|
|
8170
|
+
const raw = readFileSync19(join23(dir, entry), "utf8");
|
|
8208
8171
|
const parsed = JSON.parse(raw);
|
|
8209
8172
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
8210
8173
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -8223,7 +8186,7 @@ function readRestartFlags() {
|
|
|
8223
8186
|
function deleteRestartFlag(codeName) {
|
|
8224
8187
|
const path = flagPath(codeName);
|
|
8225
8188
|
if (existsSync10(path)) {
|
|
8226
|
-
|
|
8189
|
+
rmSync4(path, { force: true });
|
|
8227
8190
|
}
|
|
8228
8191
|
}
|
|
8229
8192
|
|
|
@@ -8322,8 +8285,8 @@ async function sendError(flag, opts, text) {
|
|
|
8322
8285
|
}
|
|
8323
8286
|
|
|
8324
8287
|
// src/lib/restart-context.ts
|
|
8325
|
-
import { readdirSync as readdirSync6, readFileSync as
|
|
8326
|
-
import { dirname as dirname7, join as
|
|
8288
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync20, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, unlinkSync as unlinkSync3 } from "fs";
|
|
8289
|
+
import { dirname as dirname7, join as join24 } from "path";
|
|
8327
8290
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
8328
8291
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
8329
8292
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -8335,10 +8298,10 @@ function augmentedAgentDir(codeName) {
|
|
|
8335
8298
|
return dirname7(getProjectDir(codeName));
|
|
8336
8299
|
}
|
|
8337
8300
|
function slackPendingInboundDir(codeName) {
|
|
8338
|
-
return
|
|
8301
|
+
return join24(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
8339
8302
|
}
|
|
8340
8303
|
function slackRestartContextDir(codeName) {
|
|
8341
|
-
return
|
|
8304
|
+
return join24(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
8342
8305
|
}
|
|
8343
8306
|
function sanitizeTopic(raw) {
|
|
8344
8307
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -8380,7 +8343,7 @@ function safeReaddir(dir) {
|
|
|
8380
8343
|
}
|
|
8381
8344
|
function readStrandedMarker(path) {
|
|
8382
8345
|
try {
|
|
8383
|
-
const parsed = JSON.parse(
|
|
8346
|
+
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
8384
8347
|
if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
|
|
8385
8348
|
return { channel: parsed.channel, thread_ts: parsed.thread_ts };
|
|
8386
8349
|
}
|
|
@@ -8389,8 +8352,8 @@ function readStrandedMarker(path) {
|
|
|
8389
8352
|
return null;
|
|
8390
8353
|
}
|
|
8391
8354
|
function writeHintFile(path, dir, hint) {
|
|
8392
|
-
|
|
8393
|
-
|
|
8355
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
8356
|
+
writeFileSync11(path, JSON.stringify(hint), { mode: 384 });
|
|
8394
8357
|
}
|
|
8395
8358
|
function pruneHintsExcept(codeName, freshFilenames) {
|
|
8396
8359
|
const ctxDir = slackRestartContextDir(codeName);
|
|
@@ -8398,7 +8361,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
8398
8361
|
if (!filename.endsWith(".json")) continue;
|
|
8399
8362
|
if (freshFilenames.has(filename)) continue;
|
|
8400
8363
|
try {
|
|
8401
|
-
unlinkSync3(
|
|
8364
|
+
unlinkSync3(join24(ctxDir, filename));
|
|
8402
8365
|
} catch {
|
|
8403
8366
|
}
|
|
8404
8367
|
}
|
|
@@ -8419,7 +8382,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8419
8382
|
}
|
|
8420
8383
|
const markers = [];
|
|
8421
8384
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
8422
|
-
const parsed = readStrandedMarker(
|
|
8385
|
+
const parsed = readStrandedMarker(join24(markerDir, filename));
|
|
8423
8386
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
8424
8387
|
}
|
|
8425
8388
|
if (markers.length === 0) {
|
|
@@ -8433,7 +8396,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8433
8396
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
8434
8397
|
for (const { filename, hint } of hints) {
|
|
8435
8398
|
try {
|
|
8436
|
-
writeHintFile(
|
|
8399
|
+
writeHintFile(join24(ctxDir, filename), ctxDir, hint);
|
|
8437
8400
|
freshFilenames.add(filename);
|
|
8438
8401
|
} catch (err) {
|
|
8439
8402
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -9712,7 +9675,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
9712
9675
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
9713
9676
|
function projectMcpHash(_codeName, projectDir) {
|
|
9714
9677
|
try {
|
|
9715
|
-
const raw =
|
|
9678
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9716
9679
|
return createHash16("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
9717
9680
|
} catch {
|
|
9718
9681
|
return null;
|
|
@@ -9720,7 +9683,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
9720
9683
|
}
|
|
9721
9684
|
function projectMcpKeys(_codeName, projectDir) {
|
|
9722
9685
|
try {
|
|
9723
|
-
const raw =
|
|
9686
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9724
9687
|
const parsed = JSON.parse(raw);
|
|
9725
9688
|
const servers = parsed.mcpServers;
|
|
9726
9689
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -9738,7 +9701,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
9738
9701
|
else runningMcpServerKeys.delete(codeName);
|
|
9739
9702
|
let launchStructure = null;
|
|
9740
9703
|
try {
|
|
9741
|
-
const raw =
|
|
9704
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9742
9705
|
launchStructure = managedMcpStructureHashFromFile(
|
|
9743
9706
|
JSON.parse(raw),
|
|
9744
9707
|
isManagedMcpServerKey
|
|
@@ -9842,7 +9805,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
9842
9805
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
9843
9806
|
let mcpJsonForRebind = null;
|
|
9844
9807
|
try {
|
|
9845
|
-
mcpJsonForRebind = JSON.parse(
|
|
9808
|
+
mcpJsonForRebind = JSON.parse(readFileSync21(join25(projectDir, ".mcp.json"), "utf-8"));
|
|
9846
9809
|
} catch {
|
|
9847
9810
|
mcpJsonForRebind = null;
|
|
9848
9811
|
}
|
|
@@ -9998,7 +9961,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
9998
9961
|
function projectChannelSecretHash(projectDir) {
|
|
9999
9962
|
try {
|
|
10000
9963
|
const entries = parseEnvIntegrations(
|
|
10001
|
-
|
|
9964
|
+
readFileSync21(join25(projectDir, ".env.integrations"), "utf-8")
|
|
10002
9965
|
);
|
|
10003
9966
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
10004
9967
|
} catch {
|
|
@@ -10094,7 +10057,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
10094
10057
|
var lastVersionCheckAt = 0;
|
|
10095
10058
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
10096
10059
|
var lastResponsivenessProbeAt = 0;
|
|
10097
|
-
var agtCliVersion = true ? "0.28.
|
|
10060
|
+
var agtCliVersion = true ? "0.28.475" : "dev";
|
|
10098
10061
|
function resolveBrewPath(execFileSync2) {
|
|
10099
10062
|
try {
|
|
10100
10063
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10383,7 +10346,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
10383
10346
|
try {
|
|
10384
10347
|
let settings = {};
|
|
10385
10348
|
if (existsSync11(path)) {
|
|
10386
|
-
const raw =
|
|
10349
|
+
const raw = readFileSync21(path, "utf-8").trim();
|
|
10387
10350
|
if (raw) {
|
|
10388
10351
|
let parsed;
|
|
10389
10352
|
try {
|
|
@@ -10399,8 +10362,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
10399
10362
|
}
|
|
10400
10363
|
if (settings.channelsEnabled === true) return "ok";
|
|
10401
10364
|
settings.channelsEnabled = true;
|
|
10402
|
-
|
|
10403
|
-
|
|
10365
|
+
mkdirSync10(dirname8(path), { recursive: true });
|
|
10366
|
+
writeFileSync12(path, `${JSON.stringify(settings, null, 2)}
|
|
10404
10367
|
`);
|
|
10405
10368
|
log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
|
|
10406
10369
|
return "ok";
|
|
@@ -10438,7 +10401,7 @@ async function ensureOpencodeBinary() {
|
|
|
10438
10401
|
try {
|
|
10439
10402
|
const prefix = execFileSync2("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
10440
10403
|
if (prefix) {
|
|
10441
|
-
const npmBin =
|
|
10404
|
+
const npmBin = join25(prefix, "bin");
|
|
10442
10405
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
10443
10406
|
if (!current.includes(npmBin)) {
|
|
10444
10407
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -10555,7 +10518,7 @@ ${r.stderr}`;
|
|
|
10555
10518
|
}
|
|
10556
10519
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
10557
10520
|
function selfUpdateAppliedMarkerPath() {
|
|
10558
|
-
return
|
|
10521
|
+
return join25(homedir11(), ".augmented", ".last-self-update-applied");
|
|
10559
10522
|
}
|
|
10560
10523
|
var selfUpdateUpToDateLogged = false;
|
|
10561
10524
|
var selfUpdatePinnedLogged = false;
|
|
@@ -10583,7 +10546,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
10583
10546
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
10584
10547
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
10585
10548
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
10586
|
-
const markerPath =
|
|
10549
|
+
const markerPath = join25(homedir11(), ".augmented", ".last-update-check");
|
|
10587
10550
|
if (!force) {
|
|
10588
10551
|
try {
|
|
10589
10552
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -10943,13 +10906,13 @@ async function checkClaudeAuth() {
|
|
|
10943
10906
|
var evalEmptyMcpConfigPath = null;
|
|
10944
10907
|
function ensureEvalEmptyMcpConfig() {
|
|
10945
10908
|
if (evalEmptyMcpConfigPath && existsSync11(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
10946
|
-
const dir =
|
|
10909
|
+
const dir = join25(homedir11(), ".augmented");
|
|
10947
10910
|
try {
|
|
10948
|
-
|
|
10911
|
+
mkdirSync10(dir, { recursive: true });
|
|
10949
10912
|
} catch {
|
|
10950
10913
|
}
|
|
10951
|
-
const p =
|
|
10952
|
-
|
|
10914
|
+
const p = join25(dir, ".eval-empty-mcp.json");
|
|
10915
|
+
writeFileSync12(p, JSON.stringify({ mcpServers: {} }));
|
|
10953
10916
|
evalEmptyMcpConfigPath = p;
|
|
10954
10917
|
return p;
|
|
10955
10918
|
}
|
|
@@ -10974,7 +10937,7 @@ async function runEvalClaude(prompt, model) {
|
|
|
10974
10937
|
""
|
|
10975
10938
|
];
|
|
10976
10939
|
const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
|
|
10977
|
-
cwd:
|
|
10940
|
+
cwd: homedir11(),
|
|
10978
10941
|
timeout: 12e4,
|
|
10979
10942
|
stdin: "ignore",
|
|
10980
10943
|
env: childEnv,
|
|
@@ -11040,10 +11003,10 @@ function resolveConversationEvalBackend() {
|
|
|
11040
11003
|
return conversationEvalBackend;
|
|
11041
11004
|
}
|
|
11042
11005
|
function getStateFile() {
|
|
11043
|
-
return
|
|
11006
|
+
return join25(config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
11044
11007
|
}
|
|
11045
11008
|
function channelHashCacheDir() {
|
|
11046
|
-
return config?.configDir ??
|
|
11009
|
+
return config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
11047
11010
|
}
|
|
11048
11011
|
function loadChannelHashCache2() {
|
|
11049
11012
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -11097,7 +11060,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
11097
11060
|
var _channelQuarantineStore = null;
|
|
11098
11061
|
function channelQuarantineStore() {
|
|
11099
11062
|
if (!_channelQuarantineStore) {
|
|
11100
|
-
const dir = config?.configDir ??
|
|
11063
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
11101
11064
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
11102
11065
|
}
|
|
11103
11066
|
return _channelQuarantineStore;
|
|
@@ -11114,7 +11077,7 @@ function claudeMdSizeFor(codeName) {
|
|
|
11114
11077
|
var _hostFlagStore = null;
|
|
11115
11078
|
function hostFlagStore() {
|
|
11116
11079
|
if (!_hostFlagStore) {
|
|
11117
|
-
const dir = config?.configDir ??
|
|
11080
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
11118
11081
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
11119
11082
|
}
|
|
11120
11083
|
return _hostFlagStore;
|
|
@@ -11184,13 +11147,13 @@ function parseSkillFrontmatter(content) {
|
|
|
11184
11147
|
return out;
|
|
11185
11148
|
}
|
|
11186
11149
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
11187
|
-
const { readdirSync: readdirSync8, readFileSync: rfs, existsSync: ex, writeFileSync:
|
|
11188
|
-
const skillsDir =
|
|
11189
|
-
const claudeMdPath =
|
|
11150
|
+
const { readdirSync: readdirSync8, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync13 } = await import("fs");
|
|
11151
|
+
const skillsDir = join25(configDir, codeName, "project", ".claude", "skills");
|
|
11152
|
+
const claudeMdPath = join25(configDir, codeName, "project", "CLAUDE.md");
|
|
11190
11153
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
11191
11154
|
const entries = [];
|
|
11192
11155
|
for (const dir of readdirSync8(skillsDir).sort()) {
|
|
11193
|
-
const skillFile =
|
|
11156
|
+
const skillFile = join25(skillsDir, dir, "SKILL.md");
|
|
11194
11157
|
if (!ex(skillFile)) continue;
|
|
11195
11158
|
try {
|
|
11196
11159
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -11234,7 +11197,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
11234
11197
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
11235
11198
|
}
|
|
11236
11199
|
if (next !== current) {
|
|
11237
|
-
|
|
11200
|
+
writeFileSync13(claudeMdPath, next, "utf-8");
|
|
11238
11201
|
log2(
|
|
11239
11202
|
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)`
|
|
11240
11203
|
);
|
|
@@ -11257,7 +11220,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
11257
11220
|
if (codeNames.length === 0) return;
|
|
11258
11221
|
void (async () => {
|
|
11259
11222
|
try {
|
|
11260
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11223
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
11261
11224
|
await api.post("/host/heartbeat", {
|
|
11262
11225
|
host_id: hostId,
|
|
11263
11226
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -11364,7 +11327,7 @@ async function pollCycle() {
|
|
|
11364
11327
|
}
|
|
11365
11328
|
try {
|
|
11366
11329
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
11367
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11330
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
11368
11331
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
11369
11332
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
|
|
11370
11333
|
let tailscaleHostname;
|
|
@@ -11478,7 +11441,7 @@ async function pollCycle() {
|
|
|
11478
11441
|
collectResponsivenessProbes,
|
|
11479
11442
|
collectPanelessActivityProbes,
|
|
11480
11443
|
getResponsivenessIntervalMs
|
|
11481
|
-
} = await import("../responsiveness-probe-
|
|
11444
|
+
} = await import("../responsiveness-probe-5AG6X2BN.js");
|
|
11482
11445
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
11483
11446
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
11484
11447
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -11542,7 +11505,7 @@ async function pollCycle() {
|
|
|
11542
11505
|
collectResponsivenessProbes,
|
|
11543
11506
|
livePendingInboundOldestAgeSeconds,
|
|
11544
11507
|
parkPendingInbound
|
|
11545
|
-
} = await import("../responsiveness-probe-
|
|
11508
|
+
} = await import("../responsiveness-probe-5AG6X2BN.js");
|
|
11546
11509
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
11547
11510
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
11548
11511
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11631,13 +11594,13 @@ async function pollCycle() {
|
|
|
11631
11594
|
);
|
|
11632
11595
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
11633
11596
|
try {
|
|
11634
|
-
const paneTail =
|
|
11597
|
+
const paneTail = readFileSync21(paneLogPath(codeName), "utf8").slice(-65536);
|
|
11635
11598
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
11636
11599
|
if (transient) {
|
|
11637
|
-
const wedgeHome =
|
|
11600
|
+
const wedgeHome = join25(homedir11(), ".augmented", codeName);
|
|
11638
11601
|
if (existsSync11(wedgeHome)) {
|
|
11639
11602
|
atomicWriteFileSync(
|
|
11640
|
-
|
|
11603
|
+
join25(wedgeHome, "watchdog-give-up.json"),
|
|
11641
11604
|
JSON.stringify({
|
|
11642
11605
|
gave_up_at: wedgeNow.toISOString(),
|
|
11643
11606
|
reason: "transient_overload"
|
|
@@ -11908,8 +11871,8 @@ async function pollCycle() {
|
|
|
11908
11871
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
11909
11872
|
stopAgentRuntime2(prev.codeName, "removed-from-host");
|
|
11910
11873
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
11911
|
-
const
|
|
11912
|
-
await cleanupAgentFiles(prev.codeName,
|
|
11874
|
+
const agentDir = join25(adapter.getAgentDir(prev.codeName), "provision");
|
|
11875
|
+
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
11913
11876
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
11914
11877
|
}
|
|
11915
11878
|
}
|
|
@@ -11995,10 +11958,10 @@ async function pollCycle() {
|
|
|
11995
11958
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
11996
11959
|
// the watchdog, never fails the poll cycle.
|
|
11997
11960
|
signalGiveUp: (codeName) => {
|
|
11998
|
-
const dir =
|
|
11961
|
+
const dir = join25(homedir11(), ".augmented", codeName);
|
|
11999
11962
|
if (!existsSync11(dir)) return;
|
|
12000
11963
|
atomicWriteFileSync(
|
|
12001
|
-
|
|
11964
|
+
join25(dir, "watchdog-give-up.json"),
|
|
12002
11965
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
12003
11966
|
);
|
|
12004
11967
|
}
|
|
@@ -12140,7 +12103,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12140
12103
|
}
|
|
12141
12104
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12142
12105
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
12143
|
-
let
|
|
12106
|
+
let agentDir = join25(adapter.getAgentDir(agent.code_name), "provision");
|
|
12144
12107
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
12145
12108
|
if (previousKnownStatus !== agent.status) {
|
|
12146
12109
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -12180,7 +12143,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12180
12143
|
const residuals = {
|
|
12181
12144
|
gatewayRunning: false,
|
|
12182
12145
|
portAllocated: false,
|
|
12183
|
-
provisionDirExists: existsSync11(
|
|
12146
|
+
provisionDirExists: existsSync11(agentDir)
|
|
12184
12147
|
};
|
|
12185
12148
|
if (!hasRevokedResiduals(residuals)) {
|
|
12186
12149
|
agentStates.push({
|
|
@@ -12205,7 +12168,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12205
12168
|
log(`Agent '${agent.code_name}' is revoked, cleaning up`);
|
|
12206
12169
|
stopAgentRuntime2(agent.code_name, "revoked");
|
|
12207
12170
|
killAgentChannelProcesses(agent.code_name, { log });
|
|
12208
|
-
await cleanupAgentFiles(agent.code_name,
|
|
12171
|
+
await cleanupAgentFiles(agent.code_name, agentDir);
|
|
12209
12172
|
clearAgentCaches(agent.agent_id, agent.code_name);
|
|
12210
12173
|
agentState.knownStatuses.set(agent.agent_id, agent.status);
|
|
12211
12174
|
agentStates.push({
|
|
@@ -12314,7 +12277,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12314
12277
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
12315
12278
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
12316
12279
|
const frameworkAdapter = getFramework(frameworkId);
|
|
12317
|
-
|
|
12280
|
+
agentDir = join25(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
12318
12281
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
12319
12282
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
12320
12283
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -12361,9 +12324,9 @@ async function processAgent(agent, agentStates) {
|
|
|
12361
12324
|
try {
|
|
12362
12325
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter, renderIntegrationsSection);
|
|
12363
12326
|
const changedFiles = [];
|
|
12364
|
-
|
|
12327
|
+
mkdirSync10(agentDir, { recursive: true });
|
|
12365
12328
|
for (const artifact of artifacts) {
|
|
12366
|
-
const filePath =
|
|
12329
|
+
const filePath = join25(agentDir, artifact.relativePath);
|
|
12367
12330
|
let existingHash;
|
|
12368
12331
|
let newHash;
|
|
12369
12332
|
let writeContent = artifact.content;
|
|
@@ -12382,8 +12345,8 @@ async function processAgent(agent, agentStates) {
|
|
|
12382
12345
|
};
|
|
12383
12346
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
12384
12347
|
try {
|
|
12385
|
-
const projectClaudeMd =
|
|
12386
|
-
const existing =
|
|
12348
|
+
const projectClaudeMd = join25(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
12349
|
+
const existing = readFileSync21(projectClaudeMd, "utf-8");
|
|
12387
12350
|
existingHash = sha256(stripDynamicSections(existing));
|
|
12388
12351
|
} catch {
|
|
12389
12352
|
existingHash = null;
|
|
@@ -12401,7 +12364,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12401
12364
|
const generatorKeys = Object.keys(generatorServers);
|
|
12402
12365
|
let existingRaw = "";
|
|
12403
12366
|
try {
|
|
12404
|
-
existingRaw =
|
|
12367
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
12405
12368
|
} catch {
|
|
12406
12369
|
}
|
|
12407
12370
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -12417,7 +12380,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12417
12380
|
} else if (artifact.relativePath === "opencode.json") {
|
|
12418
12381
|
let existingRaw = null;
|
|
12419
12382
|
try {
|
|
12420
|
-
existingRaw =
|
|
12383
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
12421
12384
|
} catch {
|
|
12422
12385
|
}
|
|
12423
12386
|
const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
|
|
@@ -12433,26 +12396,26 @@ async function processAgent(agent, agentStates) {
|
|
|
12433
12396
|
}
|
|
12434
12397
|
}
|
|
12435
12398
|
if (changedFiles.length > 0) {
|
|
12436
|
-
const isFirst = !existsSync11(
|
|
12399
|
+
const isFirst = !existsSync11(join25(agentDir, "CHARTER.md"));
|
|
12437
12400
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
12438
12401
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
12439
12402
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
12440
12403
|
for (const file of changedFiles) {
|
|
12441
|
-
const filePath =
|
|
12442
|
-
|
|
12404
|
+
const filePath = join25(agentDir, file.relativePath);
|
|
12405
|
+
mkdirSync10(dirname8(filePath), { recursive: true });
|
|
12443
12406
|
if (file.relativePath === ".mcp.json") {
|
|
12444
12407
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
12445
12408
|
} else {
|
|
12446
|
-
|
|
12409
|
+
writeFileSync12(filePath, file.content);
|
|
12447
12410
|
}
|
|
12448
12411
|
}
|
|
12449
12412
|
try {
|
|
12450
|
-
const provSkillsDir =
|
|
12413
|
+
const provSkillsDir = join25(agentDir, ".claude", "skills");
|
|
12451
12414
|
if (existsSync11(provSkillsDir)) {
|
|
12452
12415
|
for (const folder of readdirSync7(provSkillsDir)) {
|
|
12453
12416
|
if (folder.startsWith("knowledge-")) {
|
|
12454
12417
|
try {
|
|
12455
|
-
|
|
12418
|
+
rmSync5(join25(provSkillsDir, folder), { recursive: true });
|
|
12456
12419
|
} catch {
|
|
12457
12420
|
}
|
|
12458
12421
|
}
|
|
@@ -12465,7 +12428,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12465
12428
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
12466
12429
|
const hashes = /* @__PURE__ */ new Map();
|
|
12467
12430
|
for (const file of trackedFiles2) {
|
|
12468
|
-
const h = hashFile(
|
|
12431
|
+
const h = hashFile(join25(agentDir, file));
|
|
12469
12432
|
if (h) hashes.set(file, h);
|
|
12470
12433
|
}
|
|
12471
12434
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -12473,7 +12436,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12473
12436
|
const primaryModel2 = resolvedModelsForRegistration.primary ?? refreshData.agent.primary_model;
|
|
12474
12437
|
const registeredAgents = await getOrCacheRegisteredAgents(frameworkAdapter, agent.code_name);
|
|
12475
12438
|
if (!registeredAgents.has(agent.code_name)) {
|
|
12476
|
-
const registered = await frameworkAdapter.registerAgent(agent.code_name,
|
|
12439
|
+
const registered = await frameworkAdapter.registerAgent(agent.code_name, agentDir, primaryModel2, agent.agent_id);
|
|
12477
12440
|
if (registered) {
|
|
12478
12441
|
registeredAgents.add(agent.code_name);
|
|
12479
12442
|
log(`Registered '${agent.code_name}' in ${frameworkAdapter.label}`);
|
|
@@ -12483,14 +12446,14 @@ async function processAgent(agent, agentStates) {
|
|
|
12483
12446
|
}
|
|
12484
12447
|
if (Array.isArray(refreshData.workflows)) {
|
|
12485
12448
|
try {
|
|
12486
|
-
const provWorkflowsDir =
|
|
12449
|
+
const provWorkflowsDir = join25(agentDir, ".claude", "workflows");
|
|
12487
12450
|
if (existsSync11(provWorkflowsDir)) {
|
|
12488
12451
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
12489
12452
|
for (const file of readdirSync7(provWorkflowsDir)) {
|
|
12490
12453
|
if (!file.endsWith(".js")) continue;
|
|
12491
12454
|
if (expected.has(file)) continue;
|
|
12492
12455
|
try {
|
|
12493
|
-
|
|
12456
|
+
rmSync5(join25(provWorkflowsDir, file));
|
|
12494
12457
|
} catch {
|
|
12495
12458
|
}
|
|
12496
12459
|
}
|
|
@@ -12499,7 +12462,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12499
12462
|
}
|
|
12500
12463
|
}
|
|
12501
12464
|
if (frameworkAdapter.deployArtifactsToProject) {
|
|
12502
|
-
frameworkAdapter.deployArtifactsToProject(agent.code_name,
|
|
12465
|
+
frameworkAdapter.deployArtifactsToProject(agent.code_name, agentDir);
|
|
12503
12466
|
}
|
|
12504
12467
|
} catch (err) {
|
|
12505
12468
|
log(`Provision failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -12569,10 +12532,10 @@ async function processAgent(agent, agentStates) {
|
|
|
12569
12532
|
}
|
|
12570
12533
|
let lastDriftCheckAt = now;
|
|
12571
12534
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
12572
|
-
if (written && existsSync11(
|
|
12535
|
+
if (written && existsSync11(agentDir)) {
|
|
12573
12536
|
const driftedFiles = [];
|
|
12574
12537
|
for (const [file, expectedHash] of written) {
|
|
12575
|
-
const localHash = hashFile(
|
|
12538
|
+
const localHash = hashFile(join25(agentDir, file));
|
|
12576
12539
|
if (localHash && localHash !== expectedHash) {
|
|
12577
12540
|
driftedFiles.push(file);
|
|
12578
12541
|
}
|
|
@@ -12583,7 +12546,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12583
12546
|
try {
|
|
12584
12547
|
const localHashes = {};
|
|
12585
12548
|
for (const file of driftedFiles) {
|
|
12586
|
-
localHashes[file] = hashFile(
|
|
12549
|
+
localHashes[file] = hashFile(join25(agentDir, file));
|
|
12587
12550
|
}
|
|
12588
12551
|
await api.post("/host/drift", {
|
|
12589
12552
|
agent_id: agent.agent_id,
|
|
@@ -12785,15 +12748,15 @@ async function processAgent(agent, agentStates) {
|
|
|
12785
12748
|
const addedChannels = [...restartDecision.added];
|
|
12786
12749
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
12787
12750
|
try {
|
|
12788
|
-
const agentAugmentedDir =
|
|
12789
|
-
|
|
12751
|
+
const agentAugmentedDir = join25(homedir11(), ".augmented", agent.code_name);
|
|
12752
|
+
mkdirSync10(agentAugmentedDir, { recursive: true });
|
|
12790
12753
|
const markerJson = JSON.stringify({
|
|
12791
12754
|
version: 1,
|
|
12792
12755
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12793
12756
|
added: addedChannels
|
|
12794
12757
|
});
|
|
12795
12758
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
12796
|
-
atomicWriteFileSync(
|
|
12759
|
+
atomicWriteFileSync(join25(agentAugmentedDir, file), markerJson);
|
|
12797
12760
|
}
|
|
12798
12761
|
} catch (err) {
|
|
12799
12762
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -12981,19 +12944,19 @@ async function processAgent(agent, agentStates) {
|
|
|
12981
12944
|
const agentSessionMode = refreshData.agent.session_mode;
|
|
12982
12945
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
12983
12946
|
try {
|
|
12984
|
-
const agentProvisionDir =
|
|
12985
|
-
const projectDir =
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
const provisionMcpPath =
|
|
12989
|
-
const projectMcpPath =
|
|
12947
|
+
const agentProvisionDir = agentDir;
|
|
12948
|
+
const projectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
12949
|
+
mkdirSync10(agentProvisionDir, { recursive: true });
|
|
12950
|
+
mkdirSync10(projectDir, { recursive: true });
|
|
12951
|
+
const provisionMcpPath = join25(agentProvisionDir, ".mcp.json");
|
|
12952
|
+
const projectMcpPath = join25(projectDir, ".mcp.json");
|
|
12990
12953
|
let mcpConfig = { mcpServers: {} };
|
|
12991
12954
|
try {
|
|
12992
|
-
mcpConfig = JSON.parse(
|
|
12955
|
+
mcpConfig = JSON.parse(readFileSync21(provisionMcpPath, "utf-8"));
|
|
12993
12956
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
12994
12957
|
} catch {
|
|
12995
12958
|
}
|
|
12996
|
-
const localDirectChatChannel =
|
|
12959
|
+
const localDirectChatChannel = join25(homedir11(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
12997
12960
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
12998
12961
|
const directChatTz = (() => {
|
|
12999
12962
|
const tz = directChatTeamSettings?.["timezone"];
|
|
@@ -13019,7 +12982,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13019
12982
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
13020
12983
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
13021
12984
|
// so it byte-matches the broker readers' path.
|
|
13022
|
-
AGT_TURN_INITIATOR_FILE:
|
|
12985
|
+
AGT_TURN_INITIATOR_FILE: join25(
|
|
13023
12986
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
13024
12987
|
".current-turn-initiator.json"
|
|
13025
12988
|
)
|
|
@@ -13039,10 +13002,10 @@ async function processAgent(agent, agentStates) {
|
|
|
13039
13002
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
13040
13003
|
}
|
|
13041
13004
|
}
|
|
13042
|
-
const staleChannelsPath =
|
|
13005
|
+
const staleChannelsPath = join25(projectDir, ".mcp-channels.json");
|
|
13043
13006
|
if (existsSync11(staleChannelsPath)) {
|
|
13044
13007
|
try {
|
|
13045
|
-
|
|
13008
|
+
rmSync5(staleChannelsPath, { force: true });
|
|
13046
13009
|
} catch {
|
|
13047
13010
|
}
|
|
13048
13011
|
}
|
|
@@ -13129,7 +13092,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13129
13092
|
}
|
|
13130
13093
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
13131
13094
|
try {
|
|
13132
|
-
const probeProjectDir =
|
|
13095
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13133
13096
|
let probeSet = integrations;
|
|
13134
13097
|
try {
|
|
13135
13098
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -13175,7 +13138,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13175
13138
|
const forceDue = attemptsLeft > 0;
|
|
13176
13139
|
let probeRan = false;
|
|
13177
13140
|
try {
|
|
13178
|
-
const probeProjectDir =
|
|
13141
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13179
13142
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
13180
13143
|
} catch (err) {
|
|
13181
13144
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -13252,11 +13215,11 @@ async function processAgent(agent, agentStates) {
|
|
|
13252
13215
|
const intHash = computeIntegrationsHash(integrations);
|
|
13253
13216
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
13254
13217
|
if (intHash !== prevIntHash) {
|
|
13255
|
-
const projectDir =
|
|
13256
|
-
const envIntPath =
|
|
13218
|
+
const projectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13219
|
+
const envIntPath = join25(projectDir, ".env.integrations");
|
|
13257
13220
|
let preWriteEnv;
|
|
13258
13221
|
try {
|
|
13259
|
-
preWriteEnv =
|
|
13222
|
+
preWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
13260
13223
|
} catch {
|
|
13261
13224
|
preWriteEnv = void 0;
|
|
13262
13225
|
}
|
|
@@ -13275,9 +13238,9 @@ async function processAgent(agent, agentStates) {
|
|
|
13275
13238
|
}
|
|
13276
13239
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
13277
13240
|
try {
|
|
13278
|
-
const projectMcpPath =
|
|
13279
|
-
const postWriteEnv =
|
|
13280
|
-
const mcpContent =
|
|
13241
|
+
const projectMcpPath = join25(projectDir, ".mcp.json");
|
|
13242
|
+
const postWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
13243
|
+
const mcpContent = readFileSync21(projectMcpPath, "utf-8");
|
|
13281
13244
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
13282
13245
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
13283
13246
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -13523,17 +13486,17 @@ async function processAgent(agent, agentStates) {
|
|
|
13523
13486
|
}
|
|
13524
13487
|
}
|
|
13525
13488
|
try {
|
|
13526
|
-
const { readdirSync: readdirSync8, rmSync:
|
|
13527
|
-
const { homedir:
|
|
13489
|
+
const { readdirSync: readdirSync8, rmSync: rmSync6 } = await import("fs");
|
|
13490
|
+
const { homedir: homedir12 } = await import("os");
|
|
13528
13491
|
const frameworkId2 = frameworkAdapter.id;
|
|
13529
13492
|
const candidateSkillDirs = [
|
|
13530
13493
|
// Claude Code — framework runtime tree
|
|
13531
|
-
|
|
13494
|
+
join25(homedir12(), ".augmented", agent.code_name, "skills"),
|
|
13532
13495
|
// Claude Code — project tree
|
|
13533
|
-
|
|
13496
|
+
join25(homedir12(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13534
13497
|
// Defensive: legacy provision-side path, not currently an
|
|
13535
13498
|
// install target but cheap to sweep.
|
|
13536
|
-
|
|
13499
|
+
join25(agentDir, ".claude", "skills")
|
|
13537
13500
|
];
|
|
13538
13501
|
const existingDirs = candidateSkillDirs.filter((d) => existsSync11(d));
|
|
13539
13502
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
@@ -13549,9 +13512,9 @@ async function processAgent(agent, agentStates) {
|
|
|
13549
13512
|
}
|
|
13550
13513
|
const removeSkillFolder = (entry, reason) => {
|
|
13551
13514
|
for (const dir of existingDirs) {
|
|
13552
|
-
const p =
|
|
13515
|
+
const p = join25(dir, entry);
|
|
13553
13516
|
if (existsSync11(p)) {
|
|
13554
|
-
|
|
13517
|
+
rmSync6(p, { recursive: true, force: true });
|
|
13555
13518
|
}
|
|
13556
13519
|
}
|
|
13557
13520
|
log(`Removed ${reason} '${entry}' for '${agent.code_name}' (framework=${frameworkId2})`);
|
|
@@ -13569,7 +13532,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13569
13532
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
13570
13533
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
13571
13534
|
const manifestPath = managedSkillManifestPath(
|
|
13572
|
-
|
|
13535
|
+
join25(homedir11(), ".augmented", agent.code_name)
|
|
13573
13536
|
);
|
|
13574
13537
|
const prevIds = /* @__PURE__ */ new Set([
|
|
13575
13538
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -13589,16 +13552,16 @@ async function processAgent(agent, agentStates) {
|
|
|
13589
13552
|
}
|
|
13590
13553
|
if (plan.removes.length) {
|
|
13591
13554
|
const globalSkillDirs = [
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13555
|
+
join25(homedir11(), ".augmented", agent.code_name, "skills"),
|
|
13556
|
+
join25(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13557
|
+
join25(agentDir, ".claude", "skills")
|
|
13595
13558
|
];
|
|
13596
13559
|
for (const id of plan.removes) {
|
|
13597
13560
|
let prunedAny = false;
|
|
13598
13561
|
for (const dir of globalSkillDirs) {
|
|
13599
|
-
const p =
|
|
13600
|
-
if (existsSync11(p) && existsSync11(
|
|
13601
|
-
|
|
13562
|
+
const p = join25(dir, id);
|
|
13563
|
+
if (existsSync11(p) && existsSync11(join25(p, "SKILL.md"))) {
|
|
13564
|
+
rmSync5(p, { recursive: true, force: true });
|
|
13602
13565
|
prunedAny = true;
|
|
13603
13566
|
}
|
|
13604
13567
|
}
|
|
@@ -13745,7 +13708,10 @@ async function processAgent(agent, agentStates) {
|
|
|
13745
13708
|
);
|
|
13746
13709
|
}
|
|
13747
13710
|
} else if (nudgeAction === "nudge") {
|
|
13748
|
-
const tickLimitedUntil =
|
|
13711
|
+
const tickLimitedUntil = readUsageCapUntil({
|
|
13712
|
+
codeName: agent.code_name,
|
|
13713
|
+
projectDir: getProjectDir(agent.code_name)
|
|
13714
|
+
});
|
|
13749
13715
|
if (tickLimitedUntil) {
|
|
13750
13716
|
if (shouldLogUsageCapDeferral("kanban-tick", agent.code_name, tickLimitedUntil)) {
|
|
13751
13717
|
log(
|
|
@@ -13825,8 +13791,8 @@ async function processAgent(agent, agentStates) {
|
|
|
13825
13791
|
const sess = getSessionState(agent.code_name);
|
|
13826
13792
|
let mcpJsonParsed = null;
|
|
13827
13793
|
try {
|
|
13828
|
-
const mcpPath =
|
|
13829
|
-
mcpJsonParsed = JSON.parse(
|
|
13794
|
+
const mcpPath = join25(getProjectDir(agent.code_name), ".mcp.json");
|
|
13795
|
+
mcpJsonParsed = JSON.parse(readFileSync21(mcpPath, "utf-8"));
|
|
13830
13796
|
} catch {
|
|
13831
13797
|
}
|
|
13832
13798
|
reapMissingMcpSessions({
|
|
@@ -14249,10 +14215,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
14249
14215
|
}
|
|
14250
14216
|
}
|
|
14251
14217
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
14252
|
-
if (trackedFiles.length > 0 && existsSync11(
|
|
14218
|
+
if (trackedFiles.length > 0 && existsSync11(agentDir)) {
|
|
14253
14219
|
const hashes = /* @__PURE__ */ new Map();
|
|
14254
14220
|
for (const file of trackedFiles) {
|
|
14255
|
-
const h = hashFile(
|
|
14221
|
+
const h = hashFile(join25(agentDir, file));
|
|
14256
14222
|
if (h) hashes.set(file, h);
|
|
14257
14223
|
}
|
|
14258
14224
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -14267,7 +14233,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
14267
14233
|
refreshData.agent.onboarding_state
|
|
14268
14234
|
);
|
|
14269
14235
|
const obStep = obState.step;
|
|
14270
|
-
const markerPath =
|
|
14236
|
+
const markerPath = join25(homedir11(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
14271
14237
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
14272
14238
|
const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
|
|
14273
14239
|
if (decision.clearMarker) {
|
|
@@ -14321,20 +14287,6 @@ var lastModelApiErrorSig = /* @__PURE__ */ new Map();
|
|
|
14321
14287
|
var DAY_ROLLOVER_FORCE_GRACE_MIN = 30;
|
|
14322
14288
|
var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
|
|
14323
14289
|
var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
14324
|
-
var claudeAccountByAgent = /* @__PURE__ */ new Map();
|
|
14325
|
-
function _resetClaudeAccountByAgent() {
|
|
14326
|
-
claudeAccountByAgent.clear();
|
|
14327
|
-
}
|
|
14328
|
-
function clearUsageLimitMarkerOnAccountChange(codeName, fingerprint3, log2) {
|
|
14329
|
-
if (!fingerprint3) return;
|
|
14330
|
-
const previous = claudeAccountByAgent.get(codeName);
|
|
14331
|
-
claudeAccountByAgent.set(codeName, fingerprint3);
|
|
14332
|
-
if (previous === void 0 || previous === fingerprint3) return;
|
|
14333
|
-
log2(
|
|
14334
|
-
`[usage-banner] signed-in Claude account changed for '${codeName}' (${previous} \u2192 ${fingerprint3}) \u2014 clearing the usage-limit marker; the cap belonged to the previous account (ENG-8202)`
|
|
14335
|
-
);
|
|
14336
|
-
clearUsageLimitMarker(codeName, log2);
|
|
14337
|
-
}
|
|
14338
14290
|
var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
|
|
14339
14291
|
var egressAllowlistBySession = /* @__PURE__ */ new Map();
|
|
14340
14292
|
function deriveEgressAllowlist(toolsRaw) {
|
|
@@ -14369,7 +14321,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
14369
14321
|
}
|
|
14370
14322
|
stopOpencodeSlackIngest(codeName, log);
|
|
14371
14323
|
stopOpencodeTelegramIngest(codeName, log);
|
|
14372
|
-
const opencodeProjectDir =
|
|
14324
|
+
const opencodeProjectDir = join25(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
14373
14325
|
const serveEnv = {
|
|
14374
14326
|
AGT_HOST: requireHost(),
|
|
14375
14327
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -14412,8 +14364,8 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
14412
14364
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
14413
14365
|
const codeName = agent.code_name;
|
|
14414
14366
|
const projectDir = getProjectDir(codeName);
|
|
14415
|
-
const mcpConfigPath =
|
|
14416
|
-
const claudeMdPath =
|
|
14367
|
+
const mcpConfigPath = join25(projectDir, ".mcp.json");
|
|
14368
|
+
const claudeMdPath = join25(projectDir, "CLAUDE.md");
|
|
14417
14369
|
if (restartBreaker.isTripped(codeName)) {
|
|
14418
14370
|
const trip = restartBreaker.getTrip(codeName);
|
|
14419
14371
|
return {
|
|
@@ -14552,7 +14504,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
14552
14504
|
let dayRolloverDeferred = false;
|
|
14553
14505
|
let dayRolloverForced = false;
|
|
14554
14506
|
const claudeAccountFingerprint = !openRouterForAgent && claudeAuthMode === "subscription" ? await getClaudeAccountFingerprint() : null;
|
|
14555
|
-
|
|
14507
|
+
noteClaudeAccountChange(codeName, claudeAccountFingerprint, log);
|
|
14556
14508
|
const currentAuthTuple = openRouterForAgent ? `openrouter:${openRouterForAgent.fingerprint ?? openRouterForAgent.model}` : `${claudeAuthMode}:${anthropicApiKeyFingerprint ?? "none"}${claudeAccountFingerprint ? `:${claudeAccountFingerprint}` : ""}`;
|
|
14557
14509
|
const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
|
|
14558
14510
|
if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
|
|
@@ -14736,22 +14688,11 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
|
|
|
14736
14688
|
// host. An agent with no per-agent override inherits the host-wide value;
|
|
14737
14689
|
// the launcher still lets an operator AGT_NOTIFY_DISPATCH env override win.
|
|
14738
14690
|
notifyDispatchMode: hostFlagStore().getStringForAgent("notify-dispatch", agent.agent_id),
|
|
14739
|
-
// ENG-8201: materialize usage-limit-reactive-notice into the spawn env
|
|
14740
|
-
// (AGT_USAGE_LIMIT_REACTIVE_MODE) so the channel MCPs report a usage cap
|
|
14741
|
-
// reactively instead of refusing to dispatch on a prediction. Resolved
|
|
14742
|
-
// PER-AGENT so the rollout can start with one agent rather than a whole
|
|
14743
|
-
// host, and materialized (not just left to the flags-cache) because an
|
|
14744
|
-
// isolated agent's container never mounts that cache — without this the
|
|
14745
|
-
// flip reaches nothing running under Docker isolation.
|
|
14746
|
-
usageLimitReactiveMode: hostFlagStore().getStringForAgent(
|
|
14747
|
-
"usage-limit-reactive-notice",
|
|
14748
|
-
agent.agent_id
|
|
14749
|
-
),
|
|
14750
14691
|
// ENG-8269: materialize wedge-transient-notice into the spawn env so the
|
|
14751
14692
|
// channel MCPs can tell a waiting user their turn died on a transient
|
|
14752
|
-
// provider failure.
|
|
14753
|
-
//
|
|
14754
|
-
// flip reaches nothing running under Docker.
|
|
14693
|
+
// provider failure. Materialized rather than left to the flags-cache
|
|
14694
|
+
// because an isolated agent's container never mounts that cache — without
|
|
14695
|
+
// this the flip reaches nothing running under Docker isolation.
|
|
14755
14696
|
turnFailureNoticeEnabled: hostFlagStore().getBoolean("wedge-transient-notice"),
|
|
14756
14697
|
egressAllowlist,
|
|
14757
14698
|
log
|
|
@@ -14816,7 +14757,10 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
|
|
|
14816
14757
|
}
|
|
14817
14758
|
let deferReadyForUsageCap = false;
|
|
14818
14759
|
if (ready.length > 0) {
|
|
14819
|
-
const schedLimitedUntil =
|
|
14760
|
+
const schedLimitedUntil = readUsageCapUntil({
|
|
14761
|
+
codeName,
|
|
14762
|
+
projectDir: getProjectDir(codeName)
|
|
14763
|
+
});
|
|
14820
14764
|
if (schedLimitedUntil) {
|
|
14821
14765
|
if (shouldLogUsageCapDeferral("persistent-scheduler", codeName, schedLimitedUntil)) {
|
|
14822
14766
|
log(
|
|
@@ -15037,7 +14981,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
15037
14981
|
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}`));
|
|
15038
14982
|
void (async () => {
|
|
15039
14983
|
try {
|
|
15040
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14984
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
15041
14985
|
await api.post("/host/heartbeat", {
|
|
15042
14986
|
host_id: hostId,
|
|
15043
14987
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -15087,7 +15031,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
15087
15031
|
}
|
|
15088
15032
|
try {
|
|
15089
15033
|
const hostId = await getHostId();
|
|
15090
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
15034
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
15091
15035
|
await api.post("/host/heartbeat", {
|
|
15092
15036
|
host_id: hostId,
|
|
15093
15037
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -15377,9 +15321,9 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
15377
15321
|
const useDoorbell = hostFlagStore().getBoolean("direct-chat-doorbell") || isolationMode(agent.codeName) === "docker";
|
|
15378
15322
|
if (useDoorbell) {
|
|
15379
15323
|
try {
|
|
15380
|
-
const doorbell = directChatDoorbellPath(agent.agentId,
|
|
15381
|
-
|
|
15382
|
-
|
|
15324
|
+
const doorbell = directChatDoorbellPath(agent.agentId, homedir11());
|
|
15325
|
+
mkdirSync10(dirname8(doorbell), { recursive: true });
|
|
15326
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
15383
15327
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
15384
15328
|
return;
|
|
15385
15329
|
} catch (err) {
|
|
@@ -15487,9 +15431,9 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
15487
15431
|
}
|
|
15488
15432
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
15489
15433
|
try {
|
|
15490
|
-
const doorbell = directChatDoorbellPath(agentId,
|
|
15491
|
-
|
|
15492
|
-
|
|
15434
|
+
const doorbell = directChatDoorbellPath(agentId, homedir11());
|
|
15435
|
+
mkdirSync10(dirname8(doorbell), { recursive: true });
|
|
15436
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
15493
15437
|
} catch (err) {
|
|
15494
15438
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
15495
15439
|
}
|
|
@@ -15545,7 +15489,7 @@ async function processClaudePairSessions(agents) {
|
|
|
15545
15489
|
killPairSession,
|
|
15546
15490
|
pairTmuxSession,
|
|
15547
15491
|
finalizeClaudePairOnboarding
|
|
15548
|
-
} = await import("../claude-pair-runtime-
|
|
15492
|
+
} = await import("../claude-pair-runtime-IIQ6O7QX.js");
|
|
15549
15493
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
15550
15494
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
15551
15495
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -15799,8 +15743,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
15799
15743
|
};
|
|
15800
15744
|
}
|
|
15801
15745
|
async function syncMemories(agent, configDir, log2) {
|
|
15802
|
-
const projectDir =
|
|
15803
|
-
const memoryDir =
|
|
15746
|
+
const projectDir = join25(configDir, agent.code_name, "project");
|
|
15747
|
+
const memoryDir = join25(projectDir, "memory");
|
|
15804
15748
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
15805
15749
|
if (isFreshSync) {
|
|
15806
15750
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -15818,7 +15762,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15818
15762
|
for (const file of readdirSync7(memoryDir)) {
|
|
15819
15763
|
if (!file.endsWith(".md")) continue;
|
|
15820
15764
|
try {
|
|
15821
|
-
const raw =
|
|
15765
|
+
const raw = readFileSync21(join25(memoryDir, file), "utf-8");
|
|
15822
15766
|
const fileHash = createHash16("sha256").update(raw).digest("hex").slice(0, 16);
|
|
15823
15767
|
currentHashes.set(file, fileHash);
|
|
15824
15768
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -15843,7 +15787,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15843
15787
|
} catch (err) {
|
|
15844
15788
|
for (const mem of changedMemories) {
|
|
15845
15789
|
for (const [file] of currentHashes) {
|
|
15846
|
-
const parsed = parseMemoryFile(
|
|
15790
|
+
const parsed = parseMemoryFile(readFileSync21(join25(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
15847
15791
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
15848
15792
|
}
|
|
15849
15793
|
}
|
|
@@ -15871,14 +15815,14 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
|
15871
15815
|
lastDownloadHash.set(agent.agent_id, responseHash);
|
|
15872
15816
|
lastLocalFileHash.set(agent.agent_id, localListHash);
|
|
15873
15817
|
if (dbMemories.memories?.length) {
|
|
15874
|
-
|
|
15818
|
+
mkdirSync10(memoryDir, { recursive: true });
|
|
15875
15819
|
let written = 0;
|
|
15876
15820
|
let overwritten = 0;
|
|
15877
15821
|
for (let i = 0; i < dbMemories.memories.length; i++) {
|
|
15878
15822
|
const mem = dbMemories.memories[i];
|
|
15879
15823
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
15880
15824
|
const slug = rawSlug || `memory-${i}`;
|
|
15881
|
-
const filePath =
|
|
15825
|
+
const filePath = join25(memoryDir, `${slug}.md`);
|
|
15882
15826
|
const desired = `---
|
|
15883
15827
|
name: ${JSON.stringify(mem.name)}
|
|
15884
15828
|
type: ${mem.type}
|
|
@@ -15890,14 +15834,14 @@ ${mem.content}
|
|
|
15890
15834
|
if (existsSync11(filePath)) {
|
|
15891
15835
|
let existing = "";
|
|
15892
15836
|
try {
|
|
15893
|
-
existing =
|
|
15837
|
+
existing = readFileSync21(filePath, "utf-8");
|
|
15894
15838
|
} catch {
|
|
15895
15839
|
}
|
|
15896
15840
|
if (existing === desired) continue;
|
|
15897
|
-
|
|
15841
|
+
writeFileSync12(filePath, desired);
|
|
15898
15842
|
overwritten++;
|
|
15899
15843
|
} else {
|
|
15900
|
-
|
|
15844
|
+
writeFileSync12(filePath, desired);
|
|
15901
15845
|
written++;
|
|
15902
15846
|
}
|
|
15903
15847
|
}
|
|
@@ -15913,10 +15857,10 @@ ${mem.content}
|
|
|
15913
15857
|
return false;
|
|
15914
15858
|
}
|
|
15915
15859
|
}
|
|
15916
|
-
async function cleanupAgentFiles(codeName,
|
|
15917
|
-
if (existsSync11(
|
|
15860
|
+
async function cleanupAgentFiles(codeName, agentDir) {
|
|
15861
|
+
if (existsSync11(agentDir)) {
|
|
15918
15862
|
try {
|
|
15919
|
-
|
|
15863
|
+
rmSync5(agentDir, { recursive: true, force: true });
|
|
15920
15864
|
log(`Removed provision directory for '${codeName}'`);
|
|
15921
15865
|
} catch (err) {
|
|
15922
15866
|
log(`Failed to remove provision dir for '${codeName}': ${err.message}`);
|
|
@@ -16154,7 +16098,7 @@ function startManager(opts) {
|
|
|
16154
16098
|
try {
|
|
16155
16099
|
const stateFile = getStateFile();
|
|
16156
16100
|
if (existsSync11(stateFile)) {
|
|
16157
|
-
const raw =
|
|
16101
|
+
const raw = readFileSync21(stateFile, "utf-8");
|
|
16158
16102
|
const parsed = JSON.parse(raw);
|
|
16159
16103
|
if (Array.isArray(parsed.agents)) {
|
|
16160
16104
|
state6.agents = parsed.agents;
|
|
@@ -16181,7 +16125,7 @@ function startManager(opts) {
|
|
|
16181
16125
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
16182
16126
|
}
|
|
16183
16127
|
log(
|
|
16184
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
16128
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join25(homedir11(), ".augmented", "manager.log")}`
|
|
16185
16129
|
);
|
|
16186
16130
|
deployMcpAssets();
|
|
16187
16131
|
reapOrphanChannelMcps({ log });
|
|
@@ -16210,7 +16154,7 @@ async function reapOrphanedClaudePids() {
|
|
|
16210
16154
|
const looksLikeClaude = (pid) => {
|
|
16211
16155
|
if (process.platform !== "linux") return true;
|
|
16212
16156
|
try {
|
|
16213
|
-
const comm =
|
|
16157
|
+
const comm = readFileSync21(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
16214
16158
|
return comm.includes("claude");
|
|
16215
16159
|
} catch {
|
|
16216
16160
|
return false;
|
|
@@ -16307,14 +16251,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
16307
16251
|
}
|
|
16308
16252
|
}
|
|
16309
16253
|
function deployMcpAssets() {
|
|
16310
|
-
const targetDir =
|
|
16311
|
-
|
|
16254
|
+
const targetDir = join25(homedir11(), ".augmented", "_mcp");
|
|
16255
|
+
mkdirSync10(targetDir, { recursive: true });
|
|
16312
16256
|
const moduleDir = dirname8(fileURLToPath(import.meta.url));
|
|
16313
16257
|
let mcpSourceDir = "";
|
|
16314
16258
|
let dir = moduleDir;
|
|
16315
16259
|
for (let i = 0; i < 6; i++) {
|
|
16316
|
-
const candidate =
|
|
16317
|
-
if (existsSync11(
|
|
16260
|
+
const candidate = join25(dir, "dist", "mcp");
|
|
16261
|
+
if (existsSync11(join25(candidate, "index.js"))) {
|
|
16318
16262
|
mcpSourceDir = candidate;
|
|
16319
16263
|
break;
|
|
16320
16264
|
}
|
|
@@ -16330,7 +16274,7 @@ function deployMcpAssets() {
|
|
|
16330
16274
|
const fileHash = (p) => {
|
|
16331
16275
|
try {
|
|
16332
16276
|
if (!existsSync11(p)) return null;
|
|
16333
|
-
return createHash16("sha256").update(
|
|
16277
|
+
return createHash16("sha256").update(readFileSync21(p)).digest("hex");
|
|
16334
16278
|
} catch {
|
|
16335
16279
|
return null;
|
|
16336
16280
|
}
|
|
@@ -16394,8 +16338,8 @@ function deployMcpAssets() {
|
|
|
16394
16338
|
// needs restarting to pick up a token rotation.
|
|
16395
16339
|
"xero.js"
|
|
16396
16340
|
]) {
|
|
16397
|
-
const src =
|
|
16398
|
-
const dst =
|
|
16341
|
+
const src = join25(mcpSourceDir, file);
|
|
16342
|
+
const dst = join25(targetDir, file);
|
|
16399
16343
|
if (!existsSync11(src)) continue;
|
|
16400
16344
|
const before = fileHash(dst);
|
|
16401
16345
|
try {
|
|
@@ -16413,23 +16357,23 @@ function deployMcpAssets() {
|
|
|
16413
16357
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
16414
16358
|
restartRunningChannelMcps(changedBasenames);
|
|
16415
16359
|
}
|
|
16416
|
-
const localMcpPath =
|
|
16360
|
+
const localMcpPath = join25(targetDir, "index.js");
|
|
16417
16361
|
try {
|
|
16418
|
-
const agentsDir =
|
|
16362
|
+
const agentsDir = join25(homedir11(), ".augmented", "agents");
|
|
16419
16363
|
if (existsSync11(agentsDir)) {
|
|
16420
16364
|
for (const entry of readdirSync7(agentsDir, { withFileTypes: true })) {
|
|
16421
16365
|
if (!entry.isDirectory()) continue;
|
|
16422
16366
|
for (const subdir of ["provision", "project"]) {
|
|
16423
|
-
const mcpJsonPath =
|
|
16367
|
+
const mcpJsonPath = join25(agentsDir, entry.name, subdir, ".mcp.json");
|
|
16424
16368
|
try {
|
|
16425
|
-
const raw =
|
|
16369
|
+
const raw = readFileSync21(mcpJsonPath, "utf-8");
|
|
16426
16370
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
16427
16371
|
const mcpConfig = JSON.parse(raw);
|
|
16428
16372
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
16429
16373
|
if (!augServer) continue;
|
|
16430
16374
|
augServer.command = "node";
|
|
16431
16375
|
augServer.args = [localMcpPath];
|
|
16432
|
-
|
|
16376
|
+
writeFileSync12(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
16433
16377
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
16434
16378
|
} catch {
|
|
16435
16379
|
}
|
|
@@ -16466,13 +16410,11 @@ process.on("disconnect", () => {
|
|
|
16466
16410
|
export {
|
|
16467
16411
|
BACK_ONLINE_GREETING_GUIDANCE,
|
|
16468
16412
|
DAY_ROLLOVER_FORCE_GRACE_MIN,
|
|
16469
|
-
_resetClaudeAccountByAgent,
|
|
16470
16413
|
applyRestartAcks,
|
|
16471
16414
|
cancelKanbanNoticeOnDrain,
|
|
16472
16415
|
claudeCodeUpgradeMarkerPath,
|
|
16473
16416
|
claudeCodeUpgradeThrottled,
|
|
16474
16417
|
claudeManagedSettingsPath,
|
|
16475
|
-
clearUsageLimitMarkerOnAccountChange,
|
|
16476
16418
|
dashboardRestartBreakerReason,
|
|
16477
16419
|
ensureClaudeManagedSettings,
|
|
16478
16420
|
extractCharterSlackPeers,
|