@integrity-labs/agt-cli 0.28.438 → 0.28.440
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-MOASN7XT.js → chunk-R6GVWACQ.js} +48 -6
- package/dist/{chunk-MOASN7XT.js.map → chunk-R6GVWACQ.js.map} +1 -1
- package/dist/{chunk-WNSFE56R.js → chunk-V3G7G4QM.js} +3 -3
- package/dist/{claude-pair-runtime-QDNXOLED.js → claude-pair-runtime-Z4DP2IQA.js} +2 -2
- package/dist/lib/manager-worker.js +337 -216
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-2TTEAJDH.js → persistent-session-4MIMM3TN.js} +2 -2
- package/dist/{responsiveness-probe-PMDNQ4J4.js → responsiveness-probe-5SRDBI4B.js} +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-WNSFE56R.js.map → chunk-V3G7G4QM.js.map} +0 -0
- /package/dist/{claude-pair-runtime-QDNXOLED.js.map → claude-pair-runtime-Z4DP2IQA.js.map} +0 -0
- /package/dist/{persistent-session-2TTEAJDH.js.map → persistent-session-4MIMM3TN.js.map} +0 -0
- /package/dist/{responsiveness-probe-PMDNQ4J4.js.map → responsiveness-probe-5SRDBI4B.js.map} +0 -0
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
resolveEffectivePinRaw,
|
|
43
43
|
safeWriteJsonAtomic,
|
|
44
44
|
setConfigHash
|
|
45
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-V3G7G4QM.js";
|
|
46
46
|
import {
|
|
47
47
|
getProjectDir as getProjectDir2,
|
|
48
48
|
getReadyTasks,
|
|
@@ -129,6 +129,7 @@ import {
|
|
|
129
129
|
readOpencodePaneLogTail,
|
|
130
130
|
readPaneLogTail,
|
|
131
131
|
readProvisionedOpencodeModel,
|
|
132
|
+
readUsageLimitUntil,
|
|
132
133
|
reloadEgressSidecar,
|
|
133
134
|
resetRestartCount,
|
|
134
135
|
resolveAgentTimezone,
|
|
@@ -142,6 +143,7 @@ import {
|
|
|
142
143
|
sessionTranscriptDir,
|
|
143
144
|
sha256,
|
|
144
145
|
sharedBusyBuckets,
|
|
146
|
+
shouldLogUsageCapDeferral,
|
|
145
147
|
startOpencodeSession,
|
|
146
148
|
startPersistentSession,
|
|
147
149
|
stopAllSessionsAndWait,
|
|
@@ -155,16 +157,16 @@ import {
|
|
|
155
157
|
transcriptActivityAgeSeconds,
|
|
156
158
|
writeEgressAllowlist,
|
|
157
159
|
writeUsageLimitMarker
|
|
158
|
-
} from "../chunk-
|
|
160
|
+
} from "../chunk-R6GVWACQ.js";
|
|
159
161
|
import {
|
|
160
162
|
reapOrphanChannelMcps
|
|
161
163
|
} from "../chunk-XWVM4KPK.js";
|
|
162
164
|
|
|
163
165
|
// src/lib/manager-worker.ts
|
|
164
166
|
import { createHash as createHash16 } from "crypto";
|
|
165
|
-
import { readFileSync as
|
|
167
|
+
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";
|
|
166
168
|
import { execFileSync as syncExecFile } from "child_process";
|
|
167
|
-
import { join as
|
|
169
|
+
import { join as join25, dirname as dirname8, delimiter as pathDelimiter } from "path";
|
|
168
170
|
import { homedir as homedir11 } from "os";
|
|
169
171
|
import { fileURLToPath } from "url";
|
|
170
172
|
|
|
@@ -2051,12 +2053,100 @@ var nodeArtifactFs = {
|
|
|
2051
2053
|
}
|
|
2052
2054
|
};
|
|
2053
2055
|
|
|
2056
|
+
// src/lib/agent-serving-probe.ts
|
|
2057
|
+
import { readFileSync as readFileSync7, readdirSync, statSync } from "fs";
|
|
2058
|
+
import { join as join6 } from "path";
|
|
2059
|
+
var RATE_LIMIT_WINDOW_MS = 15 * 60 * 1e3;
|
|
2060
|
+
function classifyLine(line, startMs, endMs) {
|
|
2061
|
+
const trimmed = line.trim();
|
|
2062
|
+
if (!trimmed) return null;
|
|
2063
|
+
let obj;
|
|
2064
|
+
try {
|
|
2065
|
+
obj = JSON.parse(trimmed);
|
|
2066
|
+
} catch {
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2069
|
+
if (typeof obj !== "object" || obj === null) return null;
|
|
2070
|
+
const record = obj;
|
|
2071
|
+
if (record.type !== "assistant") return null;
|
|
2072
|
+
const ts = record.timestamp;
|
|
2073
|
+
if (typeof ts !== "string" || !ts) return null;
|
|
2074
|
+
const tsMs = new Date(ts).getTime();
|
|
2075
|
+
if (!Number.isFinite(tsMs) || tsMs < startMs || tsMs > endMs) return null;
|
|
2076
|
+
if (record.error === "rate_limit" || record.apiErrorStatus === 429) {
|
|
2077
|
+
return { tsMs, verdict: "capped" };
|
|
2078
|
+
}
|
|
2079
|
+
if (record.isApiErrorMessage === true) return null;
|
|
2080
|
+
const message = record.message;
|
|
2081
|
+
if (typeof message !== "object" || message === null) return null;
|
|
2082
|
+
const msg = message;
|
|
2083
|
+
if (msg.model === "<synthetic>") return null;
|
|
2084
|
+
const usage = msg.usage;
|
|
2085
|
+
if (typeof usage !== "object" || usage === null) return null;
|
|
2086
|
+
const u = usage;
|
|
2087
|
+
const spent = Number(u.input_tokens ?? 0) + Number(u.output_tokens ?? 0) + Number(u.cache_creation_input_tokens ?? 0) + Number(u.cache_read_input_tokens ?? 0);
|
|
2088
|
+
if (!Number.isFinite(spent) || spent <= 0) return null;
|
|
2089
|
+
return { tsMs, verdict: "serving" };
|
|
2090
|
+
}
|
|
2091
|
+
function probeRateLimitState(args) {
|
|
2092
|
+
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
2093
|
+
const endMs = now.getTime();
|
|
2094
|
+
const startMs = endMs - (args.windowMs ?? RATE_LIMIT_WINDOW_MS);
|
|
2095
|
+
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
2096
|
+
let entries;
|
|
2097
|
+
try {
|
|
2098
|
+
entries = readdirSync(dir);
|
|
2099
|
+
} catch {
|
|
2100
|
+
return "unknown";
|
|
2101
|
+
}
|
|
2102
|
+
let newest = null;
|
|
2103
|
+
for (const name of entries) {
|
|
2104
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
2105
|
+
const path = join6(dir, name);
|
|
2106
|
+
try {
|
|
2107
|
+
const st = statSync(path);
|
|
2108
|
+
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
2109
|
+
} catch {
|
|
2110
|
+
continue;
|
|
2111
|
+
}
|
|
2112
|
+
let content;
|
|
2113
|
+
try {
|
|
2114
|
+
content = readFileSync7(path, "utf-8");
|
|
2115
|
+
} catch {
|
|
2116
|
+
continue;
|
|
2117
|
+
}
|
|
2118
|
+
for (const line of content.split("\n")) {
|
|
2119
|
+
const c = classifyLine(line, startMs, endMs);
|
|
2120
|
+
if (c && (newest === null || c.tsMs >= newest.tsMs)) newest = c;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
return newest?.verdict ?? "unknown";
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2054
2126
|
// src/lib/usage-banner-monitor.ts
|
|
2055
2127
|
function syncUsageLimitMarker(args) {
|
|
2056
2128
|
if (args.pct < 100) {
|
|
2057
2129
|
clearUsageLimitMarker(args.codeName, args.log);
|
|
2058
2130
|
return;
|
|
2059
2131
|
}
|
|
2132
|
+
const verdict = args.verdict ?? probeRateLimitState({
|
|
2133
|
+
codeName: args.codeName,
|
|
2134
|
+
projectDir: getProjectDir(args.codeName),
|
|
2135
|
+
now: args.now
|
|
2136
|
+
});
|
|
2137
|
+
if (verdict === "serving") {
|
|
2138
|
+
args.log(
|
|
2139
|
+
`[usage-banner] saturated banner for '${args.codeName}' NOT armed - a turn completed, so the agent is serving (ENG-8198)`
|
|
2140
|
+
);
|
|
2141
|
+
clearUsageLimitMarker(args.codeName, args.log);
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2144
|
+
if (verdict === "unknown") {
|
|
2145
|
+
args.log(
|
|
2146
|
+
`[usage-banner] saturated banner for '${args.codeName}' NOT armed - no classifiable turn in the transcript; leaving any existing marker untouched (ENG-8198)`
|
|
2147
|
+
);
|
|
2148
|
+
return;
|
|
2149
|
+
}
|
|
2060
2150
|
writeUsageLimitMarker(args.codeName, args.weekResetsAt, args.log);
|
|
2061
2151
|
}
|
|
2062
2152
|
var SPAWN_MARKER = /--- spawn \S+ \(session [^)]*\) ---/g;
|
|
@@ -2110,7 +2200,8 @@ async function maybeReportUsageBanner(args) {
|
|
|
2110
2200
|
codeName,
|
|
2111
2201
|
pct: observation.pct,
|
|
2112
2202
|
weekResetsAt: observation.weekResetsAt,
|
|
2113
|
-
log: log2
|
|
2203
|
+
log: log2,
|
|
2204
|
+
now
|
|
2114
2205
|
});
|
|
2115
2206
|
const observedAtIso = next.lastWeekResetsAt;
|
|
2116
2207
|
const weekResetsAtIso = observation.weekResetsAt.toISOString();
|
|
@@ -2138,12 +2229,12 @@ async function maybeReportUsageBanner(args) {
|
|
|
2138
2229
|
import { createHash as createHash6 } from "crypto";
|
|
2139
2230
|
import { readFile as readFile3, readdir as readdir3 } from "fs/promises";
|
|
2140
2231
|
import { homedir as homedir4, platform as platform2 } from "os";
|
|
2141
|
-
import { dirname as dirname4, join as
|
|
2232
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
2142
2233
|
|
|
2143
2234
|
// src/lib/claude-auth-detect.ts
|
|
2144
2235
|
import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
2145
2236
|
import { homedir as homedir3, platform } from "os";
|
|
2146
|
-
import { join as
|
|
2237
|
+
import { join as join7 } from "path";
|
|
2147
2238
|
import { execFile } from "child_process";
|
|
2148
2239
|
import { promisify } from "util";
|
|
2149
2240
|
var execFileAsync = promisify(execFile);
|
|
@@ -2158,16 +2249,16 @@ async function detectClaudeAuth() {
|
|
|
2158
2249
|
}
|
|
2159
2250
|
async function findClaudeCredentialsPaths() {
|
|
2160
2251
|
const candidates = [
|
|
2161
|
-
|
|
2162
|
-
|
|
2252
|
+
join7(homedir3(), ".claude", ".credentials.json"),
|
|
2253
|
+
join7(homedir3(), ".claude", "credentials.json")
|
|
2163
2254
|
];
|
|
2164
2255
|
const isLinuxRoot = platform() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
|
|
2165
2256
|
if (isLinuxRoot) {
|
|
2166
2257
|
try {
|
|
2167
2258
|
const entries = await readdir2("/home", { withFileTypes: true });
|
|
2168
2259
|
for (const entry of entries.filter((entry2) => entry2.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2169
|
-
candidates.push(
|
|
2170
|
-
candidates.push(
|
|
2260
|
+
candidates.push(join7("/home", entry.name, ".claude", ".credentials.json"));
|
|
2261
|
+
candidates.push(join7("/home", entry.name, ".claude", "credentials.json"));
|
|
2171
2262
|
}
|
|
2172
2263
|
} catch {
|
|
2173
2264
|
}
|
|
@@ -2251,7 +2342,7 @@ async function candidateHomes() {
|
|
|
2251
2342
|
try {
|
|
2252
2343
|
const entries = await readdir3("/home", { withFileTypes: true });
|
|
2253
2344
|
for (const entry of entries.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2254
|
-
homes.push(
|
|
2345
|
+
homes.push(join8("/home", entry.name));
|
|
2255
2346
|
}
|
|
2256
2347
|
} catch {
|
|
2257
2348
|
}
|
|
@@ -2271,11 +2362,11 @@ async function homeOfActiveCredentials() {
|
|
|
2271
2362
|
async function claudeConfigCandidatePaths() {
|
|
2272
2363
|
const paths = [];
|
|
2273
2364
|
const configDir = process.env["CLAUDE_CONFIG_DIR"]?.trim();
|
|
2274
|
-
if (configDir) paths.push(
|
|
2365
|
+
if (configDir) paths.push(join8(configDir, ".claude.json"));
|
|
2275
2366
|
const activeHome = await homeOfActiveCredentials();
|
|
2276
|
-
if (activeHome) paths.push(
|
|
2367
|
+
if (activeHome) paths.push(join8(activeHome, ".claude.json"));
|
|
2277
2368
|
for (const home of await candidateHomes()) {
|
|
2278
|
-
const path =
|
|
2369
|
+
const path = join8(home, ".claude.json");
|
|
2279
2370
|
if (!paths.includes(path)) paths.push(path);
|
|
2280
2371
|
}
|
|
2281
2372
|
return paths;
|
|
@@ -2321,9 +2412,9 @@ async function getClaudeAccountFingerprint(paths, nowMs = Date.now()) {
|
|
|
2321
2412
|
// src/lib/account-enforcement-marker.ts
|
|
2322
2413
|
import { mkdirSync as mkdirSync4, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
2323
2414
|
import { homedir as homedir5 } from "os";
|
|
2324
|
-
import { join as
|
|
2415
|
+
import { join as join9 } from "path";
|
|
2325
2416
|
function accountEnforcementMarkerPath(codeName) {
|
|
2326
|
-
return
|
|
2417
|
+
return join9(homedir5(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2327
2418
|
}
|
|
2328
2419
|
function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.stderr.write(`${m}
|
|
2329
2420
|
`)) {
|
|
@@ -2331,8 +2422,8 @@ function syncAccountEnforcementMarker(codeName, level, log2 = (m) => process.std
|
|
|
2331
2422
|
clearAccountEnforcementMarker(codeName, log2);
|
|
2332
2423
|
return;
|
|
2333
2424
|
}
|
|
2334
|
-
const dir =
|
|
2335
|
-
const path =
|
|
2425
|
+
const dir = join9(homedir5(), ".augmented", codeName);
|
|
2426
|
+
const path = join9(dir, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
|
|
2336
2427
|
const tempPath = `${path}.${process.pid}.tmp`;
|
|
2337
2428
|
try {
|
|
2338
2429
|
mkdirSync4(dir, { recursive: true });
|
|
@@ -2357,8 +2448,8 @@ function clearAccountEnforcementMarker(codeName, log2 = (m) => process.stderr.wr
|
|
|
2357
2448
|
}
|
|
2358
2449
|
|
|
2359
2450
|
// src/lib/token-usage-monitor.ts
|
|
2360
|
-
import { readdirSync, readFileSync as
|
|
2361
|
-
import { join as
|
|
2451
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
2452
|
+
import { join as join10 } from "path";
|
|
2362
2453
|
var MIN_CHECK_INTERVAL_MS2 = 6e4;
|
|
2363
2454
|
var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
2364
2455
|
var MAX_ENTRIES_PER_POST = 200;
|
|
@@ -2376,7 +2467,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2376
2467
|
const next = { files, lastCheckedAt: nowMs };
|
|
2377
2468
|
let dirEntries;
|
|
2378
2469
|
try {
|
|
2379
|
-
dirEntries =
|
|
2470
|
+
dirEntries = readdirSync2(dir);
|
|
2380
2471
|
} catch {
|
|
2381
2472
|
state2.set(codeName, next);
|
|
2382
2473
|
return;
|
|
@@ -2387,10 +2478,10 @@ async function maybeReportTokenUsage(args) {
|
|
|
2387
2478
|
if (!name.endsWith(".jsonl")) continue;
|
|
2388
2479
|
const sessionId = name.slice(0, -".jsonl".length);
|
|
2389
2480
|
if (!sessionId) continue;
|
|
2390
|
-
const path =
|
|
2481
|
+
const path = join10(dir, name);
|
|
2391
2482
|
let st;
|
|
2392
2483
|
try {
|
|
2393
|
-
st =
|
|
2484
|
+
st = statSync2(path);
|
|
2394
2485
|
} catch {
|
|
2395
2486
|
continue;
|
|
2396
2487
|
}
|
|
@@ -2403,7 +2494,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2403
2494
|
}
|
|
2404
2495
|
let content;
|
|
2405
2496
|
try {
|
|
2406
|
-
content =
|
|
2497
|
+
content = readFileSync8(path, "utf-8");
|
|
2407
2498
|
} catch (err) {
|
|
2408
2499
|
log2(`[token-usage] read failed for '${codeName}/${name}': ${err.message}`);
|
|
2409
2500
|
continue;
|
|
@@ -2484,8 +2575,8 @@ async function maybeReportTokenUsage(args) {
|
|
|
2484
2575
|
}
|
|
2485
2576
|
|
|
2486
2577
|
// src/lib/workflow-run-reconciler.ts
|
|
2487
|
-
import { readdirSync as
|
|
2488
|
-
import { join as
|
|
2578
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
|
|
2579
|
+
import { join as join11 } from "path";
|
|
2489
2580
|
var MIN_CHECK_INTERVAL_MS3 = 5 * 6e4;
|
|
2490
2581
|
var SETTLE_MS = 3e4;
|
|
2491
2582
|
var TRANSCRIPT_MTIME_WINDOW_MS2 = 2 * 24 * 60 * 60 * 1e3;
|
|
@@ -2499,15 +2590,15 @@ function collectJsonlRecursive(dir, minMtimeMs, out, depth) {
|
|
|
2499
2590
|
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
2500
2591
|
let entries;
|
|
2501
2592
|
try {
|
|
2502
|
-
entries =
|
|
2593
|
+
entries = readdirSync3(dir);
|
|
2503
2594
|
} catch {
|
|
2504
2595
|
return;
|
|
2505
2596
|
}
|
|
2506
2597
|
for (const name of entries) {
|
|
2507
|
-
const p =
|
|
2598
|
+
const p = join11(dir, name);
|
|
2508
2599
|
let st;
|
|
2509
2600
|
try {
|
|
2510
|
-
st =
|
|
2601
|
+
st = statSync3(p);
|
|
2511
2602
|
} catch {
|
|
2512
2603
|
continue;
|
|
2513
2604
|
}
|
|
@@ -2522,15 +2613,15 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2522
2613
|
const out = [];
|
|
2523
2614
|
let entries;
|
|
2524
2615
|
try {
|
|
2525
|
-
entries =
|
|
2616
|
+
entries = readdirSync3(transcriptDir);
|
|
2526
2617
|
} catch {
|
|
2527
2618
|
return out;
|
|
2528
2619
|
}
|
|
2529
2620
|
for (const name of entries) {
|
|
2530
|
-
const path =
|
|
2621
|
+
const path = join11(transcriptDir, name);
|
|
2531
2622
|
let st;
|
|
2532
2623
|
try {
|
|
2533
|
-
st =
|
|
2624
|
+
st = statSync3(path);
|
|
2534
2625
|
} catch {
|
|
2535
2626
|
continue;
|
|
2536
2627
|
}
|
|
@@ -2539,7 +2630,7 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
2539
2630
|
continue;
|
|
2540
2631
|
}
|
|
2541
2632
|
if (st.isDirectory()) {
|
|
2542
|
-
collectJsonlRecursive(
|
|
2633
|
+
collectJsonlRecursive(join11(path, "subagents"), minMtimeMs, out, 0);
|
|
2543
2634
|
}
|
|
2544
2635
|
}
|
|
2545
2636
|
return out;
|
|
@@ -2584,7 +2675,7 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2584
2675
|
const contents = [];
|
|
2585
2676
|
for (const path of files) {
|
|
2586
2677
|
try {
|
|
2587
|
-
contents.push(
|
|
2678
|
+
contents.push(readFileSync9(path, "utf-8"));
|
|
2588
2679
|
} catch {
|
|
2589
2680
|
}
|
|
2590
2681
|
}
|
|
@@ -2629,8 +2720,8 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
2629
2720
|
}
|
|
2630
2721
|
|
|
2631
2722
|
// src/lib/conversation-evaluator.ts
|
|
2632
|
-
import { readdirSync as
|
|
2633
|
-
import { join as
|
|
2723
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
|
|
2724
|
+
import { join as join12 } from "path";
|
|
2634
2725
|
var MIN_CHECK_INTERVAL_MS4 = 5 * 6e4;
|
|
2635
2726
|
var TRANSCRIPT_MTIME_WINDOW_MS3 = 7 * 24 * 60 * 60 * 1e3;
|
|
2636
2727
|
var WINDOW_PAD_MS = 5 * 6e4;
|
|
@@ -3061,12 +3152,12 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3061
3152
|
const visit = (d) => {
|
|
3062
3153
|
let entries;
|
|
3063
3154
|
try {
|
|
3064
|
-
entries =
|
|
3155
|
+
entries = readdirSync4(d, { withFileTypes: true });
|
|
3065
3156
|
} catch {
|
|
3066
3157
|
return;
|
|
3067
3158
|
}
|
|
3068
3159
|
for (const ent of entries) {
|
|
3069
|
-
const full =
|
|
3160
|
+
const full = join12(d, ent.name);
|
|
3070
3161
|
if (ent.isDirectory()) {
|
|
3071
3162
|
visit(full);
|
|
3072
3163
|
continue;
|
|
@@ -3074,14 +3165,14 @@ function readRecentTurns(dir, nowMs) {
|
|
|
3074
3165
|
if (!ent.isFile() || !ent.name.endsWith(".jsonl")) continue;
|
|
3075
3166
|
let mtimeMs;
|
|
3076
3167
|
try {
|
|
3077
|
-
mtimeMs =
|
|
3168
|
+
mtimeMs = statSync4(full).mtimeMs;
|
|
3078
3169
|
} catch {
|
|
3079
3170
|
continue;
|
|
3080
3171
|
}
|
|
3081
3172
|
if (nowMs - mtimeMs > TRANSCRIPT_MTIME_WINDOW_MS3) continue;
|
|
3082
3173
|
let content;
|
|
3083
3174
|
try {
|
|
3084
|
-
content =
|
|
3175
|
+
content = readFileSync10(full, "utf8");
|
|
3085
3176
|
} catch {
|
|
3086
3177
|
continue;
|
|
3087
3178
|
}
|
|
@@ -3371,11 +3462,11 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
|
|
|
3371
3462
|
}
|
|
3372
3463
|
|
|
3373
3464
|
// src/lib/activity-cache-monitor.ts
|
|
3374
|
-
import { existsSync as existsSync2, readFileSync as
|
|
3465
|
+
import { existsSync as existsSync2, readFileSync as readFileSync11 } from "fs";
|
|
3375
3466
|
import { homedir as homedir6 } from "os";
|
|
3376
|
-
import { join as
|
|
3467
|
+
import { join as join13 } from "path";
|
|
3377
3468
|
var MIN_CHECK_INTERVAL_MS6 = 6e4;
|
|
3378
|
-
var STATS_CACHE_PATH =
|
|
3469
|
+
var STATS_CACHE_PATH = join13(homedir6(), ".claude", "stats-cache.json");
|
|
3379
3470
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
3380
3471
|
var state5 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
3381
3472
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
@@ -3423,7 +3514,7 @@ async function maybeReportActivityCache(args) {
|
|
|
3423
3514
|
}
|
|
3424
3515
|
let raw;
|
|
3425
3516
|
try {
|
|
3426
|
-
raw =
|
|
3517
|
+
raw = readFileSync11(STATS_CACHE_PATH, "utf-8");
|
|
3427
3518
|
} catch (err) {
|
|
3428
3519
|
log2(`[activity-cache] readFileSync failed: ${err.message}`);
|
|
3429
3520
|
return;
|
|
@@ -3627,18 +3718,18 @@ function computeChannelConfigHash(input) {
|
|
|
3627
3718
|
}
|
|
3628
3719
|
|
|
3629
3720
|
// src/lib/channel-hash-cache.ts
|
|
3630
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3631
|
-
import { join as
|
|
3721
|
+
import { existsSync as existsSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
|
|
3722
|
+
import { join as join14 } from "path";
|
|
3632
3723
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
3633
3724
|
function getChannelHashCacheFile(configDir) {
|
|
3634
|
-
return
|
|
3725
|
+
return join14(configDir, CACHE_FILENAME);
|
|
3635
3726
|
}
|
|
3636
3727
|
function loadChannelHashCache(target, configDir) {
|
|
3637
3728
|
const path = getChannelHashCacheFile(configDir);
|
|
3638
3729
|
if (!existsSync3(path)) return;
|
|
3639
3730
|
let parsed;
|
|
3640
3731
|
try {
|
|
3641
|
-
parsed = JSON.parse(
|
|
3732
|
+
parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
3642
3733
|
} catch {
|
|
3643
3734
|
return;
|
|
3644
3735
|
}
|
|
@@ -3658,8 +3749,8 @@ function saveChannelHashCache(source, configDir) {
|
|
|
3658
3749
|
}
|
|
3659
3750
|
|
|
3660
3751
|
// src/lib/sender-policy-baseline.ts
|
|
3661
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3662
|
-
import { join as
|
|
3752
|
+
import { existsSync as existsSync4, readFileSync as readFileSync13 } from "fs";
|
|
3753
|
+
import { join as join15 } from "path";
|
|
3663
3754
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
3664
3755
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
3665
3756
|
var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
|
|
@@ -3671,14 +3762,14 @@ function createDeliveryBaselineMaps() {
|
|
|
3671
3762
|
};
|
|
3672
3763
|
}
|
|
3673
3764
|
function getSenderPolicyBaselineFile(configDir) {
|
|
3674
|
-
return
|
|
3765
|
+
return join15(configDir, BASELINE_FILENAME);
|
|
3675
3766
|
}
|
|
3676
3767
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
3677
3768
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
3678
3769
|
if (!existsSync4(path)) return;
|
|
3679
3770
|
let parsed;
|
|
3680
3771
|
try {
|
|
3681
|
-
parsed = JSON.parse(
|
|
3772
|
+
parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
3682
3773
|
} catch (err) {
|
|
3683
3774
|
log2?.(
|
|
3684
3775
|
`[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
|
|
@@ -4201,16 +4292,16 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
4201
4292
|
}
|
|
4202
4293
|
|
|
4203
4294
|
// src/lib/manager/managed-skill-manifest.ts
|
|
4204
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as
|
|
4205
|
-
import { dirname as dirname5, join as
|
|
4295
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync6 } from "fs";
|
|
4296
|
+
import { dirname as dirname5, join as join16 } from "path";
|
|
4206
4297
|
var MANIFEST_VERSION = 1;
|
|
4207
4298
|
function managedSkillManifestPath(agentRootDir) {
|
|
4208
|
-
return
|
|
4299
|
+
return join16(agentRootDir, "managed-skills.json");
|
|
4209
4300
|
}
|
|
4210
4301
|
function readManagedSkillManifest(path) {
|
|
4211
4302
|
try {
|
|
4212
4303
|
if (!existsSync5(path)) return /* @__PURE__ */ new Set();
|
|
4213
|
-
const parsed = JSON.parse(
|
|
4304
|
+
const parsed = JSON.parse(readFileSync14(path, "utf-8"));
|
|
4214
4305
|
const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
|
|
4215
4306
|
return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
|
|
4216
4307
|
} catch {
|
|
@@ -4323,7 +4414,7 @@ function resolveModelChain(refreshData) {
|
|
|
4323
4414
|
|
|
4324
4415
|
// src/lib/manager/claude-auth.ts
|
|
4325
4416
|
import { existsSync as existsSync6, rmSync as rmSync3 } from "fs";
|
|
4326
|
-
import { join as
|
|
4417
|
+
import { join as join17 } from "path";
|
|
4327
4418
|
import { homedir as homedir7 } from "os";
|
|
4328
4419
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
4329
4420
|
const apiKey = getApiKey();
|
|
@@ -4336,9 +4427,9 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4336
4427
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
4337
4428
|
}
|
|
4338
4429
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
4339
|
-
const claudeDir =
|
|
4430
|
+
const claudeDir = join17(homedir7(), ".claude");
|
|
4340
4431
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
4341
|
-
const p =
|
|
4432
|
+
const p = join17(claudeDir, filename);
|
|
4342
4433
|
if (existsSync6(p)) {
|
|
4343
4434
|
try {
|
|
4344
4435
|
rmSync3(p, { force: true });
|
|
@@ -4353,8 +4444,8 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
4353
4444
|
}
|
|
4354
4445
|
|
|
4355
4446
|
// src/lib/manager/kanban/parsers.ts
|
|
4356
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4357
|
-
import { join as
|
|
4447
|
+
import { existsSync as existsSync7, readFileSync as readFileSync15 } from "fs";
|
|
4448
|
+
import { join as join18 } from "path";
|
|
4358
4449
|
var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
|
|
4359
4450
|
var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
|
|
4360
4451
|
var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
|
|
@@ -4493,12 +4584,12 @@ function getBuiltInSkillContent(skillId) {
|
|
|
4493
4584
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
4494
4585
|
try {
|
|
4495
4586
|
const candidates = [
|
|
4496
|
-
|
|
4497
|
-
|
|
4587
|
+
join18(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
4588
|
+
join18(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
4498
4589
|
];
|
|
4499
4590
|
for (const candidate of candidates) {
|
|
4500
4591
|
if (existsSync7(candidate)) {
|
|
4501
|
-
const content =
|
|
4592
|
+
const content = readFileSync15(candidate, "utf-8");
|
|
4502
4593
|
const files = [{ relativePath: "SKILL.md", content }];
|
|
4503
4594
|
builtInSkillCache.set(skillId, files);
|
|
4504
4595
|
return files;
|
|
@@ -4639,19 +4730,19 @@ function formatBoardForPrompt(items, template) {
|
|
|
4639
4730
|
}
|
|
4640
4731
|
|
|
4641
4732
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
4642
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4643
|
-
import { join as
|
|
4733
|
+
import { existsSync as existsSync8, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "fs";
|
|
4734
|
+
import { join as join19 } from "path";
|
|
4644
4735
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
4645
4736
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
4646
4737
|
function getKanbanNudgeStateFile(configDir) {
|
|
4647
|
-
return
|
|
4738
|
+
return join19(configDir, CACHE_FILENAME2);
|
|
4648
4739
|
}
|
|
4649
4740
|
function loadKanbanNudgeState(target, configDir) {
|
|
4650
4741
|
const path = getKanbanNudgeStateFile(configDir);
|
|
4651
4742
|
if (!existsSync8(path)) return;
|
|
4652
4743
|
let parsed;
|
|
4653
4744
|
try {
|
|
4654
|
-
parsed = JSON.parse(
|
|
4745
|
+
parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
4655
4746
|
} catch {
|
|
4656
4747
|
return;
|
|
4657
4748
|
}
|
|
@@ -5217,9 +5308,9 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
5217
5308
|
|
|
5218
5309
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
5219
5310
|
import { createHash as createHash11 } from "crypto";
|
|
5220
|
-
import { writeFileSync as writeFileSync8, renameSync as renameSync2, mkdirSync as mkdirSync6, readFileSync as
|
|
5311
|
+
import { writeFileSync as writeFileSync8, renameSync as renameSync2, mkdirSync as mkdirSync6, readFileSync as readFileSync17, unlinkSync } from "fs";
|
|
5221
5312
|
import { homedir as homedir8 } from "os";
|
|
5222
|
-
import { join as
|
|
5313
|
+
import { join as join20, dirname as dirname6 } from "path";
|
|
5223
5314
|
|
|
5224
5315
|
// src/lib/manager/scheduler/notify.ts
|
|
5225
5316
|
import { createHash as createHash10 } from "crypto";
|
|
@@ -5559,7 +5650,7 @@ function resolveScheduledSlackTarget(task) {
|
|
|
5559
5650
|
}
|
|
5560
5651
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
5561
5652
|
try {
|
|
5562
|
-
const file =
|
|
5653
|
+
const file = join20(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5563
5654
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
5564
5655
|
const tmp = `${file}.tmp`;
|
|
5565
5656
|
writeFileSync8(tmp, JSON.stringify(marker), "utf8");
|
|
@@ -5569,9 +5660,9 @@ function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
|
5569
5660
|
}
|
|
5570
5661
|
}
|
|
5571
5662
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
5572
|
-
const file =
|
|
5663
|
+
const file = join20(homedir8(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
5573
5664
|
try {
|
|
5574
|
-
const raw = JSON.parse(
|
|
5665
|
+
const raw = JSON.parse(readFileSync17(file, "utf8"));
|
|
5575
5666
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
5576
5667
|
unlinkSync(file);
|
|
5577
5668
|
log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
|
|
@@ -5778,9 +5869,9 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5778
5869
|
// src/lib/manager/scheduler/execution.ts
|
|
5779
5870
|
import { createHash as createHash12 } from "crypto";
|
|
5780
5871
|
import { homedir as homedir9 } from "os";
|
|
5781
|
-
import { join as
|
|
5872
|
+
import { join as join21 } from "path";
|
|
5782
5873
|
function claudePidFilePath() {
|
|
5783
|
-
return
|
|
5874
|
+
return join21(homedir9(), ".augmented", "manager-claude-pids.json");
|
|
5784
5875
|
}
|
|
5785
5876
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
5786
5877
|
function registerClaudeSpawn(record) {
|
|
@@ -5819,6 +5910,15 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5819
5910
|
const state7 = claudeSchedulerStates.get(codeName);
|
|
5820
5911
|
const ready = getReadyTasks(state7, inFlightClaudeTasks);
|
|
5821
5912
|
if (ready.length === 0) return;
|
|
5913
|
+
const limitedUntil = readUsageLimitUntil({ codeName });
|
|
5914
|
+
if (limitedUntil) {
|
|
5915
|
+
if (shouldLogUsageCapDeferral("claude-scheduler", codeName, limitedUntil)) {
|
|
5916
|
+
log(
|
|
5917
|
+
`[claude-scheduler] Deferring ${ready.length} ready task(s) for '${codeName}' \u2014 agent is at its Claude usage limit until ${limitedUntil.toISOString()}; schedule NOT advanced, will fire after the limit resets (further deferrals this window are not logged)`
|
|
5918
|
+
);
|
|
5919
|
+
}
|
|
5920
|
+
return;
|
|
5921
|
+
}
|
|
5822
5922
|
for (const task of ready) {
|
|
5823
5923
|
if ((claudeTaskConcurrency.get(codeName) ?? 0) >= MAX_CLAUDE_CONCURRENCY) break;
|
|
5824
5924
|
if (KANBAN_WORK_TEMPLATES.has(task.templateId)) {
|
|
@@ -5841,14 +5941,14 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5841
5941
|
}
|
|
5842
5942
|
|
|
5843
5943
|
// src/lib/pane-occupancy-sampler.ts
|
|
5844
|
-
import { statSync as
|
|
5944
|
+
import { statSync as statSync5 } from "fs";
|
|
5845
5945
|
var SAMPLE_INTERVAL_MS = 1e4;
|
|
5846
5946
|
var IDLE_GAP_MS = 12e4;
|
|
5847
5947
|
var POST_IDLE_CREDIT_MS = 6e4;
|
|
5848
5948
|
var lastMtimeMs = /* @__PURE__ */ new Map();
|
|
5849
5949
|
function paneMtimeMs(codeName) {
|
|
5850
5950
|
try {
|
|
5851
|
-
return
|
|
5951
|
+
return statSync5(paneLogPath(codeName)).mtimeMs;
|
|
5852
5952
|
} catch {
|
|
5853
5953
|
return null;
|
|
5854
5954
|
}
|
|
@@ -7004,9 +7104,9 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
7004
7104
|
|
|
7005
7105
|
// src/lib/opencode-telegram-ingest.ts
|
|
7006
7106
|
import { createHash as createHash15 } from "crypto";
|
|
7007
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as
|
|
7107
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
7008
7108
|
import { randomUUID } from "crypto";
|
|
7009
|
-
import { join as
|
|
7109
|
+
import { join as join22 } from "path";
|
|
7010
7110
|
|
|
7011
7111
|
// src/lib/telegram-ingest.ts
|
|
7012
7112
|
import https2 from "https";
|
|
@@ -7554,7 +7654,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7554
7654
|
let filePath;
|
|
7555
7655
|
try {
|
|
7556
7656
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
7557
|
-
filePath =
|
|
7657
|
+
filePath = join22(dir, "telegram-getupdates-offset-opencode.json");
|
|
7558
7658
|
} catch {
|
|
7559
7659
|
dir = null;
|
|
7560
7660
|
filePath = null;
|
|
@@ -7563,7 +7663,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7563
7663
|
load() {
|
|
7564
7664
|
if (!filePath) return 0;
|
|
7565
7665
|
try {
|
|
7566
|
-
const parsed = JSON.parse(
|
|
7666
|
+
const parsed = JSON.parse(readFileSync18(filePath, "utf-8"));
|
|
7567
7667
|
if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
|
|
7568
7668
|
log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
|
|
7569
7669
|
return 0;
|
|
@@ -7813,24 +7913,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
7813
7913
|
}
|
|
7814
7914
|
|
|
7815
7915
|
// src/lib/restart-flags.ts
|
|
7816
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as
|
|
7916
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync19, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
7817
7917
|
import { homedir as homedir10 } from "os";
|
|
7818
|
-
import { join as
|
|
7918
|
+
import { join as join23 } from "path";
|
|
7819
7919
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7820
7920
|
function restartFlagsDir() {
|
|
7821
|
-
return
|
|
7921
|
+
return join23(homedir10(), ".augmented", "restart-flags");
|
|
7822
7922
|
}
|
|
7823
7923
|
function flagPath(codeName) {
|
|
7824
|
-
return
|
|
7924
|
+
return join23(restartFlagsDir(), `${codeName}.flag`);
|
|
7825
7925
|
}
|
|
7826
7926
|
function readRestartFlags() {
|
|
7827
7927
|
const dir = restartFlagsDir();
|
|
7828
7928
|
if (!existsSync10(dir)) return [];
|
|
7829
7929
|
const out = [];
|
|
7830
|
-
for (const entry of
|
|
7930
|
+
for (const entry of readdirSync5(dir)) {
|
|
7831
7931
|
if (!entry.endsWith(".flag")) continue;
|
|
7832
7932
|
try {
|
|
7833
|
-
const raw =
|
|
7933
|
+
const raw = readFileSync19(join23(dir, entry), "utf8");
|
|
7834
7934
|
const parsed = JSON.parse(raw);
|
|
7835
7935
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
7836
7936
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -7948,8 +8048,8 @@ async function sendError(flag, opts, text) {
|
|
|
7948
8048
|
}
|
|
7949
8049
|
|
|
7950
8050
|
// src/lib/restart-context.ts
|
|
7951
|
-
import { readdirSync as
|
|
7952
|
-
import { dirname as dirname7, join as
|
|
8051
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync20, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, unlinkSync as unlinkSync3 } from "fs";
|
|
8052
|
+
import { dirname as dirname7, join as join24 } from "path";
|
|
7953
8053
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
7954
8054
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
7955
8055
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -7961,10 +8061,10 @@ function augmentedAgentDir(codeName) {
|
|
|
7961
8061
|
return dirname7(getProjectDir(codeName));
|
|
7962
8062
|
}
|
|
7963
8063
|
function slackPendingInboundDir(codeName) {
|
|
7964
|
-
return
|
|
8064
|
+
return join24(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
7965
8065
|
}
|
|
7966
8066
|
function slackRestartContextDir(codeName) {
|
|
7967
|
-
return
|
|
8067
|
+
return join24(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
7968
8068
|
}
|
|
7969
8069
|
function sanitizeTopic(raw) {
|
|
7970
8070
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -7999,14 +8099,14 @@ function computeRestartContextHints(markers, allTurns, nowMs, reconstruct = reco
|
|
|
7999
8099
|
}
|
|
8000
8100
|
function safeReaddir(dir) {
|
|
8001
8101
|
try {
|
|
8002
|
-
return
|
|
8102
|
+
return readdirSync6(dir);
|
|
8003
8103
|
} catch {
|
|
8004
8104
|
return [];
|
|
8005
8105
|
}
|
|
8006
8106
|
}
|
|
8007
8107
|
function readStrandedMarker(path) {
|
|
8008
8108
|
try {
|
|
8009
|
-
const parsed = JSON.parse(
|
|
8109
|
+
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
8010
8110
|
if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
|
|
8011
8111
|
return { channel: parsed.channel, thread_ts: parsed.thread_ts };
|
|
8012
8112
|
}
|
|
@@ -8024,7 +8124,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
8024
8124
|
if (!filename.endsWith(".json")) continue;
|
|
8025
8125
|
if (freshFilenames.has(filename)) continue;
|
|
8026
8126
|
try {
|
|
8027
|
-
unlinkSync3(
|
|
8127
|
+
unlinkSync3(join24(ctxDir, filename));
|
|
8028
8128
|
} catch {
|
|
8029
8129
|
}
|
|
8030
8130
|
}
|
|
@@ -8045,7 +8145,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8045
8145
|
}
|
|
8046
8146
|
const markers = [];
|
|
8047
8147
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
8048
|
-
const parsed = readStrandedMarker(
|
|
8148
|
+
const parsed = readStrandedMarker(join24(markerDir, filename));
|
|
8049
8149
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
8050
8150
|
}
|
|
8051
8151
|
if (markers.length === 0) {
|
|
@@ -8059,7 +8159,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
8059
8159
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
8060
8160
|
for (const { filename, hint } of hints) {
|
|
8061
8161
|
try {
|
|
8062
|
-
writeHintFile(
|
|
8162
|
+
writeHintFile(join24(ctxDir, filename), ctxDir, hint);
|
|
8063
8163
|
freshFilenames.add(filename);
|
|
8064
8164
|
} catch (err) {
|
|
8065
8165
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -9168,7 +9268,7 @@ function inboundAgeSecondsFor(codeName) {
|
|
|
9168
9268
|
}
|
|
9169
9269
|
function paneLogAgeSecondsFor(codeName) {
|
|
9170
9270
|
try {
|
|
9171
|
-
const mtimeMs =
|
|
9271
|
+
const mtimeMs = statSync6(paneLogPath(codeName)).mtimeMs;
|
|
9172
9272
|
return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
|
|
9173
9273
|
} catch (err) {
|
|
9174
9274
|
if (err?.code === "ENOENT") return null;
|
|
@@ -9290,7 +9390,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
9290
9390
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
9291
9391
|
function projectMcpHash(_codeName, projectDir) {
|
|
9292
9392
|
try {
|
|
9293
|
-
const raw =
|
|
9393
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9294
9394
|
return createHash16("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
9295
9395
|
} catch {
|
|
9296
9396
|
return null;
|
|
@@ -9298,7 +9398,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
9298
9398
|
}
|
|
9299
9399
|
function projectMcpKeys(_codeName, projectDir) {
|
|
9300
9400
|
try {
|
|
9301
|
-
const raw =
|
|
9401
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9302
9402
|
const parsed = JSON.parse(raw);
|
|
9303
9403
|
const servers = parsed.mcpServers;
|
|
9304
9404
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -9316,7 +9416,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
9316
9416
|
else runningMcpServerKeys.delete(codeName);
|
|
9317
9417
|
let launchStructure = null;
|
|
9318
9418
|
try {
|
|
9319
|
-
const raw =
|
|
9419
|
+
const raw = readFileSync21(join25(projectDir, ".mcp.json"), "utf-8");
|
|
9320
9420
|
launchStructure = managedMcpStructureHashFromFile(
|
|
9321
9421
|
JSON.parse(raw),
|
|
9322
9422
|
isManagedMcpServerKey
|
|
@@ -9420,7 +9520,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
9420
9520
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
9421
9521
|
let mcpJsonForRebind = null;
|
|
9422
9522
|
try {
|
|
9423
|
-
mcpJsonForRebind = JSON.parse(
|
|
9523
|
+
mcpJsonForRebind = JSON.parse(readFileSync21(join25(projectDir, ".mcp.json"), "utf-8"));
|
|
9424
9524
|
} catch {
|
|
9425
9525
|
mcpJsonForRebind = null;
|
|
9426
9526
|
}
|
|
@@ -9571,7 +9671,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
9571
9671
|
function projectChannelSecretHash(projectDir) {
|
|
9572
9672
|
try {
|
|
9573
9673
|
const entries = parseEnvIntegrations(
|
|
9574
|
-
|
|
9674
|
+
readFileSync21(join25(projectDir, ".env.integrations"), "utf-8")
|
|
9575
9675
|
);
|
|
9576
9676
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
9577
9677
|
} catch {
|
|
@@ -9667,7 +9767,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9667
9767
|
var lastVersionCheckAt = 0;
|
|
9668
9768
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9669
9769
|
var lastResponsivenessProbeAt = 0;
|
|
9670
|
-
var agtCliVersion = true ? "0.28.
|
|
9770
|
+
var agtCliVersion = true ? "0.28.440" : "dev";
|
|
9671
9771
|
function resolveBrewPath(execFileSync2) {
|
|
9672
9772
|
try {
|
|
9673
9773
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -9956,7 +10056,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
9956
10056
|
try {
|
|
9957
10057
|
let settings = {};
|
|
9958
10058
|
if (existsSync11(path)) {
|
|
9959
|
-
const raw =
|
|
10059
|
+
const raw = readFileSync21(path, "utf-8").trim();
|
|
9960
10060
|
if (raw) {
|
|
9961
10061
|
let parsed;
|
|
9962
10062
|
try {
|
|
@@ -10011,7 +10111,7 @@ async function ensureOpencodeBinary() {
|
|
|
10011
10111
|
try {
|
|
10012
10112
|
const prefix = execFileSync2("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
10013
10113
|
if (prefix) {
|
|
10014
|
-
const npmBin =
|
|
10114
|
+
const npmBin = join25(prefix, "bin");
|
|
10015
10115
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
10016
10116
|
if (!current.includes(npmBin)) {
|
|
10017
10117
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -10128,7 +10228,7 @@ ${r.stderr}`;
|
|
|
10128
10228
|
}
|
|
10129
10229
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
10130
10230
|
function selfUpdateAppliedMarkerPath() {
|
|
10131
|
-
return
|
|
10231
|
+
return join25(homedir11(), ".augmented", ".last-self-update-applied");
|
|
10132
10232
|
}
|
|
10133
10233
|
var selfUpdateUpToDateLogged = false;
|
|
10134
10234
|
var selfUpdatePinnedLogged = false;
|
|
@@ -10156,7 +10256,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
10156
10256
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
10157
10257
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
10158
10258
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
10159
|
-
const markerPath =
|
|
10259
|
+
const markerPath = join25(homedir11(), ".augmented", ".last-update-check");
|
|
10160
10260
|
if (!force) {
|
|
10161
10261
|
try {
|
|
10162
10262
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -10516,12 +10616,12 @@ async function checkClaudeAuth() {
|
|
|
10516
10616
|
var evalEmptyMcpConfigPath = null;
|
|
10517
10617
|
function ensureEvalEmptyMcpConfig() {
|
|
10518
10618
|
if (evalEmptyMcpConfigPath && existsSync11(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
10519
|
-
const dir =
|
|
10619
|
+
const dir = join25(homedir11(), ".augmented");
|
|
10520
10620
|
try {
|
|
10521
10621
|
mkdirSync10(dir, { recursive: true });
|
|
10522
10622
|
} catch {
|
|
10523
10623
|
}
|
|
10524
|
-
const p =
|
|
10624
|
+
const p = join25(dir, ".eval-empty-mcp.json");
|
|
10525
10625
|
writeFileSync12(p, JSON.stringify({ mcpServers: {} }));
|
|
10526
10626
|
evalEmptyMcpConfigPath = p;
|
|
10527
10627
|
return p;
|
|
@@ -10613,10 +10713,10 @@ function resolveConversationEvalBackend() {
|
|
|
10613
10713
|
return conversationEvalBackend;
|
|
10614
10714
|
}
|
|
10615
10715
|
function getStateFile() {
|
|
10616
|
-
return
|
|
10716
|
+
return join25(config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
10617
10717
|
}
|
|
10618
10718
|
function channelHashCacheDir() {
|
|
10619
|
-
return config?.configDir ??
|
|
10719
|
+
return config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
10620
10720
|
}
|
|
10621
10721
|
function loadChannelHashCache2() {
|
|
10622
10722
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -10668,7 +10768,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
10668
10768
|
var _channelQuarantineStore = null;
|
|
10669
10769
|
function channelQuarantineStore() {
|
|
10670
10770
|
if (!_channelQuarantineStore) {
|
|
10671
|
-
const dir = config?.configDir ??
|
|
10771
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
10672
10772
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
10673
10773
|
}
|
|
10674
10774
|
return _channelQuarantineStore;
|
|
@@ -10685,7 +10785,7 @@ function claudeMdSizeFor(codeName) {
|
|
|
10685
10785
|
var _hostFlagStore = null;
|
|
10686
10786
|
function hostFlagStore() {
|
|
10687
10787
|
if (!_hostFlagStore) {
|
|
10688
|
-
const dir = config?.configDir ??
|
|
10788
|
+
const dir = config?.configDir ?? join25(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
10689
10789
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
10690
10790
|
}
|
|
10691
10791
|
return _hostFlagStore;
|
|
@@ -10752,13 +10852,13 @@ function parseSkillFrontmatter(content) {
|
|
|
10752
10852
|
return out;
|
|
10753
10853
|
}
|
|
10754
10854
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
10755
|
-
const { readdirSync:
|
|
10756
|
-
const skillsDir =
|
|
10757
|
-
const claudeMdPath =
|
|
10855
|
+
const { readdirSync: readdirSync8, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync13 } = await import("fs");
|
|
10856
|
+
const skillsDir = join25(configDir, codeName, "project", ".claude", "skills");
|
|
10857
|
+
const claudeMdPath = join25(configDir, codeName, "project", "CLAUDE.md");
|
|
10758
10858
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
10759
10859
|
const entries = [];
|
|
10760
|
-
for (const dir of
|
|
10761
|
-
const skillFile =
|
|
10860
|
+
for (const dir of readdirSync8(skillsDir).sort()) {
|
|
10861
|
+
const skillFile = join25(skillsDir, dir, "SKILL.md");
|
|
10762
10862
|
if (!ex(skillFile)) continue;
|
|
10763
10863
|
try {
|
|
10764
10864
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -10825,7 +10925,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
10825
10925
|
if (codeNames.length === 0) return;
|
|
10826
10926
|
void (async () => {
|
|
10827
10927
|
try {
|
|
10828
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10928
|
+
const { collectDiagnostics } = await import("../persistent-session-4MIMM3TN.js");
|
|
10829
10929
|
await api.post("/host/heartbeat", {
|
|
10830
10930
|
host_id: hostId,
|
|
10831
10931
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -10932,7 +11032,7 @@ async function pollCycle() {
|
|
|
10932
11032
|
}
|
|
10933
11033
|
try {
|
|
10934
11034
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
10935
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11035
|
+
const { collectDiagnostics } = await import("../persistent-session-4MIMM3TN.js");
|
|
10936
11036
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
10937
11037
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
|
|
10938
11038
|
let tailscaleHostname;
|
|
@@ -11046,7 +11146,7 @@ async function pollCycle() {
|
|
|
11046
11146
|
collectResponsivenessProbes,
|
|
11047
11147
|
collectPanelessActivityProbes,
|
|
11048
11148
|
getResponsivenessIntervalMs
|
|
11049
|
-
} = await import("../responsiveness-probe-
|
|
11149
|
+
} = await import("../responsiveness-probe-5SRDBI4B.js");
|
|
11050
11150
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
11051
11151
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
11052
11152
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -11110,7 +11210,7 @@ async function pollCycle() {
|
|
|
11110
11210
|
collectResponsivenessProbes,
|
|
11111
11211
|
livePendingInboundOldestAgeSeconds,
|
|
11112
11212
|
parkPendingInbound
|
|
11113
|
-
} = await import("../responsiveness-probe-
|
|
11213
|
+
} = await import("../responsiveness-probe-5SRDBI4B.js");
|
|
11114
11214
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
11115
11215
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
11116
11216
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11199,13 +11299,13 @@ async function pollCycle() {
|
|
|
11199
11299
|
);
|
|
11200
11300
|
if (hostFlagStore().getBoolean("wedge-transient-notice")) {
|
|
11201
11301
|
try {
|
|
11202
|
-
const paneTail =
|
|
11302
|
+
const paneTail = readFileSync21(paneLogPath(codeName), "utf8").slice(-65536);
|
|
11203
11303
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
11204
11304
|
if (transient) {
|
|
11205
|
-
const wedgeHome =
|
|
11305
|
+
const wedgeHome = join25(homedir11(), ".augmented", codeName);
|
|
11206
11306
|
if (existsSync11(wedgeHome)) {
|
|
11207
11307
|
atomicWriteFileSync(
|
|
11208
|
-
|
|
11308
|
+
join25(wedgeHome, "watchdog-give-up.json"),
|
|
11209
11309
|
JSON.stringify({
|
|
11210
11310
|
gave_up_at: wedgeNow.toISOString(),
|
|
11211
11311
|
reason: "transient_overload"
|
|
@@ -11476,7 +11576,7 @@ async function pollCycle() {
|
|
|
11476
11576
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
11477
11577
|
stopAgentRuntime2(prev.codeName, "removed-from-host");
|
|
11478
11578
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
11479
|
-
const agentDir =
|
|
11579
|
+
const agentDir = join25(adapter.getAgentDir(prev.codeName), "provision");
|
|
11480
11580
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
11481
11581
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
11482
11582
|
}
|
|
@@ -11563,10 +11663,10 @@ async function pollCycle() {
|
|
|
11563
11663
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
11564
11664
|
// the watchdog, never fails the poll cycle.
|
|
11565
11665
|
signalGiveUp: (codeName) => {
|
|
11566
|
-
const dir =
|
|
11666
|
+
const dir = join25(homedir11(), ".augmented", codeName);
|
|
11567
11667
|
if (!existsSync11(dir)) return;
|
|
11568
11668
|
atomicWriteFileSync(
|
|
11569
|
-
|
|
11669
|
+
join25(dir, "watchdog-give-up.json"),
|
|
11570
11670
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
11571
11671
|
);
|
|
11572
11672
|
}
|
|
@@ -11706,7 +11806,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11706
11806
|
}
|
|
11707
11807
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11708
11808
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
11709
|
-
let agentDir =
|
|
11809
|
+
let agentDir = join25(adapter.getAgentDir(agent.code_name), "provision");
|
|
11710
11810
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
11711
11811
|
if (previousKnownStatus !== agent.status) {
|
|
11712
11812
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -11879,7 +11979,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11879
11979
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
11880
11980
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
11881
11981
|
const frameworkAdapter = getFramework(frameworkId);
|
|
11882
|
-
agentDir =
|
|
11982
|
+
agentDir = join25(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
11883
11983
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
11884
11984
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
11885
11985
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -11928,7 +12028,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11928
12028
|
const changedFiles = [];
|
|
11929
12029
|
mkdirSync10(agentDir, { recursive: true });
|
|
11930
12030
|
for (const artifact of artifacts) {
|
|
11931
|
-
const filePath =
|
|
12031
|
+
const filePath = join25(agentDir, artifact.relativePath);
|
|
11932
12032
|
let existingHash;
|
|
11933
12033
|
let newHash;
|
|
11934
12034
|
let writeContent = artifact.content;
|
|
@@ -11947,8 +12047,8 @@ async function processAgent(agent, agentStates) {
|
|
|
11947
12047
|
};
|
|
11948
12048
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
11949
12049
|
try {
|
|
11950
|
-
const projectClaudeMd =
|
|
11951
|
-
const existing =
|
|
12050
|
+
const projectClaudeMd = join25(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
12051
|
+
const existing = readFileSync21(projectClaudeMd, "utf-8");
|
|
11952
12052
|
existingHash = sha256(stripDynamicSections(existing));
|
|
11953
12053
|
} catch {
|
|
11954
12054
|
existingHash = null;
|
|
@@ -11966,7 +12066,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11966
12066
|
const generatorKeys = Object.keys(generatorServers);
|
|
11967
12067
|
let existingRaw = "";
|
|
11968
12068
|
try {
|
|
11969
|
-
existingRaw =
|
|
12069
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
11970
12070
|
} catch {
|
|
11971
12071
|
}
|
|
11972
12072
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -11982,7 +12082,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11982
12082
|
} else if (artifact.relativePath === "opencode.json") {
|
|
11983
12083
|
let existingRaw = null;
|
|
11984
12084
|
try {
|
|
11985
|
-
existingRaw =
|
|
12085
|
+
existingRaw = readFileSync21(filePath, "utf-8");
|
|
11986
12086
|
} catch {
|
|
11987
12087
|
}
|
|
11988
12088
|
const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
|
|
@@ -11998,12 +12098,12 @@ async function processAgent(agent, agentStates) {
|
|
|
11998
12098
|
}
|
|
11999
12099
|
}
|
|
12000
12100
|
if (changedFiles.length > 0) {
|
|
12001
|
-
const isFirst = !existsSync11(
|
|
12101
|
+
const isFirst = !existsSync11(join25(agentDir, "CHARTER.md"));
|
|
12002
12102
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
12003
12103
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
12004
12104
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
12005
12105
|
for (const file of changedFiles) {
|
|
12006
|
-
const filePath =
|
|
12106
|
+
const filePath = join25(agentDir, file.relativePath);
|
|
12007
12107
|
mkdirSync10(dirname8(filePath), { recursive: true });
|
|
12008
12108
|
if (file.relativePath === ".mcp.json") {
|
|
12009
12109
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
@@ -12012,12 +12112,12 @@ async function processAgent(agent, agentStates) {
|
|
|
12012
12112
|
}
|
|
12013
12113
|
}
|
|
12014
12114
|
try {
|
|
12015
|
-
const provSkillsDir =
|
|
12115
|
+
const provSkillsDir = join25(agentDir, ".claude", "skills");
|
|
12016
12116
|
if (existsSync11(provSkillsDir)) {
|
|
12017
|
-
for (const folder of
|
|
12117
|
+
for (const folder of readdirSync7(provSkillsDir)) {
|
|
12018
12118
|
if (folder.startsWith("knowledge-")) {
|
|
12019
12119
|
try {
|
|
12020
|
-
rmSync5(
|
|
12120
|
+
rmSync5(join25(provSkillsDir, folder), { recursive: true });
|
|
12021
12121
|
} catch {
|
|
12022
12122
|
}
|
|
12023
12123
|
}
|
|
@@ -12030,7 +12130,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12030
12130
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
12031
12131
|
const hashes = /* @__PURE__ */ new Map();
|
|
12032
12132
|
for (const file of trackedFiles2) {
|
|
12033
|
-
const h = hashFile(
|
|
12133
|
+
const h = hashFile(join25(agentDir, file));
|
|
12034
12134
|
if (h) hashes.set(file, h);
|
|
12035
12135
|
}
|
|
12036
12136
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -12048,14 +12148,14 @@ async function processAgent(agent, agentStates) {
|
|
|
12048
12148
|
}
|
|
12049
12149
|
if (Array.isArray(refreshData.workflows)) {
|
|
12050
12150
|
try {
|
|
12051
|
-
const provWorkflowsDir =
|
|
12151
|
+
const provWorkflowsDir = join25(agentDir, ".claude", "workflows");
|
|
12052
12152
|
if (existsSync11(provWorkflowsDir)) {
|
|
12053
12153
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
12054
|
-
for (const file of
|
|
12154
|
+
for (const file of readdirSync7(provWorkflowsDir)) {
|
|
12055
12155
|
if (!file.endsWith(".js")) continue;
|
|
12056
12156
|
if (expected.has(file)) continue;
|
|
12057
12157
|
try {
|
|
12058
|
-
rmSync5(
|
|
12158
|
+
rmSync5(join25(provWorkflowsDir, file));
|
|
12059
12159
|
} catch {
|
|
12060
12160
|
}
|
|
12061
12161
|
}
|
|
@@ -12137,7 +12237,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12137
12237
|
if (written && existsSync11(agentDir)) {
|
|
12138
12238
|
const driftedFiles = [];
|
|
12139
12239
|
for (const [file, expectedHash] of written) {
|
|
12140
|
-
const localHash = hashFile(
|
|
12240
|
+
const localHash = hashFile(join25(agentDir, file));
|
|
12141
12241
|
if (localHash && localHash !== expectedHash) {
|
|
12142
12242
|
driftedFiles.push(file);
|
|
12143
12243
|
}
|
|
@@ -12148,7 +12248,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12148
12248
|
try {
|
|
12149
12249
|
const localHashes = {};
|
|
12150
12250
|
for (const file of driftedFiles) {
|
|
12151
|
-
localHashes[file] = hashFile(
|
|
12251
|
+
localHashes[file] = hashFile(join25(agentDir, file));
|
|
12152
12252
|
}
|
|
12153
12253
|
await api.post("/host/drift", {
|
|
12154
12254
|
agent_id: agent.agent_id,
|
|
@@ -12335,7 +12435,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12335
12435
|
const addedChannels = [...restartDecision.added];
|
|
12336
12436
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
12337
12437
|
try {
|
|
12338
|
-
const agentAugmentedDir =
|
|
12438
|
+
const agentAugmentedDir = join25(homedir11(), ".augmented", agent.code_name);
|
|
12339
12439
|
mkdirSync10(agentAugmentedDir, { recursive: true });
|
|
12340
12440
|
const markerJson = JSON.stringify({
|
|
12341
12441
|
version: 1,
|
|
@@ -12343,7 +12443,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12343
12443
|
added: addedChannels
|
|
12344
12444
|
});
|
|
12345
12445
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
12346
|
-
atomicWriteFileSync(
|
|
12446
|
+
atomicWriteFileSync(join25(agentAugmentedDir, file), markerJson);
|
|
12347
12447
|
}
|
|
12348
12448
|
} catch (err) {
|
|
12349
12449
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -12532,18 +12632,18 @@ async function processAgent(agent, agentStates) {
|
|
|
12532
12632
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
12533
12633
|
try {
|
|
12534
12634
|
const agentProvisionDir = agentDir;
|
|
12535
|
-
const projectDir =
|
|
12635
|
+
const projectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
12536
12636
|
mkdirSync10(agentProvisionDir, { recursive: true });
|
|
12537
12637
|
mkdirSync10(projectDir, { recursive: true });
|
|
12538
|
-
const provisionMcpPath =
|
|
12539
|
-
const projectMcpPath =
|
|
12638
|
+
const provisionMcpPath = join25(agentProvisionDir, ".mcp.json");
|
|
12639
|
+
const projectMcpPath = join25(projectDir, ".mcp.json");
|
|
12540
12640
|
let mcpConfig = { mcpServers: {} };
|
|
12541
12641
|
try {
|
|
12542
|
-
mcpConfig = JSON.parse(
|
|
12642
|
+
mcpConfig = JSON.parse(readFileSync21(provisionMcpPath, "utf-8"));
|
|
12543
12643
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
12544
12644
|
} catch {
|
|
12545
12645
|
}
|
|
12546
|
-
const localDirectChatChannel =
|
|
12646
|
+
const localDirectChatChannel = join25(homedir11(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
12547
12647
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
12548
12648
|
const directChatTz = (() => {
|
|
12549
12649
|
const tz = directChatTeamSettings?.["timezone"];
|
|
@@ -12569,7 +12669,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12569
12669
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
12570
12670
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
12571
12671
|
// so it byte-matches the broker readers' path.
|
|
12572
|
-
AGT_TURN_INITIATOR_FILE:
|
|
12672
|
+
AGT_TURN_INITIATOR_FILE: join25(
|
|
12573
12673
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
12574
12674
|
".current-turn-initiator.json"
|
|
12575
12675
|
)
|
|
@@ -12589,7 +12689,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12589
12689
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
12590
12690
|
}
|
|
12591
12691
|
}
|
|
12592
|
-
const staleChannelsPath =
|
|
12692
|
+
const staleChannelsPath = join25(projectDir, ".mcp-channels.json");
|
|
12593
12693
|
if (existsSync11(staleChannelsPath)) {
|
|
12594
12694
|
try {
|
|
12595
12695
|
rmSync5(staleChannelsPath, { force: true });
|
|
@@ -12679,7 +12779,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12679
12779
|
}
|
|
12680
12780
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
12681
12781
|
try {
|
|
12682
|
-
const probeProjectDir =
|
|
12782
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
12683
12783
|
let probeSet = integrations;
|
|
12684
12784
|
try {
|
|
12685
12785
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -12725,7 +12825,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12725
12825
|
const forceDue = attemptsLeft > 0;
|
|
12726
12826
|
let probeRan = false;
|
|
12727
12827
|
try {
|
|
12728
|
-
const probeProjectDir =
|
|
12828
|
+
const probeProjectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
12729
12829
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
12730
12830
|
} catch (err) {
|
|
12731
12831
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -12800,11 +12900,11 @@ async function processAgent(agent, agentStates) {
|
|
|
12800
12900
|
const intHash = computeIntegrationsHash(integrations);
|
|
12801
12901
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
12802
12902
|
if (intHash !== prevIntHash) {
|
|
12803
|
-
const projectDir =
|
|
12804
|
-
const envIntPath =
|
|
12903
|
+
const projectDir = join25(homedir11(), ".augmented", agent.code_name, "project");
|
|
12904
|
+
const envIntPath = join25(projectDir, ".env.integrations");
|
|
12805
12905
|
let preWriteEnv;
|
|
12806
12906
|
try {
|
|
12807
|
-
preWriteEnv =
|
|
12907
|
+
preWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
12808
12908
|
} catch {
|
|
12809
12909
|
preWriteEnv = void 0;
|
|
12810
12910
|
}
|
|
@@ -12821,9 +12921,9 @@ async function processAgent(agent, agentStates) {
|
|
|
12821
12921
|
}
|
|
12822
12922
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
12823
12923
|
try {
|
|
12824
|
-
const projectMcpPath =
|
|
12825
|
-
const postWriteEnv =
|
|
12826
|
-
const mcpContent =
|
|
12924
|
+
const projectMcpPath = join25(projectDir, ".mcp.json");
|
|
12925
|
+
const postWriteEnv = readFileSync21(envIntPath, "utf-8");
|
|
12926
|
+
const mcpContent = readFileSync21(projectMcpPath, "utf-8");
|
|
12827
12927
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
12828
12928
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
12829
12929
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -13069,23 +13169,23 @@ async function processAgent(agent, agentStates) {
|
|
|
13069
13169
|
}
|
|
13070
13170
|
}
|
|
13071
13171
|
try {
|
|
13072
|
-
const { readdirSync:
|
|
13172
|
+
const { readdirSync: readdirSync8, rmSync: rmSync6 } = await import("fs");
|
|
13073
13173
|
const { homedir: homedir12 } = await import("os");
|
|
13074
13174
|
const frameworkId2 = frameworkAdapter.id;
|
|
13075
13175
|
const candidateSkillDirs = [
|
|
13076
13176
|
// Claude Code — framework runtime tree
|
|
13077
|
-
|
|
13177
|
+
join25(homedir12(), ".augmented", agent.code_name, "skills"),
|
|
13078
13178
|
// Claude Code — project tree
|
|
13079
|
-
|
|
13179
|
+
join25(homedir12(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13080
13180
|
// Defensive: legacy provision-side path, not currently an
|
|
13081
13181
|
// install target but cheap to sweep.
|
|
13082
|
-
|
|
13182
|
+
join25(agentDir, ".claude", "skills")
|
|
13083
13183
|
];
|
|
13084
13184
|
const existingDirs = candidateSkillDirs.filter((d) => existsSync11(d));
|
|
13085
13185
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
13086
13186
|
for (const dir of existingDirs) {
|
|
13087
13187
|
try {
|
|
13088
|
-
for (const entry of
|
|
13188
|
+
for (const entry of readdirSync8(dir)) {
|
|
13089
13189
|
if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
|
|
13090
13190
|
discoveredEntries.add(entry);
|
|
13091
13191
|
}
|
|
@@ -13095,7 +13195,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13095
13195
|
}
|
|
13096
13196
|
const removeSkillFolder = (entry, reason) => {
|
|
13097
13197
|
for (const dir of existingDirs) {
|
|
13098
|
-
const p =
|
|
13198
|
+
const p = join25(dir, entry);
|
|
13099
13199
|
if (existsSync11(p)) {
|
|
13100
13200
|
rmSync6(p, { recursive: true, force: true });
|
|
13101
13201
|
}
|
|
@@ -13115,7 +13215,7 @@ async function processAgent(agent, agentStates) {
|
|
|
13115
13215
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
13116
13216
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
13117
13217
|
const manifestPath = managedSkillManifestPath(
|
|
13118
|
-
|
|
13218
|
+
join25(homedir11(), ".augmented", agent.code_name)
|
|
13119
13219
|
);
|
|
13120
13220
|
const prevIds = /* @__PURE__ */ new Set([
|
|
13121
13221
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -13135,15 +13235,15 @@ async function processAgent(agent, agentStates) {
|
|
|
13135
13235
|
}
|
|
13136
13236
|
if (plan.removes.length) {
|
|
13137
13237
|
const globalSkillDirs = [
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13238
|
+
join25(homedir11(), ".augmented", agent.code_name, "skills"),
|
|
13239
|
+
join25(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
13240
|
+
join25(agentDir, ".claude", "skills")
|
|
13141
13241
|
];
|
|
13142
13242
|
for (const id of plan.removes) {
|
|
13143
13243
|
let prunedAny = false;
|
|
13144
13244
|
for (const dir of globalSkillDirs) {
|
|
13145
|
-
const p =
|
|
13146
|
-
if (existsSync11(p) && existsSync11(
|
|
13245
|
+
const p = join25(dir, id);
|
|
13246
|
+
if (existsSync11(p) && existsSync11(join25(p, "SKILL.md"))) {
|
|
13147
13247
|
rmSync5(p, { recursive: true, force: true });
|
|
13148
13248
|
prunedAny = true;
|
|
13149
13249
|
}
|
|
@@ -13291,12 +13391,21 @@ async function processAgent(agent, agentStates) {
|
|
|
13291
13391
|
);
|
|
13292
13392
|
}
|
|
13293
13393
|
} else if (nudgeAction === "nudge") {
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
agent.
|
|
13297
|
-
|
|
13298
|
-
|
|
13299
|
-
|
|
13394
|
+
const tickLimitedUntil = readUsageLimitUntil({ codeName: agent.code_name });
|
|
13395
|
+
if (tickLimitedUntil) {
|
|
13396
|
+
if (shouldLogUsageCapDeferral("kanban-tick", agent.code_name, tickLimitedUntil)) {
|
|
13397
|
+
log(
|
|
13398
|
+
`[manager-worker] kanban inject skipped for '${agent.code_name}' - agent is at its Claude usage limit until ${tickLimitedUntil.toISOString()} (${allowed.length} actionable card(s) left on the board); further skips this window are not logged`
|
|
13399
|
+
);
|
|
13400
|
+
}
|
|
13401
|
+
} else {
|
|
13402
|
+
void maybeInjectKanbanCheck(
|
|
13403
|
+
agent.code_name,
|
|
13404
|
+
agent.agent_id,
|
|
13405
|
+
allowed.length,
|
|
13406
|
+
kanbanActionableSignature(allowed)
|
|
13407
|
+
);
|
|
13408
|
+
}
|
|
13300
13409
|
} else if (nudgeAction === "close-suppressed") {
|
|
13301
13410
|
closeInjectedRunIfOpen(
|
|
13302
13411
|
agent.code_name,
|
|
@@ -13362,8 +13471,8 @@ async function processAgent(agent, agentStates) {
|
|
|
13362
13471
|
const sess = getSessionState(agent.code_name);
|
|
13363
13472
|
let mcpJsonParsed = null;
|
|
13364
13473
|
try {
|
|
13365
|
-
const mcpPath =
|
|
13366
|
-
mcpJsonParsed = JSON.parse(
|
|
13474
|
+
const mcpPath = join25(getProjectDir(agent.code_name), ".mcp.json");
|
|
13475
|
+
mcpJsonParsed = JSON.parse(readFileSync21(mcpPath, "utf-8"));
|
|
13367
13476
|
} catch {
|
|
13368
13477
|
}
|
|
13369
13478
|
reapMissingMcpSessions({
|
|
@@ -13728,7 +13837,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
13728
13837
|
if (trackedFiles.length > 0 && existsSync11(agentDir)) {
|
|
13729
13838
|
const hashes = /* @__PURE__ */ new Map();
|
|
13730
13839
|
for (const file of trackedFiles) {
|
|
13731
|
-
const h = hashFile(
|
|
13840
|
+
const h = hashFile(join25(agentDir, file));
|
|
13732
13841
|
if (h) hashes.set(file, h);
|
|
13733
13842
|
}
|
|
13734
13843
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -13743,7 +13852,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
13743
13852
|
refreshData.agent.onboarding_state
|
|
13744
13853
|
);
|
|
13745
13854
|
const obStep = obState.step;
|
|
13746
|
-
const markerPath =
|
|
13855
|
+
const markerPath = join25(homedir11(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
13747
13856
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
13748
13857
|
const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
|
|
13749
13858
|
if (decision.clearMarker) {
|
|
@@ -13831,7 +13940,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
13831
13940
|
}
|
|
13832
13941
|
stopOpencodeSlackIngest(codeName, log);
|
|
13833
13942
|
stopOpencodeTelegramIngest(codeName, log);
|
|
13834
|
-
const opencodeProjectDir =
|
|
13943
|
+
const opencodeProjectDir = join25(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
13835
13944
|
const serveEnv = {
|
|
13836
13945
|
AGT_HOST: requireHost(),
|
|
13837
13946
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -13874,8 +13983,8 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
13874
13983
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
13875
13984
|
const codeName = agent.code_name;
|
|
13876
13985
|
const projectDir = getProjectDir(codeName);
|
|
13877
|
-
const mcpConfigPath =
|
|
13878
|
-
const claudeMdPath =
|
|
13986
|
+
const mcpConfigPath = join25(projectDir, ".mcp.json");
|
|
13987
|
+
const claudeMdPath = join25(projectDir, "CLAUDE.md");
|
|
13879
13988
|
if (restartBreaker.isTripped(codeName)) {
|
|
13880
13989
|
const trip = restartBreaker.getTrip(codeName);
|
|
13881
13990
|
return {
|
|
@@ -14217,7 +14326,19 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
|
|
|
14217
14326
|
if (ready.length > 0) {
|
|
14218
14327
|
log(`[persistent-session] ${ready.length} ready task(s) for '${codeName}': ${ready.map((t) => `${t.name}(next=${t.nextFireAt ? new Date(t.nextFireAt).toISOString() : "null"})`).join(", ")}`);
|
|
14219
14328
|
}
|
|
14220
|
-
|
|
14329
|
+
let deferReadyForUsageCap = false;
|
|
14330
|
+
if (ready.length > 0) {
|
|
14331
|
+
const schedLimitedUntil = readUsageLimitUntil({ codeName });
|
|
14332
|
+
if (schedLimitedUntil) {
|
|
14333
|
+
if (shouldLogUsageCapDeferral("persistent-scheduler", codeName, schedLimitedUntil)) {
|
|
14334
|
+
log(
|
|
14335
|
+
`[persistent-session] Deferring ${ready.length} ready task(s) for '${codeName}' \u2014 agent is at its Claude usage limit until ${schedLimitedUntil.toISOString()}; schedule NOT advanced, will fire after the limit resets (further deferrals this window are not logged)`
|
|
14336
|
+
);
|
|
14337
|
+
}
|
|
14338
|
+
deferReadyForUsageCap = true;
|
|
14339
|
+
}
|
|
14340
|
+
}
|
|
14341
|
+
for (const task of deferReadyForUsageCap ? [] : ready) {
|
|
14221
14342
|
if (KANBAN_WORK_TEMPLATES.has(task.templateId)) {
|
|
14222
14343
|
const updated = markTaskFired(codeName, task.taskId, "ok");
|
|
14223
14344
|
claudeSchedulerStates.set(codeName, updated);
|
|
@@ -14428,7 +14549,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
14428
14549
|
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}`));
|
|
14429
14550
|
void (async () => {
|
|
14430
14551
|
try {
|
|
14431
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14552
|
+
const { collectDiagnostics } = await import("../persistent-session-4MIMM3TN.js");
|
|
14432
14553
|
await api.post("/host/heartbeat", {
|
|
14433
14554
|
host_id: hostId,
|
|
14434
14555
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -14478,7 +14599,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
14478
14599
|
}
|
|
14479
14600
|
try {
|
|
14480
14601
|
const hostId = await getHostId();
|
|
14481
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14602
|
+
const { collectDiagnostics } = await import("../persistent-session-4MIMM3TN.js");
|
|
14482
14603
|
await api.post("/host/heartbeat", {
|
|
14483
14604
|
host_id: hostId,
|
|
14484
14605
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -14931,7 +15052,7 @@ async function processClaudePairSessions(agents) {
|
|
|
14931
15052
|
killPairSession,
|
|
14932
15053
|
pairTmuxSession,
|
|
14933
15054
|
finalizeClaudePairOnboarding
|
|
14934
|
-
} = await import("../claude-pair-runtime-
|
|
15055
|
+
} = await import("../claude-pair-runtime-Z4DP2IQA.js");
|
|
14935
15056
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
14936
15057
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
14937
15058
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -15181,8 +15302,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
15181
15302
|
};
|
|
15182
15303
|
}
|
|
15183
15304
|
async function syncMemories(agent, configDir, log2) {
|
|
15184
|
-
const projectDir =
|
|
15185
|
-
const memoryDir =
|
|
15305
|
+
const projectDir = join25(configDir, agent.code_name, "project");
|
|
15306
|
+
const memoryDir = join25(projectDir, "memory");
|
|
15186
15307
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
15187
15308
|
if (isFreshSync) {
|
|
15188
15309
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -15197,10 +15318,10 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15197
15318
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
15198
15319
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
15199
15320
|
const changedMemories = [];
|
|
15200
|
-
for (const file of
|
|
15321
|
+
for (const file of readdirSync7(memoryDir)) {
|
|
15201
15322
|
if (!file.endsWith(".md")) continue;
|
|
15202
15323
|
try {
|
|
15203
|
-
const raw =
|
|
15324
|
+
const raw = readFileSync21(join25(memoryDir, file), "utf-8");
|
|
15204
15325
|
const fileHash = createHash16("sha256").update(raw).digest("hex").slice(0, 16);
|
|
15205
15326
|
currentHashes.set(file, fileHash);
|
|
15206
15327
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -15225,7 +15346,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15225
15346
|
} catch (err) {
|
|
15226
15347
|
for (const mem of changedMemories) {
|
|
15227
15348
|
for (const [file] of currentHashes) {
|
|
15228
|
-
const parsed = parseMemoryFile(
|
|
15349
|
+
const parsed = parseMemoryFile(readFileSync21(join25(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
15229
15350
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
15230
15351
|
}
|
|
15231
15352
|
}
|
|
@@ -15238,7 +15359,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
15238
15359
|
}
|
|
15239
15360
|
}
|
|
15240
15361
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
15241
|
-
const localFiles = existsSync11(memoryDir) ?
|
|
15362
|
+
const localFiles = existsSync11(memoryDir) ? readdirSync7(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
15242
15363
|
const localListHash = createHash16("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
15243
15364
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
15244
15365
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
@@ -15260,7 +15381,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
|
15260
15381
|
const mem = dbMemories.memories[i];
|
|
15261
15382
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
15262
15383
|
const slug = rawSlug || `memory-${i}`;
|
|
15263
|
-
const filePath =
|
|
15384
|
+
const filePath = join25(memoryDir, `${slug}.md`);
|
|
15264
15385
|
const desired = `---
|
|
15265
15386
|
name: ${JSON.stringify(mem.name)}
|
|
15266
15387
|
type: ${mem.type}
|
|
@@ -15272,7 +15393,7 @@ ${mem.content}
|
|
|
15272
15393
|
if (existsSync11(filePath)) {
|
|
15273
15394
|
let existing = "";
|
|
15274
15395
|
try {
|
|
15275
|
-
existing =
|
|
15396
|
+
existing = readFileSync21(filePath, "utf-8");
|
|
15276
15397
|
} catch {
|
|
15277
15398
|
}
|
|
15278
15399
|
if (existing === desired) continue;
|
|
@@ -15284,7 +15405,7 @@ ${mem.content}
|
|
|
15284
15405
|
}
|
|
15285
15406
|
}
|
|
15286
15407
|
if (written > 0 || overwritten > 0) {
|
|
15287
|
-
const updatedFiles =
|
|
15408
|
+
const updatedFiles = readdirSync7(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
15288
15409
|
lastLocalFileHash.set(agent.agent_id, createHash16("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
15289
15410
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
15290
15411
|
}
|
|
@@ -15536,7 +15657,7 @@ function startManager(opts) {
|
|
|
15536
15657
|
try {
|
|
15537
15658
|
const stateFile = getStateFile();
|
|
15538
15659
|
if (existsSync11(stateFile)) {
|
|
15539
|
-
const raw =
|
|
15660
|
+
const raw = readFileSync21(stateFile, "utf-8");
|
|
15540
15661
|
const parsed = JSON.parse(raw);
|
|
15541
15662
|
if (Array.isArray(parsed.agents)) {
|
|
15542
15663
|
state6.agents = parsed.agents;
|
|
@@ -15563,7 +15684,7 @@ function startManager(opts) {
|
|
|
15563
15684
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
15564
15685
|
}
|
|
15565
15686
|
log(
|
|
15566
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
15687
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join25(homedir11(), ".augmented", "manager.log")}`
|
|
15567
15688
|
);
|
|
15568
15689
|
deployMcpAssets();
|
|
15569
15690
|
reapOrphanChannelMcps({ log });
|
|
@@ -15592,7 +15713,7 @@ async function reapOrphanedClaudePids() {
|
|
|
15592
15713
|
const looksLikeClaude = (pid) => {
|
|
15593
15714
|
if (process.platform !== "linux") return true;
|
|
15594
15715
|
try {
|
|
15595
|
-
const comm =
|
|
15716
|
+
const comm = readFileSync21(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
15596
15717
|
return comm.includes("claude");
|
|
15597
15718
|
} catch {
|
|
15598
15719
|
return false;
|
|
@@ -15689,14 +15810,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
15689
15810
|
}
|
|
15690
15811
|
}
|
|
15691
15812
|
function deployMcpAssets() {
|
|
15692
|
-
const targetDir =
|
|
15813
|
+
const targetDir = join25(homedir11(), ".augmented", "_mcp");
|
|
15693
15814
|
mkdirSync10(targetDir, { recursive: true });
|
|
15694
15815
|
const moduleDir = dirname8(fileURLToPath(import.meta.url));
|
|
15695
15816
|
let mcpSourceDir = "";
|
|
15696
15817
|
let dir = moduleDir;
|
|
15697
15818
|
for (let i = 0; i < 6; i++) {
|
|
15698
|
-
const candidate =
|
|
15699
|
-
if (existsSync11(
|
|
15819
|
+
const candidate = join25(dir, "dist", "mcp");
|
|
15820
|
+
if (existsSync11(join25(candidate, "index.js"))) {
|
|
15700
15821
|
mcpSourceDir = candidate;
|
|
15701
15822
|
break;
|
|
15702
15823
|
}
|
|
@@ -15712,7 +15833,7 @@ function deployMcpAssets() {
|
|
|
15712
15833
|
const fileHash = (p) => {
|
|
15713
15834
|
try {
|
|
15714
15835
|
if (!existsSync11(p)) return null;
|
|
15715
|
-
return createHash16("sha256").update(
|
|
15836
|
+
return createHash16("sha256").update(readFileSync21(p)).digest("hex");
|
|
15716
15837
|
} catch {
|
|
15717
15838
|
return null;
|
|
15718
15839
|
}
|
|
@@ -15776,8 +15897,8 @@ function deployMcpAssets() {
|
|
|
15776
15897
|
// needs restarting to pick up a token rotation.
|
|
15777
15898
|
"xero.js"
|
|
15778
15899
|
]) {
|
|
15779
|
-
const src =
|
|
15780
|
-
const dst =
|
|
15900
|
+
const src = join25(mcpSourceDir, file);
|
|
15901
|
+
const dst = join25(targetDir, file);
|
|
15781
15902
|
if (!existsSync11(src)) continue;
|
|
15782
15903
|
const before = fileHash(dst);
|
|
15783
15904
|
try {
|
|
@@ -15795,16 +15916,16 @@ function deployMcpAssets() {
|
|
|
15795
15916
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
15796
15917
|
restartRunningChannelMcps(changedBasenames);
|
|
15797
15918
|
}
|
|
15798
|
-
const localMcpPath =
|
|
15919
|
+
const localMcpPath = join25(targetDir, "index.js");
|
|
15799
15920
|
try {
|
|
15800
|
-
const agentsDir =
|
|
15921
|
+
const agentsDir = join25(homedir11(), ".augmented", "agents");
|
|
15801
15922
|
if (existsSync11(agentsDir)) {
|
|
15802
|
-
for (const entry of
|
|
15923
|
+
for (const entry of readdirSync7(agentsDir, { withFileTypes: true })) {
|
|
15803
15924
|
if (!entry.isDirectory()) continue;
|
|
15804
15925
|
for (const subdir of ["provision", "project"]) {
|
|
15805
|
-
const mcpJsonPath =
|
|
15926
|
+
const mcpJsonPath = join25(agentsDir, entry.name, subdir, ".mcp.json");
|
|
15806
15927
|
try {
|
|
15807
|
-
const raw =
|
|
15928
|
+
const raw = readFileSync21(mcpJsonPath, "utf-8");
|
|
15808
15929
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
15809
15930
|
const mcpConfig = JSON.parse(raw);
|
|
15810
15931
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|