@integrity-labs/agt-cli 0.28.473 → 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-VHWLFDME.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 +440 -430
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/augmented-admin.js +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-VHWLFDME.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;
|
|
@@ -2576,12 +2450,65 @@ async function getClaudeAccountFingerprint(paths, nowMs = Date.now()) {
|
|
|
2576
2450
|
return lastKnownFingerprint;
|
|
2577
2451
|
}
|
|
2578
2452
|
|
|
2453
|
+
// src/lib/auth-tuple-diff.ts
|
|
2454
|
+
var ABSENT2 = "none";
|
|
2455
|
+
var COMPONENT_ORDER = [
|
|
2456
|
+
"auth_mode",
|
|
2457
|
+
"anthropic_api_key_fingerprint",
|
|
2458
|
+
"claude_account_fingerprint",
|
|
2459
|
+
"openrouter_fingerprint"
|
|
2460
|
+
];
|
|
2461
|
+
function parseAuthTuple(tuple) {
|
|
2462
|
+
const raw = typeof tuple === "string" ? tuple : "";
|
|
2463
|
+
if (raw.startsWith("openrouter:")) {
|
|
2464
|
+
return {
|
|
2465
|
+
auth_mode: "openrouter",
|
|
2466
|
+
openrouter_fingerprint: raw.slice("openrouter:".length) || ABSENT2
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
const parts = raw.split(":");
|
|
2470
|
+
if (parts.length < 2) {
|
|
2471
|
+
return { auth_mode: raw || ABSENT2 };
|
|
2472
|
+
}
|
|
2473
|
+
return {
|
|
2474
|
+
auth_mode: parts[0] || ABSENT2,
|
|
2475
|
+
anthropic_api_key_fingerprint: parts[1] || ABSENT2,
|
|
2476
|
+
// Omitted from the string when there is no signed-in account fingerprint
|
|
2477
|
+
// (api_key mode, or subscription mode before the first successful read).
|
|
2478
|
+
// Recorded as the ABSENT sentinel so "account appeared" / "account
|
|
2479
|
+
// disappeared" is itself visible as a change.
|
|
2480
|
+
claude_account_fingerprint: parts[2] || ABSENT2
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
function diffAuthTuples(recorded, current) {
|
|
2484
|
+
const before = parseAuthTuple(recorded);
|
|
2485
|
+
const after = parseAuthTuple(current);
|
|
2486
|
+
const names = [
|
|
2487
|
+
...COMPONENT_ORDER.filter((n) => n in before || n in after),
|
|
2488
|
+
// Anything unexpected (a tuple shape a newer manager introduced) still gets
|
|
2489
|
+
// reported rather than dropped — this path must never hide a change.
|
|
2490
|
+
...Object.keys({ ...before, ...after }).filter((n) => !COMPONENT_ORDER.includes(n)).sort()
|
|
2491
|
+
];
|
|
2492
|
+
const components = names.map((component) => {
|
|
2493
|
+
const from = before[component] ?? ABSENT2;
|
|
2494
|
+
const to = after[component] ?? ABSENT2;
|
|
2495
|
+
return { component, changed: from !== to, from, to };
|
|
2496
|
+
});
|
|
2497
|
+
const changed = components.filter((c) => c.changed).map((c) => c.component);
|
|
2498
|
+
const unchanged = components.filter((c) => !c.changed).map((c) => c.component);
|
|
2499
|
+
const summary = changed.length === 0 ? "auth-tuple-change: no component differs (tuple string re-formatted)" : `auth-tuple-change: ${changed.map((name) => {
|
|
2500
|
+
const c = components.find((x) => x.component === name);
|
|
2501
|
+
return `${name} ${c.from}\u2192${c.to}`;
|
|
2502
|
+
}).join(", ")}${unchanged.length > 0 ? ` (unchanged: ${unchanged.join(", ")})` : ""}`;
|
|
2503
|
+
return { changed, unchanged, components, summary };
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2579
2506
|
// src/lib/account-enforcement-marker.ts
|
|
2580
|
-
import { mkdirSync as
|
|
2581
|
-
import { homedir as
|
|
2582
|
-
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";
|
|
2583
2510
|
function accountEnforcementMarkerPath(codeName) {
|
|
2584
|
-
return
|
|
2511
|
+
return join8(homedir5(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2585
2512
|
}
|
|
2586
2513
|
function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.stderr.write(`${m}
|
|
2587
2514
|
`)) {
|
|
@@ -2589,16 +2516,16 @@ function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.std
|
|
|
2589
2516
|
clearAccountEnforcementMarker(codeName, log2);
|
|
2590
2517
|
return;
|
|
2591
2518
|
}
|
|
2592
|
-
const dir =
|
|
2593
|
-
const path =
|
|
2519
|
+
const dir = join8(homedir5(), ".augmented", codeName);
|
|
2520
|
+
const path = join8(dir, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2594
2521
|
const tempPath = `${path}.${process.pid}.tmp`;
|
|
2595
2522
|
try {
|
|
2596
|
-
|
|
2597
|
-
|
|
2523
|
+
mkdirSync4(dir, { recursive: true });
|
|
2524
|
+
writeFileSync4(tempPath, serializeAccountEnforcementMarker(level), "utf-8");
|
|
2598
2525
|
renameSync(tempPath, path);
|
|
2599
2526
|
} catch (err) {
|
|
2600
2527
|
try {
|
|
2601
|
-
|
|
2528
|
+
rmSync2(tempPath, { force: true });
|
|
2602
2529
|
} catch {
|
|
2603
2530
|
}
|
|
2604
2531
|
log2(`[account-enforcement] marker sync failed for '${codeName}': ${err.message}`);
|
|
@@ -2608,15 +2535,15 @@ function clearAccountEnforcementMarker(codeName, log2 = (m) => process.stderr.wr
|
|
|
2608
2535
|
`)) {
|
|
2609
2536
|
const path = accountEnforcementMarkerPath(codeName);
|
|
2610
2537
|
try {
|
|
2611
|
-
|
|
2538
|
+
rmSync2(path, { force: true });
|
|
2612
2539
|
} catch (err) {
|
|
2613
2540
|
log2(`[account-enforcement] marker clear failed for '${codeName}': ${err.message}`);
|
|
2614
2541
|
}
|
|
2615
2542
|
}
|
|
2616
2543
|
|
|
2617
2544
|
// src/lib/token-usage-monitor.ts
|
|
2618
|
-
import { readdirSync
|
|
2619
|
-
import { join as
|
|
2545
|
+
import { readdirSync, readFileSync as readFileSync7, statSync } from "fs";
|
|
2546
|
+
import { join as join9 } from "path";
|
|
2620
2547
|
var MIN_CHECK_INTERVAL_MS2 = 6e4;
|
|
2621
2548
|
var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
2622
2549
|
var MAX_ENTRIES_PER_POST = 200;
|
|
@@ -2634,7 +2561,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2634
2561
|
const next = { files, lastCheckedAt: nowMs };
|
|
2635
2562
|
let dirEntries;
|
|
2636
2563
|
try {
|
|
2637
|
-
dirEntries =
|
|
2564
|
+
dirEntries = readdirSync(dir);
|
|
2638
2565
|
} catch {
|
|
2639
2566
|
state2.set(codeName, next);
|
|
2640
2567
|
return;
|
|
@@ -2645,10 +2572,10 @@ async function maybeReportTokenUsage(args) {
|
|
|
2645
2572
|
if (!name.endsWith(".jsonl")) continue;
|
|
2646
2573
|
const sessionId = name.slice(0, -".jsonl".length);
|
|
2647
2574
|
if (!sessionId) continue;
|
|
2648
|
-
const path =
|
|
2575
|
+
const path = join9(dir, name);
|
|
2649
2576
|
let st;
|
|
2650
2577
|
try {
|
|
2651
|
-
st =
|
|
2578
|
+
st = statSync(path);
|
|
2652
2579
|
} catch {
|
|
2653
2580
|
continue;
|
|
2654
2581
|
}
|
|
@@ -2661,7 +2588,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2661
2588
|
}
|
|
2662
2589
|
let content;
|
|
2663
2590
|
try {
|
|
2664
|
-
content =
|
|
2591
|
+
content = readFileSync7(path, "utf-8");
|
|
2665
2592
|
} catch (err) {
|
|
2666
2593
|
log2(`[token-usage] read failed for '${codeName}/${name}': ${err.message}`);
|
|
2667
2594
|
continue;
|
|
@@ -2742,8 +2669,8 @@ async function maybeReportTokenUsage(args) {
|
|
|
2742
2669
|
}
|
|
2743
2670
|
|
|
2744
2671
|
// src/lib/workflow-run-reconciler.ts
|
|
2745
|
-
import { readdirSync as
|
|
2746
|
-
import { join as
|
|
2672
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
2673
|
+
import { join as join10 } from "path";
|
|
2747
2674
|
var MIN_CHECK_INTERVAL_MS3 = 5 * 6e4;
|
|
2748
2675
|
var SETTLE_MS = 3e4;
|
|
2749
2676
|
var TRANSCRIPT_MTIME_WINDOW_MS2 = 2 * 24 * 60 * 60 * 1e3;
|
|
@@ -2757,15 +2684,15 @@ function collectJsonlRecursive(dir, minMtimeMs, out, depth) {
|
|
|
2757
2684
|
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
2758
2685
|
let entries;
|
|
2759
2686
|
try {
|
|
2760
|
-
entries =
|
|
2687
|
+
entries = readdirSync2(dir);
|
|
2761
2688
|
} catch {
|
|
2762
2689
|
return;
|
|
2763
2690
|
}
|
|
2764
2691
|
for (const name of entries) {
|
|
2765
|
-
const p =
|
|
2692
|
+
const p = join10(dir, name);
|
|
2766
2693
|
let st;
|
|
2767
2694
|
try {
|
|
2768
|
-
st =
|
|
2695
|
+
st = statSync2(p);
|
|
2769
2696
|
} catch {
|
|
2770
2697
|
continue;
|
|
2771
2698
|
}
|
|
@@ -2780,15 +2707,15 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2780
2707
|
const out = [];
|
|
2781
2708
|
let entries;
|
|
2782
2709
|
try {
|
|
2783
|
-
entries =
|
|
2710
|
+
entries = readdirSync2(transcriptDir);
|
|
2784
2711
|
} catch {
|
|
2785
2712
|
return out;
|
|
2786
2713
|
}
|
|
2787
2714
|
for (const name of entries) {
|
|
2788
|
-
const path =
|
|
2715
|
+
const path = join10(transcriptDir, name);
|
|
2789
2716
|
let st;
|
|
2790
2717
|
try {
|
|
2791
|
-
st =
|
|
2718
|
+
st = statSync2(path);
|
|
2792
2719
|
} catch {
|
|
2793
2720
|
continue;
|
|
2794
2721
|
}
|
|
@@ -2797,7 +2724,7 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2797
2724
|
continue;
|
|
2798
2725
|
}
|
|
2799
2726
|
if (st.isDirectory()) {
|
|
2800
|
-
collectJsonlRecursive(
|
|
2727
|
+
collectJsonlRecursive(join10(path, "subagents"), minMtimeMs, out, 0);
|
|
2801
2728
|
}
|
|
2802
2729
|
}
|
|
2803
2730
|
return out;
|
|
@@ -2842,7 +2769,7 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2842
2769
|
const contents = [];
|
|
2843
2770
|
for (const path of files) {
|
|
2844
2771
|
try {
|
|
2845
|
-
contents.push(
|
|
2772
|
+
contents.push(readFileSync8(path, "utf-8"));
|
|
2846
2773
|
} catch {
|
|
2847
2774
|
}
|
|
2848
2775
|
}
|
|
@@ -2887,8 +2814,8 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2887
2814
|
}
|
|
2888
2815
|
|
|
2889
2816
|
// src/lib/conversation-evaluator.ts
|
|
2890
|
-
import { readdirSync as
|
|
2891
|
-
import { join as
|
|
2817
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
|
|
2818
|
+
import { join as join11 } from "path";
|
|
2892
2819
|
var MIN_CHECK_INTERVAL_MS4 = 5 * 6e4;
|
|
2893
2820
|
var TRANSCRIPT_MTIME_WINDOW_MS3 = 7 * 24 * 60 * 60 * 1e3;
|
|
2894
2821
|
var WINDOW_PAD_MS = 5 * 6e4;
|
|
@@ -3319,12 +3246,12 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3319
3246
|
const visit = (d) => {
|
|
3320
3247
|
let entries;
|
|
3321
3248
|
try {
|
|
3322
|
-
entries =
|
|
3249
|
+
entries = readdirSync3(d, { withFileTypes: true });
|
|
3323
3250
|
} catch {
|
|
3324
3251
|
return;
|
|
3325
3252
|
}
|
|
3326
3253
|
for (const ent of entries) {
|
|
3327
|
-
const full =
|
|
3254
|
+
const full = join11(d, ent.name);
|
|
3328
3255
|
if (ent.isDirectory()) {
|
|
3329
3256
|
visit(full);
|
|
3330
3257
|
continue;
|
|
@@ -3332,14 +3259,14 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3332
3259
|
if (!ent.isFile() || !ent.name.endsWith(".jsonl")) continue;
|
|
3333
3260
|
let mtimeMs;
|
|
3334
3261
|
try {
|
|
3335
|
-
mtimeMs =
|
|
3262
|
+
mtimeMs = statSync3(full).mtimeMs;
|
|
3336
3263
|
} catch {
|
|
3337
3264
|
continue;
|
|
3338
3265
|
}
|
|
3339
3266
|
if (nowMs - mtimeMs > TRANSCRIPT_MTIME_WINDOW_MS3) continue;
|
|
3340
3267
|
let content;
|
|
3341
3268
|
try {
|
|
3342
|
-
content =
|
|
3269
|
+
content = readFileSync9(full, "utf8");
|
|
3343
3270
|
} catch {
|
|
3344
3271
|
continue;
|
|
3345
3272
|
}
|
|
@@ -3629,11 +3556,11 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
|
|
|
3629
3556
|
}
|
|
3630
3557
|
|
|
3631
3558
|
// src/lib/activity-cache-monitor.ts
|
|
3632
|
-
import { existsSync as existsSync2, readFileSync as
|
|
3633
|
-
import { homedir as
|
|
3634
|
-
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";
|
|
3635
3562
|
var MIN_CHECK_INTERVAL_MS6 = 6e4;
|
|
3636
|
-
var STATS_CACHE_PATH =
|
|
3563
|
+
var STATS_CACHE_PATH = join12(homedir6(), ".claude", "stats-cache.json");
|
|
3637
3564
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
3638
3565
|
var state5 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
3639
3566
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
@@ -3681,7 +3608,7 @@ async function maybeReportActivityCache(args) {
|
|
|
3681
3608
|
}
|
|
3682
3609
|
let raw;
|
|
3683
3610
|
try {
|
|
3684
|
-
raw =
|
|
3611
|
+
raw = readFileSync10(STATS_CACHE_PATH, "utf-8");
|
|
3685
3612
|
} catch (err) {
|
|
3686
3613
|
log2(`[activity-cache] readFileSync failed: ${err.message}`);
|
|
3687
3614
|
return;
|
|
@@ -3885,18 +3812,18 @@ function computeChannelConfigHash(input) {
|
|
|
3885
3812
|
}
|
|
3886
3813
|
|
|
3887
3814
|
// src/lib/channel-hash-cache.ts
|
|
3888
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3889
|
-
import { join as
|
|
3815
|
+
import { existsSync as existsSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "fs";
|
|
3816
|
+
import { join as join13 } from "path";
|
|
3890
3817
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
3891
3818
|
function getChannelHashCacheFile(configDir) {
|
|
3892
|
-
return
|
|
3819
|
+
return join13(configDir, CACHE_FILENAME);
|
|
3893
3820
|
}
|
|
3894
3821
|
function loadChannelHashCache(target, configDir) {
|
|
3895
3822
|
const path = getChannelHashCacheFile(configDir);
|
|
3896
3823
|
if (!existsSync3(path)) return;
|
|
3897
3824
|
let parsed;
|
|
3898
3825
|
try {
|
|
3899
|
-
parsed = JSON.parse(
|
|
3826
|
+
parsed = JSON.parse(readFileSync11(path, "utf-8"));
|
|
3900
3827
|
} catch {
|
|
3901
3828
|
return;
|
|
3902
3829
|
}
|
|
@@ -3910,14 +3837,14 @@ function saveChannelHashCache(source, configDir) {
|
|
|
3910
3837
|
const obj = {};
|
|
3911
3838
|
for (const [key, value] of source) obj[key] = value;
|
|
3912
3839
|
try {
|
|
3913
|
-
|
|
3840
|
+
writeFileSync5(path, JSON.stringify(obj, null, 2));
|
|
3914
3841
|
} catch {
|
|
3915
3842
|
}
|
|
3916
3843
|
}
|
|
3917
3844
|
|
|
3918
3845
|
// src/lib/sender-policy-baseline.ts
|
|
3919
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3920
|
-
import { join as
|
|
3846
|
+
import { existsSync as existsSync4, readFileSync as readFileSync12 } from "fs";
|
|
3847
|
+
import { join as join14 } from "path";
|
|
3921
3848
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
3922
3849
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
3923
3850
|
var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
|
|
@@ -3929,14 +3856,14 @@ function createDeliveryBaselineMaps() {
|
|
|
3929
3856
|
};
|
|
3930
3857
|
}
|
|
3931
3858
|
function getSenderPolicyBaselineFile(configDir) {
|
|
3932
|
-
return
|
|
3859
|
+
return join14(configDir, BASELINE_FILENAME);
|
|
3933
3860
|
}
|
|
3934
3861
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
3935
3862
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
3936
3863
|
if (!existsSync4(path)) return;
|
|
3937
3864
|
let parsed;
|
|
3938
3865
|
try {
|
|
3939
|
-
parsed = JSON.parse(
|
|
3866
|
+
parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
3940
3867
|
} catch (err) {
|
|
3941
3868
|
log2?.(
|
|
3942
3869
|
`[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
|
|
@@ -4459,16 +4386,16 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
4459
4386
|
}
|
|
4460
4387
|
|
|
4461
4388
|
// src/lib/manager/managed-skill-manifest.ts
|
|
4462
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
4463
|
-
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";
|
|
4464
4391
|
var MANIFEST_VERSION = 1;
|
|
4465
4392
|
function managedSkillManifestPath(agentRootDir) {
|
|
4466
|
-
return
|
|
4393
|
+
return join15(agentRootDir, "managed-skills.json");
|
|
4467
4394
|
}
|
|
4468
4395
|
function readManagedSkillManifest(path) {
|
|
4469
4396
|
try {
|
|
4470
4397
|
if (!existsSync5(path)) return /* @__PURE__ */ new Set();
|
|
4471
|
-
const parsed = JSON.parse(
|
|
4398
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
4472
4399
|
const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
|
|
4473
4400
|
return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
|
|
4474
4401
|
} catch {
|
|
@@ -4477,12 +4404,12 @@ function readManagedSkillManifest(path) {
|
|
|
4477
4404
|
}
|
|
4478
4405
|
function writeManagedSkillManifest(path, ids) {
|
|
4479
4406
|
try {
|
|
4480
|
-
|
|
4407
|
+
mkdirSync5(dirname5(path), { recursive: true });
|
|
4481
4408
|
const body = {
|
|
4482
4409
|
version: MANIFEST_VERSION,
|
|
4483
4410
|
globalSkillIds: [...ids].sort()
|
|
4484
4411
|
};
|
|
4485
|
-
|
|
4412
|
+
writeFileSync6(path, JSON.stringify(body, null, 2));
|
|
4486
4413
|
} catch {
|
|
4487
4414
|
}
|
|
4488
4415
|
}
|
|
@@ -4580,9 +4507,9 @@ function resolveModelChain(refreshData) {
|
|
|
4580
4507
|
}
|
|
4581
4508
|
|
|
4582
4509
|
// src/lib/manager/claude-auth.ts
|
|
4583
|
-
import { existsSync as existsSync6, rmSync as
|
|
4584
|
-
import { join as
|
|
4585
|
-
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";
|
|
4586
4513
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
4587
4514
|
const apiKey = getApiKey();
|
|
4588
4515
|
if (!apiKey) {
|
|
@@ -4594,12 +4521,12 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4594
4521
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
4595
4522
|
}
|
|
4596
4523
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
4597
|
-
const claudeDir =
|
|
4524
|
+
const claudeDir = join16(homedir7(), ".claude");
|
|
4598
4525
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
4599
|
-
const p =
|
|
4526
|
+
const p = join16(claudeDir, filename);
|
|
4600
4527
|
if (existsSync6(p)) {
|
|
4601
4528
|
try {
|
|
4602
|
-
|
|
4529
|
+
rmSync3(p, { force: true });
|
|
4603
4530
|
log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
|
|
4604
4531
|
} catch {
|
|
4605
4532
|
}
|
|
@@ -4611,8 +4538,8 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4611
4538
|
}
|
|
4612
4539
|
|
|
4613
4540
|
// src/lib/manager/kanban/parsers.ts
|
|
4614
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4615
|
-
import { join as
|
|
4541
|
+
import { existsSync as existsSync7, readFileSync as readFileSync14 } from "fs";
|
|
4542
|
+
import { join as join17 } from "path";
|
|
4616
4543
|
var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
|
|
4617
4544
|
var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
|
|
4618
4545
|
var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
|
|
@@ -4751,12 +4678,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
4751
4678
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
4752
4679
|
try {
|
|
4753
4680
|
const candidates = [
|
|
4754
|
-
|
|
4755
|
-
|
|
4681
|
+
join17(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
4682
|
+
join17(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
4756
4683
|
];
|
|
4757
4684
|
for (const candidate of candidates) {
|
|
4758
4685
|
if (existsSync7(candidate)) {
|
|
4759
|
-
const content =
|
|
4686
|
+
const content = readFileSync14(candidate, "utf-8");
|
|
4760
4687
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
4761
4688
|
builtInSkillCache.set(skillId, files);
|
|
4762
4689
|
return files;
|
|
@@ -4897,19 +4824,19 @@ function formatBoardForPrompt(items, template) {
|
|
|
4897
4824
|
}
|
|
4898
4825
|
|
|
4899
4826
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
4900
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4901
|
-
import { join as
|
|
4827
|
+
import { existsSync as existsSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "fs";
|
|
4828
|
+
import { join as join18 } from "path";
|
|
4902
4829
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
4903
4830
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
4904
4831
|
function getKanbanNudgeStateFile(configDir) {
|
|
4905
|
-
return
|
|
4832
|
+
return join18(configDir, CACHE_FILENAME2);
|
|
4906
4833
|
}
|
|
4907
4834
|
function loadKanbanNudgeState(target, configDir) {
|
|
4908
4835
|
const path = getKanbanNudgeStateFile(configDir);
|
|
4909
4836
|
if (!existsSync8(path)) return;
|
|
4910
4837
|
let parsed;
|
|
4911
4838
|
try {
|
|
4912
|
-
parsed = JSON.parse(
|
|
4839
|
+
parsed = JSON.parse(readFileSync15(path, "utf-8"));
|
|
4913
4840
|
} catch {
|
|
4914
4841
|
return;
|
|
4915
4842
|
}
|
|
@@ -4934,7 +4861,7 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
4934
4861
|
const agents = {};
|
|
4935
4862
|
for (const [codeName, state7] of source) agents[codeName] = state7;
|
|
4936
4863
|
try {
|
|
4937
|
-
|
|
4864
|
+
writeFileSync7(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
4938
4865
|
} catch {
|
|
4939
4866
|
}
|
|
4940
4867
|
}
|
|
@@ -5509,9 +5436,9 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
5509
5436
|
|
|
5510
5437
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
5511
5438
|
import { createHash as createHash11 } from "crypto";
|
|
5512
|
-
import { writeFileSync as
|
|
5513
|
-
import { homedir as
|
|
5514
|
-
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";
|
|
5515
5442
|
|
|
5516
5443
|
// src/lib/manager/scheduler/notify.ts
|
|
5517
5444
|
import { createHash as createHash10 } from "crypto";
|
|
@@ -5851,19 +5778,19 @@ function resolveScheduledSlackTarget(task) {
|
|
|
5851
5778
|
}
|
|
5852
5779
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
5853
5780
|
try {
|
|
5854
|
-
const file =
|
|
5781
|
+
const file = join19(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5855
5782
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
5856
5783
|
const tmp = `${file}.tmp`;
|
|
5857
|
-
|
|
5784
|
+
writeFileSync8(tmp, JSON.stringify(marker), "utf8");
|
|
5858
5785
|
renameSync2(tmp, file);
|
|
5859
5786
|
} catch (err) {
|
|
5860
5787
|
log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
|
|
5861
5788
|
}
|
|
5862
5789
|
}
|
|
5863
5790
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
5864
|
-
const file =
|
|
5791
|
+
const file = join19(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5865
5792
|
try {
|
|
5866
|
-
const raw = JSON.parse(
|
|
5793
|
+
const raw = JSON.parse(readFileSync16(file, "utf8"));
|
|
5867
5794
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
5868
5795
|
unlinkSync(file);
|
|
5869
5796
|
log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
|
|
@@ -5917,9 +5844,9 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt, dura
|
|
|
5917
5844
|
return false;
|
|
5918
5845
|
}
|
|
5919
5846
|
try {
|
|
5920
|
-
const doorbell = directChatDoorbellPath(agentId,
|
|
5921
|
-
|
|
5922
|
-
|
|
5847
|
+
const doorbell = directChatDoorbellPath(agentId, homedir8());
|
|
5848
|
+
mkdirSync6(dirname6(doorbell), { recursive: true });
|
|
5849
|
+
writeFileSync8(doorbell, String(Date.now()));
|
|
5923
5850
|
} catch (err) {
|
|
5924
5851
|
log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
5925
5852
|
}
|
|
@@ -6069,10 +5996,99 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
6069
5996
|
|
|
6070
5997
|
// src/lib/manager/scheduler/execution.ts
|
|
6071
5998
|
import { createHash as createHash12 } from "crypto";
|
|
6072
|
-
import { homedir as
|
|
6073
|
-
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
|
|
6074
6090
|
function claudePidFilePath() {
|
|
6075
|
-
return
|
|
6091
|
+
return join21(homedir9(), ".augmented", "manager-claude-pids.json");
|
|
6076
6092
|
}
|
|
6077
6093
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
6078
6094
|
function registerClaudeSpawn(record) {
|
|
@@ -6111,7 +6127,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
6111
6127
|
const state7 = claudeSchedulerStates.get(codeName);
|
|
6112
6128
|
const ready = getReadyTasks(state7, inFlightClaudeTasks);
|
|
6113
6129
|
if (ready.length === 0) return;
|
|
6114
|
-
const limitedUntil =
|
|
6130
|
+
const limitedUntil = readUsageCapUntil({ codeName, projectDir: getProjectDir(codeName) });
|
|
6115
6131
|
if (limitedUntil) {
|
|
6116
6132
|
if (shouldLogUsageCapDeferral("claude-scheduler", codeName, limitedUntil)) {
|
|
6117
6133
|
log(
|
|
@@ -7305,9 +7321,9 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
7305
7321
|
|
|
7306
7322
|
// src/lib/opencode-telegram-ingest.ts
|
|
7307
7323
|
import { createHash as createHash15 } from "crypto";
|
|
7308
|
-
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";
|
|
7309
7325
|
import { randomUUID } from "crypto";
|
|
7310
|
-
import { join as
|
|
7326
|
+
import { join as join22 } from "path";
|
|
7311
7327
|
|
|
7312
7328
|
// src/lib/telegram-ingest.ts
|
|
7313
7329
|
import https2 from "https";
|
|
@@ -7855,7 +7871,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7855
7871
|
let filePath;
|
|
7856
7872
|
try {
|
|
7857
7873
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
7858
|
-
filePath =
|
|
7874
|
+
filePath = join22(dir, "telegram-getupdates-offset-opencode.json");
|
|
7859
7875
|
} catch {
|
|
7860
7876
|
dir = null;
|
|
7861
7877
|
filePath = null;
|
|
@@ -7864,7 +7880,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7864
7880
|
load() {
|
|
7865
7881
|
if (!filePath) return 0;
|
|
7866
7882
|
try {
|
|
7867
|
-
const parsed = JSON.parse(
|
|
7883
|
+
const parsed = JSON.parse(readFileSync18(filePath, "utf-8"));
|
|
7868
7884
|
if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
|
|
7869
7885
|
log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
|
|
7870
7886
|
return 0;
|
|
@@ -7882,8 +7898,8 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7882
7898
|
if (!filePath || !dir) return;
|
|
7883
7899
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
7884
7900
|
try {
|
|
7885
|
-
|
|
7886
|
-
|
|
7901
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
7902
|
+
writeFileSync9(
|
|
7887
7903
|
tmpPath,
|
|
7888
7904
|
JSON.stringify({
|
|
7889
7905
|
offset,
|
|
@@ -8134,15 +8150,15 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
8134
8150
|
}
|
|
8135
8151
|
|
|
8136
8152
|
// src/lib/restart-flags.ts
|
|
8137
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
8138
|
-
import { homedir as
|
|
8139
|
-
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";
|
|
8140
8156
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
8141
8157
|
function restartFlagsDir() {
|
|
8142
|
-
return
|
|
8158
|
+
return join23(homedir10(), ".augmented", "restart-flags");
|
|
8143
8159
|
}
|
|
8144
8160
|
function flagPath(codeName) {
|
|
8145
|
-
return
|
|
8161
|
+
return join23(restartFlagsDir(), `${codeName}.flag`);
|
|
8146
8162
|
}
|
|
8147
8163
|
function readRestartFlags() {
|
|
8148
8164
|
const dir = restartFlagsDir();
|
|
@@ -8151,7 +8167,7 @@ function readRestartFlags() {
|
|
|
8151
8167
|
for (const entry of readdirSync5(dir)) {
|
|
8152
8168
|
if (!entry.endsWith(".flag")) continue;
|
|
8153
8169
|
try {
|
|
8154
|
-
const raw =
|
|
8170
|
+
const raw = readFileSync19(join23(dir, entry), "utf8");
|
|
8155
8171
|
const parsed = JSON.parse(raw);
|
|
8156
8172
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
8157
8173
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -8170,7 +8186,7 @@ function readRestartFlags() {
|
|
|
8170
8186
|
function deleteRestartFlag(codeName) {
|
|
8171
8187
|
const path = flagPath(codeName);
|
|
8172
8188
|
if (existsSync10(path)) {
|
|
8173
|
-
|
|
8189
|
+
rmSync4(path, { force: true });
|
|
8174
8190
|
}
|
|
8175
8191
|
}
|
|
8176
8192
|
|
|
@@ -8269,8 +8285,8 @@ async function sendError(flag, opts, text) {
|
|
|
8269
8285
|
}
|
|
8270
8286
|
|
|
8271
8287
|
// src/lib/restart-context.ts
|
|
8272
|
-
import { readdirSync as readdirSync6, readFileSync as
|
|
8273
|
-
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";
|
|
8274
8290
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
8275
8291
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
8276
8292
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -8282,10 +8298,10 @@ function augmentedAgentDir(codeName) {
|
|
|
8282
8298
|
return dirname7(getProjectDir(codeName));
|
|
8283
8299
|
}
|
|
8284
8300
|
function slackPendingInboundDir(codeName) {
|
|
8285
|
-
return
|
|
8301
|
+
return join24(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
8286
8302
|
}
|
|
8287
8303
|
function slackRestartContextDir(codeName) {
|
|
8288
|
-
return
|
|
8304
|
+
return join24(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
8289
8305
|
}
|
|
8290
8306
|
function sanitizeTopic(raw) {
|
|
8291
8307
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -8327,7 +8343,7 @@ function safeReaddir(dir) {
|
|
|
8327
8343
|
}
|
|
8328
8344
|
function readStrandedMarker(path) {
|
|
8329
8345
|
try {
|
|
8330
|
-
const parsed = JSON.parse(
|
|
8346
|
+
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
8331
8347
|
if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
|
|
8332
8348
|
return { channel: parsed.channel, thread_ts: parsed.thread_ts };
|
|
8333
8349
|
}
|
|
@@ -8336,8 +8352,8 @@ function readStrandedMarker(path) {
|
|
|
8336
8352
|
return null;
|
|
8337
8353
|
}
|
|
8338
8354
|
function writeHintFile(path, dir, hint) {
|
|
8339
|
-
|
|
8340
|
-
|
|
8355
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
8356
|
+
writeFileSync11(path, JSON.stringify(hint), { mode: 384 });
|
|
8341
8357
|
}
|
|
8342
8358
|
function pruneHintsExcept(codeName, freshFilenames) {
|
|
8343
8359
|
const ctxDir = slackRestartContextDir(codeName);
|
|
@@ -8345,7 +8361,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
8345
8361
|
if (!filename.endsWith(".json")) continue;
|
|
8346
8362
|
if (freshFilenames.has(filename)) continue;
|
|
8347
8363
|
try {
|
|
8348
|
-
unlinkSync3(
|
|
8364
|
+
unlinkSync3(join24(ctxDir, filename));
|
|
8349
8365
|
} catch {
|
|
8350
8366
|
}
|
|
8351
8367
|
}
|
|
@@ -8366,7 +8382,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8366
8382
|
}
|
|
8367
8383
|
const markers = [];
|
|
8368
8384
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
8369
|
-
const parsed = readStrandedMarker(
|
|
8385
|
+
const parsed = readStrandedMarker(join24(markerDir, filename));
|
|
8370
8386
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
8371
8387
|
}
|
|
8372
8388
|
if (markers.length === 0) {
|
|
@@ -8380,7 +8396,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8380
8396
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
8381
8397
|
for (const { filename, hint } of hints) {
|
|
8382
8398
|
try {
|
|
8383
|
-
writeHintFile(
|
|
8399
|
+
writeHintFile(join24(ctxDir, filename), ctxDir, hint);
|
|
8384
8400
|
freshFilenames.add(filename);
|
|
8385
8401
|
} catch (err) {
|
|
8386
8402
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -9659,7 +9675,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
9659
9675
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
9660
9676
|
function projectMcpHash(_codeName, projectDir) {
|
|
9661
9677
|
try {
|
|
9662
|
-
const raw =
|
|
9678
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9663
9679
|
return createHash16("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
9664
9680
|
} catch {
|
|
9665
9681
|
return null;
|
|
@@ -9667,7 +9683,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
9667
9683
|
}
|
|
9668
9684
|
function projectMcpKeys(_codeName, projectDir) {
|
|
9669
9685
|
try {
|
|
9670
|
-
const raw =
|
|
9686
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9671
9687
|
const parsed = JSON.parse(raw);
|
|
9672
9688
|
const servers = parsed.mcpServers;
|
|
9673
9689
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -9685,7 +9701,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
9685
9701
|
else runningMcpServerKeys.delete(codeName);
|
|
9686
9702
|
let launchStructure = null;
|
|
9687
9703
|
try {
|
|
9688
|
-
const raw =
|
|
9704
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9689
9705
|
launchStructure = managedMcpStructureHashFromFile(
|
|
9690
9706
|
JSON.parse(raw),
|
|
9691
9707
|
isManagedMcpServerKey
|
|
@@ -9789,7 +9805,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
9789
9805
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
9790
9806
|
let mcpJsonForRebind = null;
|
|
9791
9807
|
try {
|
|
9792
|
-
mcpJsonForRebind = JSON.parse(
|
|
9808
|
+
mcpJsonForRebind = JSON.parse(readFileSync21(join25(projectDir, ".mcp.json"), "utf-8"));
|
|
9793
9809
|
} catch {
|
|
9794
9810
|
mcpJsonForRebind = null;
|
|
9795
9811
|
}
|
|
@@ -9818,7 +9834,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
9818
9834
|
}
|
|
9819
9835
|
return result != null;
|
|
9820
9836
|
}
|
|
9821
|
-
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gateReason = breakerReason, runClose) {
|
|
9837
|
+
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gateReason = breakerReason, runClose, auditDetail) {
|
|
9822
9838
|
const gate = restartGateFor(codeName, gateReason);
|
|
9823
9839
|
if (gate !== "bypass" && gate !== "proceed") {
|
|
9824
9840
|
log(`[maintenance-window] Deferring '${gateReason}' restart for '${codeName}' (${gate})`);
|
|
@@ -9844,7 +9860,10 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gate
|
|
|
9844
9860
|
void api.post("/host/restart-event", {
|
|
9845
9861
|
agent_id: restartAgentId,
|
|
9846
9862
|
source: breakerReason,
|
|
9847
|
-
|
|
9863
|
+
// ENG-8293: fall back to the source string (the pre-ENG-8293 shape)
|
|
9864
|
+
// only when the caller supplied nothing better.
|
|
9865
|
+
reason: auditDetail?.reason ?? breakerReason,
|
|
9866
|
+
...auditDetail?.detail ? { detail: auditDetail.detail } : {}
|
|
9848
9867
|
}).catch((err) => log(`[restart-event] report failed for '${codeName}': ${err.message}`));
|
|
9849
9868
|
}
|
|
9850
9869
|
}
|
|
@@ -9942,7 +9961,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
9942
9961
|
function projectChannelSecretHash(projectDir) {
|
|
9943
9962
|
try {
|
|
9944
9963
|
const entries = parseEnvIntegrations(
|
|
9945
|
-
|
|
9964
|
+
readFileSync21(join25(projectDir, ".env.integrations"), "utf-8")
|
|
9946
9965
|
);
|
|
9947
9966
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
9948
9967
|
} catch {
|
|
@@ -10038,7 +10057,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
10038
10057
|
var lastVersionCheckAt = 0;
|
|
10039
10058
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
10040
10059
|
var lastResponsivenessProbeAt = 0;
|
|
10041
|
-
var agtCliVersion = true ? "0.28.
|
|
10060
|
+
var agtCliVersion = true ? "0.28.475" : "dev";
|
|
10042
10061
|
function resolveBrewPath(execFileSync2) {
|
|
10043
10062
|
try {
|
|
10044
10063
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10327,7 +10346,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
10327
10346
|
try {
|
|
10328
10347
|
let settings = {};
|
|
10329
10348
|
if (existsSync11(path)) {
|
|
10330
|
-
const raw =
|
|
10349
|
+
const raw = readFileSync21(path, "utf-8").trim();
|
|
10331
10350
|
if (raw) {
|
|
10332
10351
|
let parsed;
|
|
10333
10352
|
try {
|
|
@@ -10343,8 +10362,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
10343
10362
|
}
|
|
10344
10363
|
if (settings.channelsEnabled === true) return "ok";
|
|
10345
10364
|
settings.channelsEnabled = true;
|
|
10346
|
-
|
|
10347
|
-
|
|
10365
|
+
mkdirSync10(dirname8(path), { recursive: true });
|
|
10366
|
+
writeFileSync12(path, `${JSON.stringify(settings, null, 2)}
|
|
10348
10367
|
`);
|
|
10349
10368
|
log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
|
|
10350
10369
|
return "ok";
|
|
@@ -10382,7 +10401,7 @@ async function ensureOpencodeBinary() {
|
|
|
10382
10401
|
try {
|
|
10383
10402
|
const prefix = execFileSync2("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
10384
10403
|
if (prefix) {
|
|
10385
|
-
const npmBin =
|
|
10404
|
+
const npmBin = join25(prefix, "bin");
|
|
10386
10405
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
10387
10406
|
if (!current.includes(npmBin)) {
|
|
10388
10407
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -10499,7 +10518,7 @@ ${r.stderr}`;
|
|
|
10499
10518
|
}
|
|
10500
10519
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
10501
10520
|
function selfUpdateAppliedMarkerPath() {
|
|
10502
|
-
return
|
|
10521
|
+
return join25(homedir11(), ".augmented", ".last-self-update-applied");
|
|
10503
10522
|
}
|
|
10504
10523
|
var selfUpdateUpToDateLogged = false;
|
|
10505
10524
|
var selfUpdatePinnedLogged = false;
|
|
@@ -10527,7 +10546,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
10527
10546
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
10528
10547
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
10529
10548
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
10530
|
-
const markerPath =
|
|
10549
|
+
const markerPath = join25(homedir11(), ".augmented", ".last-update-check");
|
|
10531
10550
|
if (!force) {
|
|
10532
10551
|
try {
|
|
10533
10552
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -10887,13 +10906,13 @@ async function checkClaudeAuth() {
|
|
|
10887
10906
|
var evalEmptyMcpConfigPath = null;
|
|
10888
10907
|
function ensureEvalEmptyMcpConfig() {
|
|
10889
10908
|
if (evalEmptyMcpConfigPath && existsSync11(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
10890
|
-
const dir =
|
|
10909
|
+
const dir = join25(homedir11(), ".augmented");
|
|
10891
10910
|
try {
|
|
10892
|
-
|
|
10911
|
+
mkdirSync10(dir, { recursive: true });
|
|
10893
10912
|
} catch {
|
|
10894
10913
|
}
|
|
10895
|
-
const p =
|
|
10896
|
-
|
|
10914
|
+
const p = join25(dir, ".eval-empty-mcp.json");
|
|
10915
|
+
writeFileSync12(p, JSON.stringify({ mcpServers: {} }));
|
|
10897
10916
|
evalEmptyMcpConfigPath = p;
|
|
10898
10917
|
return p;
|
|
10899
10918
|
}
|
|
@@ -10918,7 +10937,7 @@ async function runEvalClaude(prompt, model) {
|
|
|
10918
10937
|
""
|
|
10919
10938
|
];
|
|
10920
10939
|
const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
|
|
10921
|
-
cwd:
|
|
10940
|
+
cwd: homedir11(),
|
|
10922
10941
|
timeout: 12e4,
|
|
10923
10942
|
stdin: "ignore",
|
|
10924
10943
|
env: childEnv,
|
|
@@ -10984,10 +11003,10 @@ function resolveConversationEvalBackend() {
|
|
|
10984
11003
|
return conversationEvalBackend;
|
|
10985
11004
|
}
|
|
10986
11005
|
function getStateFile() {
|
|
10987
|
-
return
|
|
11006
|
+
return join25(config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
10988
11007
|
}
|
|
10989
11008
|
function channelHashCacheDir() {
|
|
10990
|
-
return config?.configDir ??
|
|
11009
|
+
return config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
10991
11010
|
}
|
|
10992
11011
|
function loadChannelHashCache2() {
|
|
10993
11012
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -11041,7 +11060,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
11041
11060
|
var _channelQuarantineStore = null;
|
|
11042
11061
|
function channelQuarantineStore() {
|
|
11043
11062
|
if (!_channelQuarantineStore) {
|
|
11044
|
-
const dir = config?.configDir ??
|
|
11063
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
11045
11064
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
11046
11065
|
}
|
|
11047
11066
|
return _channelQuarantineStore;
|
|
@@ -11058,7 +11077,7 @@ function claudeMdSizeFor(codeName) {
|
|
|
11058
11077
|
var _hostFlagStore = null;
|
|
11059
11078
|
function hostFlagStore() {
|
|
11060
11079
|
if (!_hostFlagStore) {
|
|
11061
|
-
const dir = config?.configDir ??
|
|
11080
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
11062
11081
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
11063
11082
|
}
|
|
11064
11083
|
return _hostFlagStore;
|
|
@@ -11128,13 +11147,13 @@ function parseSkillFrontmatter(content) {
|
|
|
11128
11147
|
return out;
|
|
11129
11148
|
}
|
|
11130
11149
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
11131
|
-
const { readdirSync: readdirSync8, readFileSync: rfs, existsSync: ex, writeFileSync:
|
|
11132
|
-
const skillsDir =
|
|
11133
|
-
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");
|
|
11134
11153
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
11135
11154
|
const entries = [];
|
|
11136
11155
|
for (const dir of readdirSync8(skillsDir).sort()) {
|
|
11137
|
-
const skillFile =
|
|
11156
|
+
const skillFile = join25(skillsDir, dir, "SKILL.md");
|
|
11138
11157
|
if (!ex(skillFile)) continue;
|
|
11139
11158
|
try {
|
|
11140
11159
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -11178,7 +11197,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
11178
11197
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
11179
11198
|
}
|
|
11180
11199
|
if (next !== current) {
|
|
11181
|
-
|
|
11200
|
+
writeFileSync13(claudeMdPath, next, "utf-8");
|
|
11182
11201
|
log2(
|
|
11183
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)`
|
|
11184
11203
|
);
|
|
@@ -11201,7 +11220,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
11201
11220
|
if (codeNames.length === 0) return;
|
|
11202
11221
|
void (async () => {
|
|
11203
11222
|
try {
|
|
11204
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11223
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
11205
11224
|
await api.post("/host/heartbeat", {
|
|
11206
11225
|
host_id: hostId,
|
|
11207
11226
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -11308,7 +11327,7 @@ async function pollCycle() {
|
|
|
11308
11327
|
}
|
|
11309
11328
|
try {
|
|
11310
11329
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
11311
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11330
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
11312
11331
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
11313
11332
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
|
|
11314
11333
|
let tailscaleHostname;
|
|
@@ -11422,7 +11441,7 @@ async function pollCycle() {
|
|
|
11422
11441
|
collectResponsivenessProbes,
|
|
11423
11442
|
collectPanelessActivityProbes,
|
|
11424
11443
|
getResponsivenessIntervalMs
|
|
11425
|
-
} = await import("../responsiveness-probe-
|
|
11444
|
+
} = await import("../responsiveness-probe-5AG6X2BN.js");
|
|
11426
11445
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
11427
11446
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
11428
11447
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -11486,7 +11505,7 @@ async function pollCycle() {
|
|
|
11486
11505
|
collectResponsivenessProbes,
|
|
11487
11506
|
livePendingInboundOldestAgeSeconds,
|
|
11488
11507
|
parkPendingInbound
|
|
11489
|
-
} = await import("../responsiveness-probe-
|
|
11508
|
+
} = await import("../responsiveness-probe-5AG6X2BN.js");
|
|
11490
11509
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
11491
11510
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
11492
11511
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11575,13 +11594,13 @@ async function pollCycle() {
|
|
|
11575
11594
|
);
|
|
11576
11595
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
11577
11596
|
try {
|
|
11578
|
-
const paneTail =
|
|
11597
|
+
const paneTail = readFileSync21(paneLogPath(codeName), "utf8").slice(-65536);
|
|
11579
11598
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
11580
11599
|
if (transient) {
|
|
11581
|
-
const wedgeHome =
|
|
11600
|
+
const wedgeHome = join25(homedir11(), ".augmented", codeName);
|
|
11582
11601
|
if (existsSync11(wedgeHome)) {
|
|
11583
11602
|
atomicWriteFileSync(
|
|
11584
|
-
|
|
11603
|
+
join25(wedgeHome, "watchdog-give-up.json"),
|
|
11585
11604
|
JSON.stringify({
|
|
11586
11605
|
gave_up_at: wedgeNow.toISOString(),
|
|
11587
11606
|
reason: "transient_overload"
|
|
@@ -11852,8 +11871,8 @@ async function pollCycle() {
|
|
|
11852
11871
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
11853
11872
|
stopAgentRuntime2(prev.codeName, "removed-from-host");
|
|
11854
11873
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
11855
|
-
const
|
|
11856
|
-
await cleanupAgentFiles(prev.codeName,
|
|
11874
|
+
const agentDir = join25(adapter.getAgentDir(prev.codeName), "provision");
|
|
11875
|
+
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
11857
11876
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
11858
11877
|
}
|
|
11859
11878
|
}
|
|
@@ -11939,10 +11958,10 @@ async function pollCycle() {
|
|
|
11939
11958
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
11940
11959
|
// the watchdog, never fails the poll cycle.
|
|
11941
11960
|
signalGiveUp: (codeName) => {
|
|
11942
|
-
const dir =
|
|
11961
|
+
const dir = join25(homedir11(), ".augmented", codeName);
|
|
11943
11962
|
if (!existsSync11(dir)) return;
|
|
11944
11963
|
atomicWriteFileSync(
|
|
11945
|
-
|
|
11964
|
+
join25(dir, "watchdog-give-up.json"),
|
|
11946
11965
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
11947
11966
|
);
|
|
11948
11967
|
}
|
|
@@ -12084,7 +12103,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12084
12103
|
}
|
|
12085
12104
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12086
12105
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
12087
|
-
let
|
|
12106
|
+
let agentDir = join25(adapter.getAgentDir(agent.code_name), "provision");
|
|
12088
12107
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
12089
12108
|
if (previousKnownStatus !== agent.status) {
|
|
12090
12109
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -12124,7 +12143,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12124
12143
|
const residuals = {
|
|
12125
12144
|
gatewayRunning: false,
|
|
12126
12145
|
portAllocated: false,
|
|
12127
|
-
provisionDirExists: existsSync11(
|
|
12146
|
+
provisionDirExists: existsSync11(agentDir)
|
|
12128
12147
|
};
|
|
12129
12148
|
if (!hasRevokedResiduals(residuals)) {
|
|
12130
12149
|
agentStates.push({
|
|
@@ -12149,7 +12168,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12149
12168
|
log(`Agent '${agent.code_name}' is revoked, cleaning up`);
|
|
12150
12169
|
stopAgentRuntime2(agent.code_name, "revoked");
|
|
12151
12170
|
killAgentChannelProcesses(agent.code_name, { log });
|
|
12152
|
-
await cleanupAgentFiles(agent.code_name,
|
|
12171
|
+
await cleanupAgentFiles(agent.code_name, agentDir);
|
|
12153
12172
|
clearAgentCaches(agent.agent_id, agent.code_name);
|
|
12154
12173
|
agentState.knownStatuses.set(agent.agent_id, agent.status);
|
|
12155
12174
|
agentStates.push({
|
|
@@ -12258,7 +12277,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12258
12277
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
12259
12278
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
12260
12279
|
const frameworkAdapter = getFramework(frameworkId);
|
|
12261
|
-
|
|
12280
|
+
agentDir = join25(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
12262
12281
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
12263
12282
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
12264
12283
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -12305,9 +12324,9 @@ async function processAgent(agent, agentStates) {
|
|
|
12305
12324
|
try {
|
|
12306
12325
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter, renderIntegrationsSection);
|
|
12307
12326
|
const changedFiles = [];
|
|
12308
|
-
|
|
12327
|
+
mkdirSync10(agentDir, { recursive: true });
|
|
12309
12328
|
for (const artifact of artifacts) {
|
|
12310
|
-
const filePath =
|
|
12329
|
+
const filePath = join25(agentDir, artifact.relativePath);
|
|
12311
12330
|
let existingHash;
|
|
12312
12331
|
let newHash;
|
|
12313
12332
|
let writeContent = artifact.content;
|
|
@@ -12326,8 +12345,8 @@ async function processAgent(agent, agentStates) {
|
|
|
12326
12345
|
};
|
|
12327
12346
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
12328
12347
|
try {
|
|
12329
|
-
const projectClaudeMd =
|
|
12330
|
-
const existing =
|
|
12348
|
+
const projectClaudeMd = join25(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
12349
|
+
const existing = readFileSync21(projectClaudeMd, "utf-8");
|
|
12331
12350
|
existingHash = sha256(stripDynamicSections(existing));
|
|
12332
12351
|
} catch {
|
|
12333
12352
|
existingHash = null;
|
|
@@ -12345,7 +12364,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12345
12364
|
const generatorKeys = Object.keys(generatorServers);
|
|
12346
12365
|
let existingRaw = "";
|
|
12347
12366
|
try {
|
|
12348
|
-
existingRaw =
|
|
12367
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
12349
12368
|
} catch {
|
|
12350
12369
|
}
|
|
12351
12370
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -12361,7 +12380,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12361
12380
|
} else if (artifact.relativePath === "opencode.json") {
|
|
12362
12381
|
let existingRaw = null;
|
|
12363
12382
|
try {
|
|
12364
|
-
existingRaw =
|
|
12383
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
12365
12384
|
} catch {
|
|
12366
12385
|
}
|
|
12367
12386
|
const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
|
|
@@ -12377,26 +12396,26 @@ async function processAgent(agent, agentStates) {
|
|
|
12377
12396
|
}
|
|
12378
12397
|
}
|
|
12379
12398
|
if (changedFiles.length > 0) {
|
|
12380
|
-
const isFirst = !existsSync11(
|
|
12399
|
+
const isFirst = !existsSync11(join25(agentDir, "CHARTER.md"));
|
|
12381
12400
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
12382
12401
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
12383
12402
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
12384
12403
|
for (const file of changedFiles) {
|
|
12385
|
-
const filePath =
|
|
12386
|
-
|
|
12404
|
+
const filePath = join25(agentDir, file.relativePath);
|
|
12405
|
+
mkdirSync10(dirname8(filePath), { recursive: true });
|
|
12387
12406
|
if (file.relativePath === ".mcp.json") {
|
|
12388
12407
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
12389
12408
|
} else {
|
|
12390
|
-
|
|
12409
|
+
writeFileSync12(filePath, file.content);
|
|
12391
12410
|
}
|
|
12392
12411
|
}
|
|
12393
12412
|
try {
|
|
12394
|
-
const provSkillsDir =
|
|
12413
|
+
const provSkillsDir = join25(agentDir, ".claude", "skills");
|
|
12395
12414
|
if (existsSync11(provSkillsDir)) {
|
|
12396
12415
|
for (const folder of readdirSync7(provSkillsDir)) {
|
|
12397
12416
|
if (folder.startsWith("knowledge-")) {
|
|
12398
12417
|
try {
|
|
12399
|
-
|
|
12418
|
+
rmSync5(join25(provSkillsDir, folder), { recursive: true });
|
|
12400
12419
|
} catch {
|
|
12401
12420
|
}
|
|
12402
12421
|
}
|
|
@@ -12409,7 +12428,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12409
12428
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
12410
12429
|
const hashes = /* @__PURE__ */ new Map();
|
|
12411
12430
|
for (const file of trackedFiles2) {
|
|
12412
|
-
const h = hashFile(
|
|
12431
|
+
const h = hashFile(join25(agentDir, file));
|
|
12413
12432
|
if (h) hashes.set(file, h);
|
|
12414
12433
|
}
|
|
12415
12434
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -12417,7 +12436,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12417
12436
|
const primaryModel2 = resolvedModelsForRegistration.primary ?? refreshData.agent.primary_model;
|
|
12418
12437
|
const registeredAgents = await getOrCacheRegisteredAgents(frameworkAdapter, agent.code_name);
|
|
12419
12438
|
if (!registeredAgents.has(agent.code_name)) {
|
|
12420
|
-
const registered = await frameworkAdapter.registerAgent(agent.code_name,
|
|
12439
|
+
const registered = await frameworkAdapter.registerAgent(agent.code_name, agentDir, primaryModel2, agent.agent_id);
|
|
12421
12440
|
if (registered) {
|
|
12422
12441
|
registeredAgents.add(agent.code_name);
|
|
12423
12442
|
log(`Registered '${agent.code_name}' in ${frameworkAdapter.label}`);
|
|
@@ -12427,14 +12446,14 @@ async function processAgent(agent, agentStates) {
|
|
|
12427
12446
|
}
|
|
12428
12447
|
if (Array.isArray(refreshData.workflows)) {
|
|
12429
12448
|
try {
|
|
12430
|
-
const provWorkflowsDir =
|
|
12449
|
+
const provWorkflowsDir = join25(agentDir, ".claude", "workflows");
|
|
12431
12450
|
if (existsSync11(provWorkflowsDir)) {
|
|
12432
12451
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
12433
12452
|
for (const file of readdirSync7(provWorkflowsDir)) {
|
|
12434
12453
|
if (!file.endsWith(".js")) continue;
|
|
12435
12454
|
if (expected.has(file)) continue;
|
|
12436
12455
|
try {
|
|
12437
|
-
|
|
12456
|
+
rmSync5(join25(provWorkflowsDir, file));
|
|
12438
12457
|
} catch {
|
|
12439
12458
|
}
|
|
12440
12459
|
}
|
|
@@ -12443,7 +12462,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12443
12462
|
}
|
|
12444
12463
|
}
|
|
12445
12464
|
if (frameworkAdapter.deployArtifactsToProject) {
|
|
12446
|
-
frameworkAdapter.deployArtifactsToProject(agent.code_name,
|
|
12465
|
+
frameworkAdapter.deployArtifactsToProject(agent.code_name, agentDir);
|
|
12447
12466
|
}
|
|
12448
12467
|
} catch (err) {
|
|
12449
12468
|
log(`Provision failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -12513,10 +12532,10 @@ async function processAgent(agent, agentStates) {
|
|
|
12513
12532
|
}
|
|
12514
12533
|
let lastDriftCheckAt = now;
|
|
12515
12534
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
12516
|
-
if (written && existsSync11(
|
|
12535
|
+
if (written && existsSync11(agentDir)) {
|
|
12517
12536
|
const driftedFiles = [];
|
|
12518
12537
|
for (const [file, expectedHash] of written) {
|
|
12519
|
-
const localHash = hashFile(
|
|
12538
|
+
const localHash = hashFile(join25(agentDir, file));
|
|
12520
12539
|
if (localHash && localHash !== expectedHash) {
|
|
12521
12540
|
driftedFiles.push(file);
|
|
12522
12541
|
}
|
|
@@ -12527,7 +12546,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12527
12546
|
try {
|
|
12528
12547
|
const localHashes = {};
|
|
12529
12548
|
for (const file of driftedFiles) {
|
|
12530
|
-
localHashes[file] = hashFile(
|
|
12549
|
+
localHashes[file] = hashFile(join25(agentDir, file));
|
|
12531
12550
|
}
|
|
12532
12551
|
await api.post("/host/drift", {
|
|
12533
12552
|
agent_id: agent.agent_id,
|
|
@@ -12729,15 +12748,15 @@ async function processAgent(agent, agentStates) {
|
|
|
12729
12748
|
const addedChannels = [...restartDecision.added];
|
|
12730
12749
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
12731
12750
|
try {
|
|
12732
|
-
const agentAugmentedDir =
|
|
12733
|
-
|
|
12751
|
+
const agentAugmentedDir = join25(homedir11(), ".augmented", agent.code_name);
|
|
12752
|
+
mkdirSync10(agentAugmentedDir, { recursive: true });
|
|
12734
12753
|
const markerJson = JSON.stringify({
|
|
12735
12754
|
version: 1,
|
|
12736
12755
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12737
12756
|
added: addedChannels
|
|
12738
12757
|
});
|
|
12739
12758
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
12740
|
-
atomicWriteFileSync(
|
|
12759
|
+
atomicWriteFileSync(join25(agentAugmentedDir, file), markerJson);
|
|
12741
12760
|
}
|
|
12742
12761
|
} catch (err) {
|
|
12743
12762
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -12925,19 +12944,19 @@ async function processAgent(agent, agentStates) {
|
|
|
12925
12944
|
const agentSessionMode = refreshData.agent.session_mode;
|
|
12926
12945
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
12927
12946
|
try {
|
|
12928
|
-
const agentProvisionDir =
|
|
12929
|
-
const projectDir =
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
const provisionMcpPath =
|
|
12933
|
-
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");
|
|
12934
12953
|
let mcpConfig = { mcpServers: {} };
|
|
12935
12954
|
try {
|
|
12936
|
-
mcpConfig = JSON.parse(
|
|
12955
|
+
mcpConfig = JSON.parse(readFileSync21(provisionMcpPath, "utf-8"));
|
|
12937
12956
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
12938
12957
|
} catch {
|
|
12939
12958
|
}
|
|
12940
|
-
const localDirectChatChannel =
|
|
12959
|
+
const localDirectChatChannel = join25(homedir11(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
12941
12960
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
12942
12961
|
const directChatTz = (() => {
|
|
12943
12962
|
const tz = directChatTeamSettings?.["timezone"];
|
|
@@ -12963,7 +12982,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12963
12982
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
12964
12983
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
12965
12984
|
// so it byte-matches the broker readers' path.
|
|
12966
|
-
AGT_TURN_INITIATOR_FILE:
|
|
12985
|
+
AGT_TURN_INITIATOR_FILE: join25(
|
|
12967
12986
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
12968
12987
|
".current-turn-initiator.json"
|
|
12969
12988
|
)
|
|
@@ -12983,10 +13002,10 @@ async function processAgent(agent, agentStates) {
|
|
|
12983
13002
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
12984
13003
|
}
|
|
12985
13004
|
}
|
|
12986
|
-
const staleChannelsPath =
|
|
13005
|
+
const staleChannelsPath = join25(projectDir, ".mcp-channels.json");
|
|
12987
13006
|
if (existsSync11(staleChannelsPath)) {
|
|
12988
13007
|
try {
|
|
12989
|
-
|
|
13008
|
+
rmSync5(staleChannelsPath, { force: true });
|
|
12990
13009
|
} catch {
|
|
12991
13010
|
}
|
|
12992
13011
|
}
|
|
@@ -13073,7 +13092,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13073
13092
|
}
|
|
13074
13093
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
13075
13094
|
try {
|
|
13076
|
-
const probeProjectDir =
|
|
13095
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13077
13096
|
let probeSet = integrations;
|
|
13078
13097
|
try {
|
|
13079
13098
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -13119,7 +13138,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13119
13138
|
const forceDue = attemptsLeft > 0;
|
|
13120
13139
|
let probeRan = false;
|
|
13121
13140
|
try {
|
|
13122
|
-
const probeProjectDir =
|
|
13141
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13123
13142
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
13124
13143
|
} catch (err) {
|
|
13125
13144
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -13196,11 +13215,11 @@ async function processAgent(agent, agentStates) {
|
|
|
13196
13215
|
const intHash = computeIntegrationsHash(integrations);
|
|
13197
13216
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
13198
13217
|
if (intHash !== prevIntHash) {
|
|
13199
|
-
const projectDir =
|
|
13200
|
-
const envIntPath =
|
|
13218
|
+
const projectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
13219
|
+
const envIntPath = join25(projectDir, ".env.integrations");
|
|
13201
13220
|
let preWriteEnv;
|
|
13202
13221
|
try {
|
|
13203
|
-
preWriteEnv =
|
|
13222
|
+
preWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
13204
13223
|
} catch {
|
|
13205
13224
|
preWriteEnv = void 0;
|
|
13206
13225
|
}
|
|
@@ -13219,9 +13238,9 @@ async function processAgent(agent, agentStates) {
|
|
|
13219
13238
|
}
|
|
13220
13239
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
13221
13240
|
try {
|
|
13222
|
-
const projectMcpPath =
|
|
13223
|
-
const postWriteEnv =
|
|
13224
|
-
const mcpContent =
|
|
13241
|
+
const projectMcpPath = join25(projectDir, ".mcp.json");
|
|
13242
|
+
const postWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
13243
|
+
const mcpContent = readFileSync21(projectMcpPath, "utf-8");
|
|
13225
13244
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
13226
13245
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
13227
13246
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -13467,17 +13486,17 @@ async function processAgent(agent, agentStates) {
|
|
|
13467
13486
|
}
|
|
13468
13487
|
}
|
|
13469
13488
|
try {
|
|
13470
|
-
const { readdirSync: readdirSync8, rmSync:
|
|
13471
|
-
const { homedir:
|
|
13489
|
+
const { readdirSync: readdirSync8, rmSync: rmSync6 } = await import("fs");
|
|
13490
|
+
const { homedir: homedir12 } = await import("os");
|
|
13472
13491
|
const frameworkId2 = frameworkAdapter.id;
|
|
13473
13492
|
const candidateSkillDirs = [
|
|
13474
13493
|
// Claude Code — framework runtime tree
|
|
13475
|
-
|
|
13494
|
+
join25(homedir12(), ".augmented", agent.code_name, "skills"),
|
|
13476
13495
|
// Claude Code — project tree
|
|
13477
|
-
|
|
13496
|
+
join25(homedir12(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13478
13497
|
// Defensive: legacy provision-side path, not currently an
|
|
13479
13498
|
// install target but cheap to sweep.
|
|
13480
|
-
|
|
13499
|
+
join25(agentDir, ".claude", "skills")
|
|
13481
13500
|
];
|
|
13482
13501
|
const existingDirs = candidateSkillDirs.filter((d) => existsSync11(d));
|
|
13483
13502
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
@@ -13493,9 +13512,9 @@ async function processAgent(agent, agentStates) {
|
|
|
13493
13512
|
}
|
|
13494
13513
|
const removeSkillFolder = (entry, reason) => {
|
|
13495
13514
|
for (const dir of existingDirs) {
|
|
13496
|
-
const p =
|
|
13515
|
+
const p = join25(dir, entry);
|
|
13497
13516
|
if (existsSync11(p)) {
|
|
13498
|
-
|
|
13517
|
+
rmSync6(p, { recursive: true, force: true });
|
|
13499
13518
|
}
|
|
13500
13519
|
}
|
|
13501
13520
|
log(`Removed ${reason} '${entry}' for '${agent.code_name}' (framework=${frameworkId2})`);
|
|
@@ -13513,7 +13532,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13513
13532
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
13514
13533
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
13515
13534
|
const manifestPath = managedSkillManifestPath(
|
|
13516
|
-
|
|
13535
|
+
join25(homedir11(), ".augmented", agent.code_name)
|
|
13517
13536
|
);
|
|
13518
13537
|
const prevIds = /* @__PURE__ */ new Set([
|
|
13519
13538
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -13533,16 +13552,16 @@ async function processAgent(agent, agentStates) {
|
|
|
13533
13552
|
}
|
|
13534
13553
|
if (plan.removes.length) {
|
|
13535
13554
|
const globalSkillDirs = [
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
|
|
13555
|
+
join25(homedir11(), ".augmented", agent.code_name, "skills"),
|
|
13556
|
+
join25(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13557
|
+
join25(agentDir, ".claude", "skills")
|
|
13539
13558
|
];
|
|
13540
13559
|
for (const id of plan.removes) {
|
|
13541
13560
|
let prunedAny = false;
|
|
13542
13561
|
for (const dir of globalSkillDirs) {
|
|
13543
|
-
const p =
|
|
13544
|
-
if (existsSync11(p) && existsSync11(
|
|
13545
|
-
|
|
13562
|
+
const p = join25(dir, id);
|
|
13563
|
+
if (existsSync11(p) && existsSync11(join25(p, "SKILL.md"))) {
|
|
13564
|
+
rmSync5(p, { recursive: true, force: true });
|
|
13546
13565
|
prunedAny = true;
|
|
13547
13566
|
}
|
|
13548
13567
|
}
|
|
@@ -13689,7 +13708,10 @@ async function processAgent(agent, agentStates) {
|
|
|
13689
13708
|
);
|
|
13690
13709
|
}
|
|
13691
13710
|
} else if (nudgeAction === "nudge") {
|
|
13692
|
-
const tickLimitedUntil =
|
|
13711
|
+
const tickLimitedUntil = readUsageCapUntil({
|
|
13712
|
+
codeName: agent.code_name,
|
|
13713
|
+
projectDir: getProjectDir(agent.code_name)
|
|
13714
|
+
});
|
|
13693
13715
|
if (tickLimitedUntil) {
|
|
13694
13716
|
if (shouldLogUsageCapDeferral("kanban-tick", agent.code_name, tickLimitedUntil)) {
|
|
13695
13717
|
log(
|
|
@@ -13769,8 +13791,8 @@ async function processAgent(agent, agentStates) {
|
|
|
13769
13791
|
const sess = getSessionState(agent.code_name);
|
|
13770
13792
|
let mcpJsonParsed = null;
|
|
13771
13793
|
try {
|
|
13772
|
-
const mcpPath =
|
|
13773
|
-
mcpJsonParsed = JSON.parse(
|
|
13794
|
+
const mcpPath = join25(getProjectDir(agent.code_name), ".mcp.json");
|
|
13795
|
+
mcpJsonParsed = JSON.parse(readFileSync21(mcpPath, "utf-8"));
|
|
13774
13796
|
} catch {
|
|
13775
13797
|
}
|
|
13776
13798
|
reapMissingMcpSessions({
|
|
@@ -14193,10 +14215,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
14193
14215
|
}
|
|
14194
14216
|
}
|
|
14195
14217
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
14196
|
-
if (trackedFiles.length > 0 && existsSync11(
|
|
14218
|
+
if (trackedFiles.length > 0 && existsSync11(agentDir)) {
|
|
14197
14219
|
const hashes = /* @__PURE__ */ new Map();
|
|
14198
14220
|
for (const file of trackedFiles) {
|
|
14199
|
-
const h = hashFile(
|
|
14221
|
+
const h = hashFile(join25(agentDir, file));
|
|
14200
14222
|
if (h) hashes.set(file, h);
|
|
14201
14223
|
}
|
|
14202
14224
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -14211,7 +14233,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
14211
14233
|
refreshData.agent.onboarding_state
|
|
14212
14234
|
);
|
|
14213
14235
|
const obStep = obState.step;
|
|
14214
|
-
const markerPath =
|
|
14236
|
+
const markerPath = join25(homedir11(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
14215
14237
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
14216
14238
|
const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
|
|
14217
14239
|
if (decision.clearMarker) {
|
|
@@ -14265,20 +14287,6 @@ var lastModelApiErrorSig = /* @__PURE__ */ new Map();
|
|
|
14265
14287
|
var DAY_ROLLOVER_FORCE_GRACE_MIN = 30;
|
|
14266
14288
|
var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
|
|
14267
14289
|
var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
14268
|
-
var claudeAccountByAgent = /* @__PURE__ */ new Map();
|
|
14269
|
-
function _resetClaudeAccountByAgent() {
|
|
14270
|
-
claudeAccountByAgent.clear();
|
|
14271
|
-
}
|
|
14272
|
-
function clearUsageLimitMarkerOnAccountChange(codeName, fingerprint3, log2) {
|
|
14273
|
-
if (!fingerprint3) return;
|
|
14274
|
-
const previous = claudeAccountByAgent.get(codeName);
|
|
14275
|
-
claudeAccountByAgent.set(codeName, fingerprint3);
|
|
14276
|
-
if (previous === void 0 || previous === fingerprint3) return;
|
|
14277
|
-
log2(
|
|
14278
|
-
`[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)`
|
|
14279
|
-
);
|
|
14280
|
-
clearUsageLimitMarker(codeName, log2);
|
|
14281
|
-
}
|
|
14282
14290
|
var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
|
|
14283
14291
|
var egressAllowlistBySession = /* @__PURE__ */ new Map();
|
|
14284
14292
|
function deriveEgressAllowlist(toolsRaw) {
|
|
@@ -14313,7 +14321,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
14313
14321
|
}
|
|
14314
14322
|
stopOpencodeSlackIngest(codeName, log);
|
|
14315
14323
|
stopOpencodeTelegramIngest(codeName, log);
|
|
14316
|
-
const opencodeProjectDir =
|
|
14324
|
+
const opencodeProjectDir = join25(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
14317
14325
|
const serveEnv = {
|
|
14318
14326
|
AGT_HOST: requireHost(),
|
|
14319
14327
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -14356,8 +14364,8 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
14356
14364
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
14357
14365
|
const codeName = agent.code_name;
|
|
14358
14366
|
const projectDir = getProjectDir(codeName);
|
|
14359
|
-
const mcpConfigPath =
|
|
14360
|
-
const claudeMdPath =
|
|
14367
|
+
const mcpConfigPath = join25(projectDir, ".mcp.json");
|
|
14368
|
+
const claudeMdPath = join25(projectDir, "CLAUDE.md");
|
|
14361
14369
|
if (restartBreaker.isTripped(codeName)) {
|
|
14362
14370
|
const trip = restartBreaker.getTrip(codeName);
|
|
14363
14371
|
return {
|
|
@@ -14496,12 +14504,24 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
14496
14504
|
let dayRolloverDeferred = false;
|
|
14497
14505
|
let dayRolloverForced = false;
|
|
14498
14506
|
const claudeAccountFingerprint = !openRouterForAgent && claudeAuthMode === "subscription" ? await getClaudeAccountFingerprint() : null;
|
|
14499
|
-
|
|
14507
|
+
noteClaudeAccountChange(codeName, claudeAccountFingerprint, log);
|
|
14500
14508
|
const currentAuthTuple = openRouterForAgent ? `openrouter:${openRouterForAgent.fingerprint ?? openRouterForAgent.model}` : `${claudeAuthMode}:${anthropicApiKeyFingerprint ?? "none"}${claudeAccountFingerprint ? `:${claudeAccountFingerprint}` : ""}`;
|
|
14501
14509
|
const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
|
|
14502
14510
|
if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
|
|
14503
|
-
|
|
14504
|
-
|
|
14511
|
+
const authTupleDiff = diffAuthTuples(recordedAuthTuple, currentAuthTuple);
|
|
14512
|
+
log(
|
|
14513
|
+
`[persistent-session] Auth config changed for '${codeName}' (${recordedAuthTuple} \u2192 ${currentAuthTuple}) \u2014 ${authTupleDiff.summary} \u2014 restarting session`
|
|
14514
|
+
);
|
|
14515
|
+
stopPersistentSessionAndForgetMcpBaseline(codeName, "auth-tuple-change", void 0, void 0, {
|
|
14516
|
+
reason: authTupleDiff.summary,
|
|
14517
|
+
detail: {
|
|
14518
|
+
auth_tuple: {
|
|
14519
|
+
changed: authTupleDiff.changed,
|
|
14520
|
+
unchanged: authTupleDiff.unchanged,
|
|
14521
|
+
components: authTupleDiff.components
|
|
14522
|
+
}
|
|
14523
|
+
}
|
|
14524
|
+
});
|
|
14505
14525
|
agentState.persistentSessionAgents.delete(codeName);
|
|
14506
14526
|
restartTrigger = "auth-tuple";
|
|
14507
14527
|
}
|
|
@@ -14668,22 +14688,11 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
|
|
|
14668
14688
|
// host. An agent with no per-agent override inherits the host-wide value;
|
|
14669
14689
|
// the launcher still lets an operator AGT_NOTIFY_DISPATCH env override win.
|
|
14670
14690
|
notifyDispatchMode: hostFlagStore().getStringForAgent("notify-dispatch", agent.agent_id),
|
|
14671
|
-
// ENG-8201: materialize usage-limit-reactive-notice into the spawn env
|
|
14672
|
-
// (AGT_USAGE_LIMIT_REACTIVE_MODE) so the channel MCPs report a usage cap
|
|
14673
|
-
// reactively instead of refusing to dispatch on a prediction. Resolved
|
|
14674
|
-
// PER-AGENT so the rollout can start with one agent rather than a whole
|
|
14675
|
-
// host, and materialized (not just left to the flags-cache) because an
|
|
14676
|
-
// isolated agent's container never mounts that cache — without this the
|
|
14677
|
-
// flip reaches nothing running under Docker isolation.
|
|
14678
|
-
usageLimitReactiveMode: hostFlagStore().getStringForAgent(
|
|
14679
|
-
"usage-limit-reactive-notice",
|
|
14680
|
-
agent.agent_id
|
|
14681
|
-
),
|
|
14682
14691
|
// ENG-8269: materialize wedge-transient-notice into the spawn env so the
|
|
14683
14692
|
// channel MCPs can tell a waiting user their turn died on a transient
|
|
14684
|
-
// provider failure.
|
|
14685
|
-
//
|
|
14686
|
-
// 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.
|
|
14687
14696
|
turnFailureNoticeEnabled: hostFlagStore().getBoolean("wedge-transient-notice"),
|
|
14688
14697
|
egressAllowlist,
|
|
14689
14698
|
log
|
|
@@ -14748,7 +14757,10 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
|
|
|
14748
14757
|
}
|
|
14749
14758
|
let deferReadyForUsageCap = false;
|
|
14750
14759
|
if (ready.length > 0) {
|
|
14751
|
-
const schedLimitedUntil =
|
|
14760
|
+
const schedLimitedUntil = readUsageCapUntil({
|
|
14761
|
+
codeName,
|
|
14762
|
+
projectDir: getProjectDir(codeName)
|
|
14763
|
+
});
|
|
14752
14764
|
if (schedLimitedUntil) {
|
|
14753
14765
|
if (shouldLogUsageCapDeferral("persistent-scheduler", codeName, schedLimitedUntil)) {
|
|
14754
14766
|
log(
|
|
@@ -14969,7 +14981,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
14969
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}`));
|
|
14970
14982
|
void (async () => {
|
|
14971
14983
|
try {
|
|
14972
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14984
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
14973
14985
|
await api.post("/host/heartbeat", {
|
|
14974
14986
|
host_id: hostId,
|
|
14975
14987
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -15019,7 +15031,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
15019
15031
|
}
|
|
15020
15032
|
try {
|
|
15021
15033
|
const hostId = await getHostId();
|
|
15022
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
15034
|
+
const { collectDiagnostics } = await import("../persistent-session-BBWEPY24.js");
|
|
15023
15035
|
await api.post("/host/heartbeat", {
|
|
15024
15036
|
host_id: hostId,
|
|
15025
15037
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -15309,9 +15321,9 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
15309
15321
|
const useDoorbell = hostFlagStore().getBoolean("direct-chat-doorbell") || isolationMode(agent.codeName) === "docker";
|
|
15310
15322
|
if (useDoorbell) {
|
|
15311
15323
|
try {
|
|
15312
|
-
const doorbell = directChatDoorbellPath(agent.agentId,
|
|
15313
|
-
|
|
15314
|
-
|
|
15324
|
+
const doorbell = directChatDoorbellPath(agent.agentId, homedir11());
|
|
15325
|
+
mkdirSync10(dirname8(doorbell), { recursive: true });
|
|
15326
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
15315
15327
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
15316
15328
|
return;
|
|
15317
15329
|
} catch (err) {
|
|
@@ -15419,9 +15431,9 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
15419
15431
|
}
|
|
15420
15432
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
15421
15433
|
try {
|
|
15422
|
-
const doorbell = directChatDoorbellPath(agentId,
|
|
15423
|
-
|
|
15424
|
-
|
|
15434
|
+
const doorbell = directChatDoorbellPath(agentId, homedir11());
|
|
15435
|
+
mkdirSync10(dirname8(doorbell), { recursive: true });
|
|
15436
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
15425
15437
|
} catch (err) {
|
|
15426
15438
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
15427
15439
|
}
|
|
@@ -15477,7 +15489,7 @@ async function processClaudePairSessions(agents) {
|
|
|
15477
15489
|
killPairSession,
|
|
15478
15490
|
pairTmuxSession,
|
|
15479
15491
|
finalizeClaudePairOnboarding
|
|
15480
|
-
} = await import("../claude-pair-runtime-
|
|
15492
|
+
} = await import("../claude-pair-runtime-IIQ6O7QX.js");
|
|
15481
15493
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
15482
15494
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
15483
15495
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -15731,8 +15743,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
15731
15743
|
};
|
|
15732
15744
|
}
|
|
15733
15745
|
async function syncMemories(agent, configDir, log2) {
|
|
15734
|
-
const projectDir =
|
|
15735
|
-
const memoryDir =
|
|
15746
|
+
const projectDir = join25(configDir, agent.code_name, "project");
|
|
15747
|
+
const memoryDir = join25(projectDir, "memory");
|
|
15736
15748
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
15737
15749
|
if (isFreshSync) {
|
|
15738
15750
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -15750,7 +15762,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15750
15762
|
for (const file of readdirSync7(memoryDir)) {
|
|
15751
15763
|
if (!file.endsWith(".md")) continue;
|
|
15752
15764
|
try {
|
|
15753
|
-
const raw =
|
|
15765
|
+
const raw = readFileSync21(join25(memoryDir, file), "utf-8");
|
|
15754
15766
|
const fileHash = createHash16("sha256").update(raw).digest("hex").slice(0, 16);
|
|
15755
15767
|
currentHashes.set(file, fileHash);
|
|
15756
15768
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -15775,7 +15787,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15775
15787
|
} catch (err) {
|
|
15776
15788
|
for (const mem of changedMemories) {
|
|
15777
15789
|
for (const [file] of currentHashes) {
|
|
15778
|
-
const parsed = parseMemoryFile(
|
|
15790
|
+
const parsed = parseMemoryFile(readFileSync21(join25(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
15779
15791
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
15780
15792
|
}
|
|
15781
15793
|
}
|
|
@@ -15803,14 +15815,14 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
|
15803
15815
|
lastDownloadHash.set(agent.agent_id, responseHash);
|
|
15804
15816
|
lastLocalFileHash.set(agent.agent_id, localListHash);
|
|
15805
15817
|
if (dbMemories.memories?.length) {
|
|
15806
|
-
|
|
15818
|
+
mkdirSync10(memoryDir, { recursive: true });
|
|
15807
15819
|
let written = 0;
|
|
15808
15820
|
let overwritten = 0;
|
|
15809
15821
|
for (let i = 0; i < dbMemories.memories.length; i++) {
|
|
15810
15822
|
const mem = dbMemories.memories[i];
|
|
15811
15823
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
15812
15824
|
const slug = rawSlug || `memory-${i}`;
|
|
15813
|
-
const filePath =
|
|
15825
|
+
const filePath = join25(memoryDir, `${slug}.md`);
|
|
15814
15826
|
const desired = `---
|
|
15815
15827
|
name: ${JSON.stringify(mem.name)}
|
|
15816
15828
|
type: ${mem.type}
|
|
@@ -15822,14 +15834,14 @@ ${mem.content}
|
|
|
15822
15834
|
if (existsSync11(filePath)) {
|
|
15823
15835
|
let existing = "";
|
|
15824
15836
|
try {
|
|
15825
|
-
existing =
|
|
15837
|
+
existing = readFileSync21(filePath, "utf-8");
|
|
15826
15838
|
} catch {
|
|
15827
15839
|
}
|
|
15828
15840
|
if (existing === desired) continue;
|
|
15829
|
-
|
|
15841
|
+
writeFileSync12(filePath, desired);
|
|
15830
15842
|
overwritten++;
|
|
15831
15843
|
} else {
|
|
15832
|
-
|
|
15844
|
+
writeFileSync12(filePath, desired);
|
|
15833
15845
|
written++;
|
|
15834
15846
|
}
|
|
15835
15847
|
}
|
|
@@ -15845,10 +15857,10 @@ ${mem.content}
|
|
|
15845
15857
|
return false;
|
|
15846
15858
|
}
|
|
15847
15859
|
}
|
|
15848
|
-
async function cleanupAgentFiles(codeName,
|
|
15849
|
-
if (existsSync11(
|
|
15860
|
+
async function cleanupAgentFiles(codeName, agentDir) {
|
|
15861
|
+
if (existsSync11(agentDir)) {
|
|
15850
15862
|
try {
|
|
15851
|
-
|
|
15863
|
+
rmSync5(agentDir, { recursive: true, force: true });
|
|
15852
15864
|
log(`Removed provision directory for '${codeName}'`);
|
|
15853
15865
|
} catch (err) {
|
|
15854
15866
|
log(`Failed to remove provision dir for '${codeName}': ${err.message}`);
|
|
@@ -16086,7 +16098,7 @@ function startManager(opts) {
|
|
|
16086
16098
|
try {
|
|
16087
16099
|
const stateFile = getStateFile();
|
|
16088
16100
|
if (existsSync11(stateFile)) {
|
|
16089
|
-
const raw =
|
|
16101
|
+
const raw = readFileSync21(stateFile, "utf-8");
|
|
16090
16102
|
const parsed = JSON.parse(raw);
|
|
16091
16103
|
if (Array.isArray(parsed.agents)) {
|
|
16092
16104
|
state6.agents = parsed.agents;
|
|
@@ -16113,7 +16125,7 @@ function startManager(opts) {
|
|
|
16113
16125
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
16114
16126
|
}
|
|
16115
16127
|
log(
|
|
16116
|
-
`[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")}`
|
|
16117
16129
|
);
|
|
16118
16130
|
deployMcpAssets();
|
|
16119
16131
|
reapOrphanChannelMcps({ log });
|
|
@@ -16142,7 +16154,7 @@ async function reapOrphanedClaudePids() {
|
|
|
16142
16154
|
const looksLikeClaude = (pid) => {
|
|
16143
16155
|
if (process.platform !== "linux") return true;
|
|
16144
16156
|
try {
|
|
16145
|
-
const comm =
|
|
16157
|
+
const comm = readFileSync21(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
16146
16158
|
return comm.includes("claude");
|
|
16147
16159
|
} catch {
|
|
16148
16160
|
return false;
|
|
@@ -16239,14 +16251,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
16239
16251
|
}
|
|
16240
16252
|
}
|
|
16241
16253
|
function deployMcpAssets() {
|
|
16242
|
-
const targetDir =
|
|
16243
|
-
|
|
16254
|
+
const targetDir = join25(homedir11(), ".augmented", "_mcp");
|
|
16255
|
+
mkdirSync10(targetDir, { recursive: true });
|
|
16244
16256
|
const moduleDir = dirname8(fileURLToPath(import.meta.url));
|
|
16245
16257
|
let mcpSourceDir = "";
|
|
16246
16258
|
let dir = moduleDir;
|
|
16247
16259
|
for (let i = 0; i < 6; i++) {
|
|
16248
|
-
const candidate =
|
|
16249
|
-
if (existsSync11(
|
|
16260
|
+
const candidate = join25(dir, "dist", "mcp");
|
|
16261
|
+
if (existsSync11(join25(candidate, "index.js"))) {
|
|
16250
16262
|
mcpSourceDir = candidate;
|
|
16251
16263
|
break;
|
|
16252
16264
|
}
|
|
@@ -16262,7 +16274,7 @@ function deployMcpAssets() {
|
|
|
16262
16274
|
const fileHash = (p) => {
|
|
16263
16275
|
try {
|
|
16264
16276
|
if (!existsSync11(p)) return null;
|
|
16265
|
-
return createHash16("sha256").update(
|
|
16277
|
+
return createHash16("sha256").update(readFileSync21(p)).digest("hex");
|
|
16266
16278
|
} catch {
|
|
16267
16279
|
return null;
|
|
16268
16280
|
}
|
|
@@ -16326,8 +16338,8 @@ function deployMcpAssets() {
|
|
|
16326
16338
|
// needs restarting to pick up a token rotation.
|
|
16327
16339
|
"xero.js"
|
|
16328
16340
|
]) {
|
|
16329
|
-
const src =
|
|
16330
|
-
const dst =
|
|
16341
|
+
const src = join25(mcpSourceDir, file);
|
|
16342
|
+
const dst = join25(targetDir, file);
|
|
16331
16343
|
if (!existsSync11(src)) continue;
|
|
16332
16344
|
const before = fileHash(dst);
|
|
16333
16345
|
try {
|
|
@@ -16345,23 +16357,23 @@ function deployMcpAssets() {
|
|
|
16345
16357
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
16346
16358
|
restartRunningChannelMcps(changedBasenames);
|
|
16347
16359
|
}
|
|
16348
|
-
const localMcpPath =
|
|
16360
|
+
const localMcpPath = join25(targetDir, "index.js");
|
|
16349
16361
|
try {
|
|
16350
|
-
const agentsDir =
|
|
16362
|
+
const agentsDir = join25(homedir11(), ".augmented", "agents");
|
|
16351
16363
|
if (existsSync11(agentsDir)) {
|
|
16352
16364
|
for (const entry of readdirSync7(agentsDir, { withFileTypes: true })) {
|
|
16353
16365
|
if (!entry.isDirectory()) continue;
|
|
16354
16366
|
for (const subdir of ["provision", "project"]) {
|
|
16355
|
-
const mcpJsonPath =
|
|
16367
|
+
const mcpJsonPath = join25(agentsDir, entry.name, subdir, ".mcp.json");
|
|
16356
16368
|
try {
|
|
16357
|
-
const raw =
|
|
16369
|
+
const raw = readFileSync21(mcpJsonPath, "utf-8");
|
|
16358
16370
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
16359
16371
|
const mcpConfig = JSON.parse(raw);
|
|
16360
16372
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|
|
16361
16373
|
if (!augServer) continue;
|
|
16362
16374
|
augServer.command = "node";
|
|
16363
16375
|
augServer.args = [localMcpPath];
|
|
16364
|
-
|
|
16376
|
+
writeFileSync12(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
16365
16377
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
16366
16378
|
} catch {
|
|
16367
16379
|
}
|
|
@@ -16398,13 +16410,11 @@ process.on("disconnect", () => {
|
|
|
16398
16410
|
export {
|
|
16399
16411
|
BACK_ONLINE_GREETING_GUIDANCE,
|
|
16400
16412
|
DAY_ROLLOVER_FORCE_GRACE_MIN,
|
|
16401
|
-
_resetClaudeAccountByAgent,
|
|
16402
16413
|
applyRestartAcks,
|
|
16403
16414
|
cancelKanbanNoticeOnDrain,
|
|
16404
16415
|
claudeCodeUpgradeMarkerPath,
|
|
16405
16416
|
claudeCodeUpgradeThrottled,
|
|
16406
16417
|
claudeManagedSettingsPath,
|
|
16407
|
-
clearUsageLimitMarkerOnAccountChange,
|
|
16408
16418
|
dashboardRestartBreakerReason,
|
|
16409
16419
|
ensureClaudeManagedSettings,
|
|
16410
16420
|
extractCharterSlackPeers,
|