@integrity-labs/agt-cli 0.28.1047 → 0.28.1048
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +5 -5
- package/dist/{chunk-2DUVDY2Y.js → chunk-4BOPLS65.js} +4 -4
- package/dist/{chunk-5GCYYWKW.js → chunk-APAEM42J.js} +141 -11
- package/dist/chunk-APAEM42J.js.map +1 -0
- package/dist/{chunk-QGUJSDN3.js → chunk-QGGDQMWF.js} +2 -2
- package/dist/{claude-pair-runtime-TOHT7XVN.js → claude-pair-runtime-KWN4XZ2H.js} +2 -2
- package/dist/lib/manager-worker.js +497 -378
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +10 -0
- package/dist/mcp/index.js +10 -0
- package/dist/mcp/origami.js +10 -0
- package/dist/mcp/slack-channel.js +10 -0
- package/dist/mcp/telegram-channel.js +10 -0
- package/dist/{persistent-session-X3C3R22F.js → persistent-session-OSQVHP6N.js} +3 -3
- package/dist/{responsiveness-probe-E23YHRUT.js → responsiveness-probe-BFDPJWZE.js} +3 -3
- package/dist/{session-auth-dead-WCUXKBHP.js → session-auth-dead-A3WD2YRK.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5GCYYWKW.js.map +0 -1
- /package/dist/{chunk-2DUVDY2Y.js.map → chunk-4BOPLS65.js.map} +0 -0
- /package/dist/{chunk-QGUJSDN3.js.map → chunk-QGGDQMWF.js.map} +0 -0
- /package/dist/{claude-pair-runtime-TOHT7XVN.js.map → claude-pair-runtime-KWN4XZ2H.js.map} +0 -0
- /package/dist/{persistent-session-X3C3R22F.js.map → persistent-session-OSQVHP6N.js.map} +0 -0
- /package/dist/{responsiveness-probe-E23YHRUT.js.map → responsiveness-probe-BFDPJWZE.js.map} +0 -0
- /package/dist/{session-auth-dead-WCUXKBHP.js.map → session-auth-dead-A3WD2YRK.js.map} +0 -0
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
safeWriteJsonAtomic,
|
|
67
67
|
setConfigHash,
|
|
68
68
|
tripClass
|
|
69
|
-
} from "../chunk-
|
|
69
|
+
} from "../chunk-4BOPLS65.js";
|
|
70
70
|
import {
|
|
71
71
|
getProjectDir as getProjectDir2,
|
|
72
72
|
getReadyTasks,
|
|
@@ -149,7 +149,7 @@ import {
|
|
|
149
149
|
takeZombieDetection,
|
|
150
150
|
toOpencodeModel,
|
|
151
151
|
writeEgressAllowlist
|
|
152
|
-
} from "../chunk-
|
|
152
|
+
} from "../chunk-QGGDQMWF.js";
|
|
153
153
|
import {
|
|
154
154
|
ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
|
|
155
155
|
AnchorSessionClient,
|
|
@@ -160,6 +160,8 @@ import {
|
|
|
160
160
|
DEFAULT_FRAMEWORK,
|
|
161
161
|
DEFAULT_NEIGHBOURHOOD_MS,
|
|
162
162
|
EXTRACTOR_IDENTIFIER_RULE,
|
|
163
|
+
FAILING_TURN_DEFAULT_MAX_TURN_MS,
|
|
164
|
+
FAILING_TURN_RUN_DEFAULT_THRESHOLD,
|
|
163
165
|
FLAGS_SCHEMA_VERSION,
|
|
164
166
|
FLAG_REGISTRY,
|
|
165
167
|
FORCED_UPDATE_HARD_DEADLINE_MS,
|
|
@@ -171,6 +173,7 @@ import {
|
|
|
171
173
|
KANBAN_CHECK_COMMAND,
|
|
172
174
|
KANBAN_NUDGE_ACTIONABLE_STATUSES,
|
|
173
175
|
MAX_AVATAR_ENV_URL_BYTES,
|
|
176
|
+
NO_FAILING_TURN_RUN,
|
|
174
177
|
SCHEDULED_TURN_MARKER_FILENAME,
|
|
175
178
|
SKILLS_INDEX_SECTION_END,
|
|
176
179
|
SKILLS_INDEX_SECTION_START,
|
|
@@ -179,6 +182,7 @@ import {
|
|
|
179
182
|
UNKNOWN_RATE_LIMIT,
|
|
180
183
|
agentHasRules,
|
|
181
184
|
agentRulesRestartBasis,
|
|
185
|
+
analyzeFailingTurnRun,
|
|
182
186
|
appendDmFooter,
|
|
183
187
|
attributeTranscriptUsageByRun,
|
|
184
188
|
bannerRemedyFor,
|
|
@@ -254,7 +258,7 @@ import {
|
|
|
254
258
|
subagentActivityAgeSeconds,
|
|
255
259
|
sumTranscriptUsageInWindow,
|
|
256
260
|
transcriptActivityAgeSeconds
|
|
257
|
-
} from "../chunk-
|
|
261
|
+
} from "../chunk-APAEM42J.js";
|
|
258
262
|
import {
|
|
259
263
|
classifyUnanswerablePane,
|
|
260
264
|
paneRemedy
|
|
@@ -273,7 +277,7 @@ import "../chunk-DGUM43GV.js";
|
|
|
273
277
|
|
|
274
278
|
// src/lib/manager-worker.ts
|
|
275
279
|
import { createHash as createHash20 } from "crypto";
|
|
276
|
-
import { readFileSync as readFileSync34, writeFileSync as writeFileSync18, mkdirSync as mkdirSync15, existsSync as existsSync19, rmSync as rmSync8, readdirSync as
|
|
280
|
+
import { readFileSync as readFileSync34, writeFileSync as writeFileSync18, mkdirSync as mkdirSync15, existsSync as existsSync19, rmSync as rmSync8, readdirSync as readdirSync13, statSync as statSync14, unlinkSync as unlinkSync6, renameSync as renameSync11, utimesSync as utimesSync4 } from "fs";
|
|
277
281
|
|
|
278
282
|
// src/lib/atomic-file-replace.ts
|
|
279
283
|
import { copyFileSync, renameSync, unlinkSync } from "fs";
|
|
@@ -299,7 +303,7 @@ function defaultUnique() {
|
|
|
299
303
|
|
|
300
304
|
// src/lib/manager-worker.ts
|
|
301
305
|
import { execFileSync as syncExecFile } from "child_process";
|
|
302
|
-
import { join as
|
|
306
|
+
import { join as join43, dirname as dirname11, delimiter as pathDelimiter } from "path";
|
|
303
307
|
import { homedir as homedir17 } from "os";
|
|
304
308
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
305
309
|
|
|
@@ -3684,10 +3688,115 @@ async function maybeReportTokenUsage(args) {
|
|
|
3684
3688
|
state3.set(codeName, next);
|
|
3685
3689
|
}
|
|
3686
3690
|
|
|
3687
|
-
// src/lib/
|
|
3688
|
-
import { readdirSync as readdirSync2,
|
|
3691
|
+
// src/lib/failing-turn-monitor.ts
|
|
3692
|
+
import { closeSync, openSync, readdirSync as readdirSync2, readSync, statSync as statSync2 } from "fs";
|
|
3689
3693
|
import { join as join17 } from "path";
|
|
3690
|
-
var MIN_CHECK_INTERVAL_MS3 =
|
|
3694
|
+
var MIN_CHECK_INTERVAL_MS3 = 3e4;
|
|
3695
|
+
var FAILING_TURN_TAIL_BYTES = 512 * 1024;
|
|
3696
|
+
var ACTIVE_TRANSCRIPT_WINDOW_MS = 60 * 60 * 1e3;
|
|
3697
|
+
var STATE_TTL_MS = 10 * 60 * 1e3;
|
|
3698
|
+
var state4 = /* @__PURE__ */ new Map();
|
|
3699
|
+
function positiveIntFromEnv(name, fallback) {
|
|
3700
|
+
const raw = process.env[name];
|
|
3701
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
3702
|
+
const n = Number(raw);
|
|
3703
|
+
return Number.isInteger(n) && n > 0 ? n : fallback;
|
|
3704
|
+
}
|
|
3705
|
+
function failingTurnThreshold() {
|
|
3706
|
+
return positiveIntFromEnv("AGT_FAILING_TURN_THRESHOLD", FAILING_TURN_RUN_DEFAULT_THRESHOLD);
|
|
3707
|
+
}
|
|
3708
|
+
function failingTurnLiveMs() {
|
|
3709
|
+
return positiveIntFromEnv("AGT_FAILING_TURN_LIVE_MS", FAILING_TURN_DEFAULT_LIVE_MS);
|
|
3710
|
+
}
|
|
3711
|
+
var FAILING_TURN_DEFAULT_LIVE_MS = 10 * 60 * 1e3;
|
|
3712
|
+
function failingTurnMaxMs() {
|
|
3713
|
+
return positiveIntFromEnv("AGT_FAILING_TURN_MAX_MS", FAILING_TURN_DEFAULT_MAX_TURN_MS);
|
|
3714
|
+
}
|
|
3715
|
+
function newestActiveTranscript(dir, nowMs) {
|
|
3716
|
+
let names;
|
|
3717
|
+
try {
|
|
3718
|
+
names = readdirSync2(dir);
|
|
3719
|
+
} catch {
|
|
3720
|
+
return null;
|
|
3721
|
+
}
|
|
3722
|
+
let best = null;
|
|
3723
|
+
for (const name of names) {
|
|
3724
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
3725
|
+
const path = join17(dir, name);
|
|
3726
|
+
try {
|
|
3727
|
+
const st = statSync2(path);
|
|
3728
|
+
if (!st.isFile() || nowMs - st.mtimeMs > ACTIVE_TRANSCRIPT_WINDOW_MS) continue;
|
|
3729
|
+
if (best === null || st.mtimeMs > best.mtimeMs) best = { path, mtimeMs: st.mtimeMs, size: st.size };
|
|
3730
|
+
} catch {
|
|
3731
|
+
continue;
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
return best;
|
|
3735
|
+
}
|
|
3736
|
+
function readTail(path, size, bytes = FAILING_TURN_TAIL_BYTES) {
|
|
3737
|
+
const length = Math.min(size, bytes);
|
|
3738
|
+
const buf = Buffer.alloc(length);
|
|
3739
|
+
const fd = openSync(path, "r");
|
|
3740
|
+
try {
|
|
3741
|
+
readSync(fd, buf, 0, length, size - length);
|
|
3742
|
+
} finally {
|
|
3743
|
+
closeSync(fd);
|
|
3744
|
+
}
|
|
3745
|
+
return buf.toString("utf-8");
|
|
3746
|
+
}
|
|
3747
|
+
function maybeCheckFailingTurns(args) {
|
|
3748
|
+
const nowMs = args.now ?? Date.now();
|
|
3749
|
+
const prev = state4.get(args.agentId);
|
|
3750
|
+
if (prev && nowMs - prev.checkedAt < MIN_CHECK_INTERVAL_MS3) return;
|
|
3751
|
+
try {
|
|
3752
|
+
const dir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(args.codeName));
|
|
3753
|
+
const file = newestActiveTranscript(dir, nowMs);
|
|
3754
|
+
if (file === null) {
|
|
3755
|
+
state4.set(args.agentId, { run: NO_FAILING_TURN_RUN, checkedAt: nowMs, file: null });
|
|
3756
|
+
return;
|
|
3757
|
+
}
|
|
3758
|
+
if (prev?.file && prev.file.path === file.path && prev.file.mtimeMs === file.mtimeMs && prev.file.size === file.size) {
|
|
3759
|
+
prev.checkedAt = nowMs;
|
|
3760
|
+
return;
|
|
3761
|
+
}
|
|
3762
|
+
const run = analyzeFailingTurnRun(readTail(file.path, file.size), { maxTurnMs: failingTurnMaxMs() });
|
|
3763
|
+
state4.set(args.agentId, { run, checkedAt: nowMs, file });
|
|
3764
|
+
} catch (err) {
|
|
3765
|
+
args.log(`[failing-turns] check failed for '${args.codeName}': ${err.message}`);
|
|
3766
|
+
if (prev) prev.checkedAt = nowMs;
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
function failingTurnLoops(now = Date.now(), threshold = failingTurnThreshold(), liveMs = failingTurnLiveMs()) {
|
|
3770
|
+
const failing = [];
|
|
3771
|
+
const recovered = [];
|
|
3772
|
+
for (const [agentId, s] of state4) {
|
|
3773
|
+
if (now - s.checkedAt > STATE_TTL_MS) {
|
|
3774
|
+
state4.delete(agentId);
|
|
3775
|
+
continue;
|
|
3776
|
+
}
|
|
3777
|
+
const live = s.run.lastFailureAtMs !== null && now - s.run.lastFailureAtMs <= liveMs;
|
|
3778
|
+
if (s.run.consecutive >= threshold && live) {
|
|
3779
|
+
failing.push({
|
|
3780
|
+
agent_id: agentId,
|
|
3781
|
+
verdict: "failing",
|
|
3782
|
+
consecutive: s.run.consecutive,
|
|
3783
|
+
first_failure_at: s.run.firstFailureAtMs === null ? null : new Date(s.run.firstFailureAtMs).toISOString(),
|
|
3784
|
+
last_failure_at: s.run.lastFailureAtMs === null ? null : new Date(s.run.lastFailureAtMs).toISOString(),
|
|
3785
|
+
last_status: s.run.lastStatus,
|
|
3786
|
+
last_error_code: s.run.lastErrorCode
|
|
3787
|
+
});
|
|
3788
|
+
} else if (s.run.newestTurn === "served") {
|
|
3789
|
+
recovered.push({ agent_id: agentId, verdict: "recovered" });
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
failing.sort((a, b) => b.consecutive - a.consecutive);
|
|
3793
|
+
return [...failing, ...recovered];
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
// src/lib/workflow-run-reconciler.ts
|
|
3797
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync12, statSync as statSync3 } from "fs";
|
|
3798
|
+
import { join as join18 } from "path";
|
|
3799
|
+
var MIN_CHECK_INTERVAL_MS4 = 5 * 6e4;
|
|
3691
3800
|
var SETTLE_MS = 3e4;
|
|
3692
3801
|
var TRANSCRIPT_MTIME_WINDOW_MS2 = 2 * 24 * 60 * 60 * 1e3;
|
|
3693
3802
|
var MAX_RUNS_PER_TICK = 20;
|
|
@@ -3700,15 +3809,15 @@ function collectJsonlRecursive(dir, minMtimeMs, out, depth) {
|
|
|
3700
3809
|
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
3701
3810
|
let entries;
|
|
3702
3811
|
try {
|
|
3703
|
-
entries =
|
|
3812
|
+
entries = readdirSync3(dir);
|
|
3704
3813
|
} catch {
|
|
3705
3814
|
return;
|
|
3706
3815
|
}
|
|
3707
3816
|
for (const name of entries) {
|
|
3708
|
-
const p =
|
|
3817
|
+
const p = join18(dir, name);
|
|
3709
3818
|
let st;
|
|
3710
3819
|
try {
|
|
3711
|
-
st =
|
|
3820
|
+
st = statSync3(p);
|
|
3712
3821
|
} catch {
|
|
3713
3822
|
continue;
|
|
3714
3823
|
}
|
|
@@ -3723,15 +3832,15 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
3723
3832
|
const out = [];
|
|
3724
3833
|
let entries;
|
|
3725
3834
|
try {
|
|
3726
|
-
entries =
|
|
3835
|
+
entries = readdirSync3(transcriptDir);
|
|
3727
3836
|
} catch {
|
|
3728
3837
|
return out;
|
|
3729
3838
|
}
|
|
3730
3839
|
for (const name of entries) {
|
|
3731
|
-
const path =
|
|
3840
|
+
const path = join18(transcriptDir, name);
|
|
3732
3841
|
let st;
|
|
3733
3842
|
try {
|
|
3734
|
-
st =
|
|
3843
|
+
st = statSync3(path);
|
|
3735
3844
|
} catch {
|
|
3736
3845
|
continue;
|
|
3737
3846
|
}
|
|
@@ -3740,7 +3849,7 @@ function enumerateTranscriptFiles(transcriptDir, nowMs, minMtimeMs = nowMs - TRA
|
|
|
3740
3849
|
continue;
|
|
3741
3850
|
}
|
|
3742
3851
|
if (st.isDirectory()) {
|
|
3743
|
-
collectJsonlRecursive(
|
|
3852
|
+
collectJsonlRecursive(join18(path, "subagents"), minMtimeMs, out, 0);
|
|
3744
3853
|
}
|
|
3745
3854
|
}
|
|
3746
3855
|
return out;
|
|
@@ -3765,7 +3874,7 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
3765
3874
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
3766
3875
|
const nowMs = now.getTime();
|
|
3767
3876
|
const prev = lastCheckedAt.get(codeName);
|
|
3768
|
-
if (prev !== void 0 && nowMs - prev <
|
|
3877
|
+
if (prev !== void 0 && nowMs - prev < MIN_CHECK_INTERVAL_MS4) return;
|
|
3769
3878
|
lastCheckedAt.set(codeName, nowMs);
|
|
3770
3879
|
let runs;
|
|
3771
3880
|
try {
|
|
@@ -3830,8 +3939,8 @@ async function maybeReconcileWorkflowRunTokens(args) {
|
|
|
3830
3939
|
}
|
|
3831
3940
|
|
|
3832
3941
|
// src/lib/conversation-evaluator.ts
|
|
3833
|
-
import { readdirSync as
|
|
3834
|
-
import { join as
|
|
3942
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync4 } from "fs";
|
|
3943
|
+
import { join as join19 } from "path";
|
|
3835
3944
|
|
|
3836
3945
|
// src/lib/detect-meta-egress.ts
|
|
3837
3946
|
var REPOST_PREAMBLE_WINDOW = 200;
|
|
@@ -3877,7 +3986,7 @@ function detectMetaEgress(agentMessages) {
|
|
|
3877
3986
|
}
|
|
3878
3987
|
|
|
3879
3988
|
// src/lib/conversation-evaluator.ts
|
|
3880
|
-
var
|
|
3989
|
+
var MIN_CHECK_INTERVAL_MS5 = 5 * 6e4;
|
|
3881
3990
|
var TRANSCRIPT_MTIME_WINDOW_MS3 = 7 * 24 * 60 * 60 * 1e3;
|
|
3882
3991
|
var WINDOW_PAD_MS = 5 * 6e4;
|
|
3883
3992
|
var MAX_TURN_CHARS = 1500;
|
|
@@ -4006,7 +4115,7 @@ function selectEvalBackend(opts) {
|
|
|
4006
4115
|
}
|
|
4007
4116
|
};
|
|
4008
4117
|
}
|
|
4009
|
-
var
|
|
4118
|
+
var state5 = /* @__PURE__ */ new Map();
|
|
4010
4119
|
function channelRefTokens(channelRef) {
|
|
4011
4120
|
return channelRef.split(":").slice(1).filter((p) => p && p !== "dm");
|
|
4012
4121
|
}
|
|
@@ -4182,11 +4291,11 @@ async function maybeEvaluateConversations(args) {
|
|
|
4182
4291
|
const { api: api2, backend, codeName, agentId, log: log2 } = args;
|
|
4183
4292
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
4184
4293
|
const nowMs = now.getTime();
|
|
4185
|
-
const existing =
|
|
4186
|
-
if (existing && nowMs - existing.lastCheckedAt <
|
|
4294
|
+
const existing = state5.get(codeName);
|
|
4295
|
+
if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS5) {
|
|
4187
4296
|
return;
|
|
4188
4297
|
}
|
|
4189
|
-
|
|
4298
|
+
state5.set(codeName, { lastCheckedAt: nowMs });
|
|
4190
4299
|
let pending2;
|
|
4191
4300
|
try {
|
|
4192
4301
|
const resp = await api2.get(
|
|
@@ -4311,12 +4420,12 @@ function readRecentTurns(dir, nowMs) {
|
|
|
4311
4420
|
const visit = (d) => {
|
|
4312
4421
|
let entries;
|
|
4313
4422
|
try {
|
|
4314
|
-
entries =
|
|
4423
|
+
entries = readdirSync4(d, { withFileTypes: true });
|
|
4315
4424
|
} catch {
|
|
4316
4425
|
return;
|
|
4317
4426
|
}
|
|
4318
4427
|
for (const ent of entries) {
|
|
4319
|
-
const full =
|
|
4428
|
+
const full = join19(d, ent.name);
|
|
4320
4429
|
if (ent.isDirectory()) {
|
|
4321
4430
|
visit(full);
|
|
4322
4431
|
continue;
|
|
@@ -4324,7 +4433,7 @@ function readRecentTurns(dir, nowMs) {
|
|
|
4324
4433
|
if (!ent.isFile() || !ent.name.endsWith(".jsonl")) continue;
|
|
4325
4434
|
let mtimeMs;
|
|
4326
4435
|
try {
|
|
4327
|
-
mtimeMs =
|
|
4436
|
+
mtimeMs = statSync4(full).mtimeMs;
|
|
4328
4437
|
} catch {
|
|
4329
4438
|
continue;
|
|
4330
4439
|
}
|
|
@@ -4451,7 +4560,7 @@ async function maybeEmitRoutineCandidates(args) {
|
|
|
4451
4560
|
}
|
|
4452
4561
|
|
|
4453
4562
|
// src/lib/memory-extractor.ts
|
|
4454
|
-
var
|
|
4563
|
+
var MIN_CHECK_INTERVAL_MS6 = 10 * 6e4;
|
|
4455
4564
|
var WINDOW_PAD_MS2 = 5 * 6e4;
|
|
4456
4565
|
var VALID_MEMORY_TYPES = /* @__PURE__ */ new Set(["user", "feedback", "project", "reference"]);
|
|
4457
4566
|
var SECRET_PATTERNS = [
|
|
@@ -4469,7 +4578,7 @@ var SECRET_PATTERNS = [
|
|
|
4469
4578
|
function scrubSensitive(text) {
|
|
4470
4579
|
return scrubPreservingIdentifiers(text, SECRET_PATTERNS);
|
|
4471
4580
|
}
|
|
4472
|
-
var
|
|
4581
|
+
var state6 = /* @__PURE__ */ new Map();
|
|
4473
4582
|
function buildExtractionPrompt(channel, transcript) {
|
|
4474
4583
|
return `You are extracting durable, reusable memories from one completed ${channel} conversation between an AI agent and an end-user. A good memory is a stable preference, fact, correction, or recurring work context that will help the agent in FUTURE conversations \u2014 not a one-off task detail or pleasantry.
|
|
4475
4584
|
|
|
@@ -4589,12 +4698,12 @@ async function maybeExtractMemories(args) {
|
|
|
4589
4698
|
const { api: api2, backend, codeName, agentId, log: log2 } = args;
|
|
4590
4699
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
4591
4700
|
const nowMs = now.getTime();
|
|
4592
|
-
const existing =
|
|
4593
|
-
if (existing && nowMs - existing.lastCheckedAt <
|
|
4701
|
+
const existing = state6.get(codeName);
|
|
4702
|
+
if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS6) {
|
|
4594
4703
|
return;
|
|
4595
4704
|
}
|
|
4596
4705
|
const st = { lastCheckedAt: nowMs, salvaged: existing?.salvaged ?? /* @__PURE__ */ new Set() };
|
|
4597
|
-
|
|
4706
|
+
state6.set(codeName, st);
|
|
4598
4707
|
let pending2;
|
|
4599
4708
|
try {
|
|
4600
4709
|
const resp = await api2.get(
|
|
@@ -4704,17 +4813,17 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
|
|
|
4704
4813
|
|
|
4705
4814
|
// src/lib/tool-call-audit.ts
|
|
4706
4815
|
import { homedir as homedir11 } from "os";
|
|
4707
|
-
import { join as
|
|
4816
|
+
import { join as join24 } from "path";
|
|
4708
4817
|
|
|
4709
4818
|
// src/lib/agent-logging-mode.ts
|
|
4710
4819
|
import { readFileSync as readFileSync14 } from "fs";
|
|
4711
4820
|
import { homedir as homedir8 } from "os";
|
|
4712
|
-
import { join as
|
|
4821
|
+
import { join as join20 } from "path";
|
|
4713
4822
|
var LOGGING_MODES = ["hash-only", "redacted", "full-local"];
|
|
4714
4823
|
function charterPath(codeName, homeDir) {
|
|
4715
4824
|
const home = homeDir ?? (process.env["HOME"]?.trim() || homedir8());
|
|
4716
4825
|
const key = agentRuntimeKey(codeName, homeDir);
|
|
4717
|
-
return
|
|
4826
|
+
return join20(home, ".augmented", key, "provision", "CHARTER.md");
|
|
4718
4827
|
}
|
|
4719
4828
|
function readAgentLoggingMode(codeName, homeDir) {
|
|
4720
4829
|
let raw;
|
|
@@ -4745,13 +4854,13 @@ function loggingModeWithholdsTargets(reading) {
|
|
|
4745
4854
|
import { randomBytes } from "crypto";
|
|
4746
4855
|
import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync15, renameSync as renameSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
4747
4856
|
import { homedir as homedir9 } from "os";
|
|
4748
|
-
import { dirname as dirname7, join as
|
|
4857
|
+
import { dirname as dirname7, join as join21 } from "path";
|
|
4749
4858
|
var SALT_BYTES = 32;
|
|
4750
4859
|
var SALT_RE = /^[0-9a-f]{64}$/;
|
|
4751
4860
|
function pathSaltPath(codeName, homeDir) {
|
|
4752
4861
|
const home = homeDir ?? (process.env["HOME"]?.trim() || homedir9());
|
|
4753
4862
|
const key = agentRuntimeKey(codeName, homeDir);
|
|
4754
|
-
return
|
|
4863
|
+
return join21(home, ".augmented", key, "tool-call-path-salt");
|
|
4755
4864
|
}
|
|
4756
4865
|
function readToolCallPathSalt(codeName, homeDir) {
|
|
4757
4866
|
let file;
|
|
@@ -4785,11 +4894,11 @@ function readToolCallPathSalt(codeName, homeDir) {
|
|
|
4785
4894
|
}
|
|
4786
4895
|
|
|
4787
4896
|
// src/lib/tool-call-scan.ts
|
|
4788
|
-
import { statSync as
|
|
4897
|
+
import { statSync as statSync5 } from "fs";
|
|
4789
4898
|
|
|
4790
4899
|
// src/lib/tool-call-extractor.ts
|
|
4791
|
-
import { closeSync, fstatSync, openSync, readFileSync as readFileSync16, readSync, readdirSync as
|
|
4792
|
-
import { basename as basename2, join as
|
|
4900
|
+
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readFileSync as readFileSync16, readSync as readSync2, readdirSync as readdirSync5 } from "fs";
|
|
4901
|
+
import { basename as basename2, join as join22, relative } from "path";
|
|
4793
4902
|
import { StringDecoder } from "string_decoder";
|
|
4794
4903
|
|
|
4795
4904
|
// src/lib/tool-call-redaction.ts
|
|
@@ -4918,7 +5027,7 @@ function redactToolTargetInner(toolName, input, ctx) {
|
|
|
4918
5027
|
var EXTRACTOR_VERSION = "e1";
|
|
4919
5028
|
function enumerateSessionTranscripts(transcriptDir, sessionId, projectsRoot) {
|
|
4920
5029
|
const files = [];
|
|
4921
|
-
const mainAbs =
|
|
5030
|
+
const mainAbs = join22(transcriptDir, `${sessionId}.jsonl`);
|
|
4922
5031
|
files.push({
|
|
4923
5032
|
absPath: mainAbs,
|
|
4924
5033
|
relPath: relative(projectsRoot, mainAbs),
|
|
@@ -4926,16 +5035,16 @@ function enumerateSessionTranscripts(transcriptDir, sessionId, projectsRoot) {
|
|
|
4926
5035
|
isSubagent: false,
|
|
4927
5036
|
subagentId: null
|
|
4928
5037
|
});
|
|
4929
|
-
const subDir =
|
|
5038
|
+
const subDir = join22(transcriptDir, sessionId, "subagents");
|
|
4930
5039
|
let entries;
|
|
4931
5040
|
try {
|
|
4932
|
-
entries =
|
|
5041
|
+
entries = readdirSync5(subDir);
|
|
4933
5042
|
} catch {
|
|
4934
5043
|
return files;
|
|
4935
5044
|
}
|
|
4936
5045
|
for (const name of entries) {
|
|
4937
5046
|
if (!name.endsWith(".jsonl")) continue;
|
|
4938
|
-
const abs =
|
|
5047
|
+
const abs = join22(subDir, name);
|
|
4939
5048
|
const stem = basename2(name, ".jsonl");
|
|
4940
5049
|
files.push({
|
|
4941
5050
|
absPath: abs,
|
|
@@ -5038,7 +5147,7 @@ var WINDOW_BUDGET_BYTES = 4 * 1024 * 1024;
|
|
|
5038
5147
|
function extractTranscriptWindow(file, opts, from) {
|
|
5039
5148
|
let fd;
|
|
5040
5149
|
try {
|
|
5041
|
-
fd =
|
|
5150
|
+
fd = openSync2(file.absPath, "r");
|
|
5042
5151
|
} catch {
|
|
5043
5152
|
return {
|
|
5044
5153
|
records: [],
|
|
@@ -5084,7 +5193,7 @@ function extractTranscriptWindow(file, opts, from) {
|
|
|
5084
5193
|
hitBudget = true;
|
|
5085
5194
|
break;
|
|
5086
5195
|
}
|
|
5087
|
-
const bytesRead =
|
|
5196
|
+
const bytesRead = readSync2(fd, buf, 0, WINDOW_CHUNK_BYTES, position);
|
|
5088
5197
|
if (bytesRead <= 0) break;
|
|
5089
5198
|
position += bytesRead;
|
|
5090
5199
|
carry += decoder.write(buf.subarray(0, bytesRead));
|
|
@@ -5107,7 +5216,7 @@ function extractTranscriptWindow(file, opts, from) {
|
|
|
5107
5216
|
} catch {
|
|
5108
5217
|
} finally {
|
|
5109
5218
|
try {
|
|
5110
|
-
|
|
5219
|
+
closeSync2(fd);
|
|
5111
5220
|
} catch {
|
|
5112
5221
|
}
|
|
5113
5222
|
}
|
|
@@ -5135,7 +5244,7 @@ function extractTranscriptWindow(file, opts, from) {
|
|
|
5135
5244
|
// src/lib/tool-call-cursor.ts
|
|
5136
5245
|
import { existsSync as existsSync5, readFileSync as readFileSync17 } from "fs";
|
|
5137
5246
|
import { homedir as homedir10 } from "os";
|
|
5138
|
-
import { join as
|
|
5247
|
+
import { join as join23 } from "path";
|
|
5139
5248
|
var COVERAGE_DISPOSITIONS = [
|
|
5140
5249
|
"ok",
|
|
5141
5250
|
"not_entitled",
|
|
@@ -5190,7 +5299,7 @@ function parseCursorKey(key) {
|
|
|
5190
5299
|
function cursorStatePath(codeName, homeDir) {
|
|
5191
5300
|
const home = homeDir ?? (process.env["HOME"]?.trim() || homedir10());
|
|
5192
5301
|
const key = agentRuntimeKey(codeName, homeDir);
|
|
5193
|
-
return
|
|
5302
|
+
return join23(home, ".augmented", key, "tool-call-cursors.json");
|
|
5194
5303
|
}
|
|
5195
5304
|
function loadCursors(path) {
|
|
5196
5305
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -5412,7 +5521,7 @@ function chunk(items, size) {
|
|
|
5412
5521
|
}
|
|
5413
5522
|
function endOfFile(absPath) {
|
|
5414
5523
|
try {
|
|
5415
|
-
return { byteOffset:
|
|
5524
|
+
return { byteOffset: statSync5(absPath).size, lineOffset: 0 };
|
|
5416
5525
|
} catch {
|
|
5417
5526
|
return null;
|
|
5418
5527
|
}
|
|
@@ -5567,9 +5676,9 @@ async function reportCoverage(args, cursors, touched, log2) {
|
|
|
5567
5676
|
}
|
|
5568
5677
|
|
|
5569
5678
|
// src/lib/tool-call-audit.ts
|
|
5570
|
-
var
|
|
5679
|
+
var MIN_CHECK_INTERVAL_MS7 = 10 * 6e4;
|
|
5571
5680
|
var ENTITLEMENT_RECHECK_MS = 30 * 6e4;
|
|
5572
|
-
var
|
|
5681
|
+
var state7 = /* @__PURE__ */ new Map();
|
|
5573
5682
|
function entitlementLatch(entry, nowMs) {
|
|
5574
5683
|
if (!entry?.notEntitledAt) return false;
|
|
5575
5684
|
return !hasElapsed(entry.notEntitledAt, nowMs, ENTITLEMENT_RECHECK_MS);
|
|
@@ -5584,13 +5693,13 @@ async function maybeScanToolCalls(args) {
|
|
|
5584
5693
|
const nowFn = args.now ?? Date.now;
|
|
5585
5694
|
const nowMs = nowFn();
|
|
5586
5695
|
try {
|
|
5587
|
-
const existing =
|
|
5588
|
-
if (existing && !hasElapsed(existing.lastCheckedAt, nowMs,
|
|
5696
|
+
const existing = state7.get(codeName);
|
|
5697
|
+
if (existing && !hasElapsed(existing.lastCheckedAt, nowMs, MIN_CHECK_INTERVAL_MS7)) return;
|
|
5589
5698
|
if (entitlementLatch(existing, nowMs)) {
|
|
5590
|
-
|
|
5699
|
+
state7.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
|
|
5591
5700
|
return;
|
|
5592
5701
|
}
|
|
5593
|
-
|
|
5702
|
+
state7.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
|
|
5594
5703
|
const loggingMode = readAgentLoggingMode(codeName, args.homeDir);
|
|
5595
5704
|
const hashOnly = loggingModeWithholdsTargets(loggingMode);
|
|
5596
5705
|
if (loggingMode.mode === null) {
|
|
@@ -5603,7 +5712,7 @@ async function maybeScanToolCalls(args) {
|
|
|
5603
5712
|
log2(`[tool-call-audit] ${codeName}: no path-hash salt available \u2014 file targets withheld`);
|
|
5604
5713
|
}
|
|
5605
5714
|
const home = args.homeDir ?? (process.env["HOME"]?.trim() || homedir11());
|
|
5606
|
-
const projectsRoot = args.projectsRoot ??
|
|
5715
|
+
const projectsRoot = args.projectsRoot ?? join24(home, ".claude", "projects");
|
|
5607
5716
|
const transcriptDir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
|
|
5608
5717
|
const current = peekCurrentSession(codeName);
|
|
5609
5718
|
const sessionIds = current ? [current.sessionId] : [];
|
|
@@ -5622,9 +5731,9 @@ async function maybeScanToolCalls(args) {
|
|
|
5622
5731
|
...args.cursorPath === void 0 ? {} : { cursorPath: args.cursorPath }
|
|
5623
5732
|
});
|
|
5624
5733
|
if (summary.notEntitled) {
|
|
5625
|
-
|
|
5734
|
+
state7.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: nowMs });
|
|
5626
5735
|
} else if (summary.callsIngested > 0) {
|
|
5627
|
-
|
|
5736
|
+
state7.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: null });
|
|
5628
5737
|
}
|
|
5629
5738
|
} catch (err) {
|
|
5630
5739
|
log2(`[tool-call-audit] ${codeName}: scan failed: ${err.message}`);
|
|
@@ -5634,11 +5743,11 @@ async function maybeScanToolCalls(args) {
|
|
|
5634
5743
|
// src/lib/activity-cache-monitor.ts
|
|
5635
5744
|
import { existsSync as existsSync6, readFileSync as readFileSync18 } from "fs";
|
|
5636
5745
|
import { homedir as homedir12 } from "os";
|
|
5637
|
-
import { join as
|
|
5638
|
-
var
|
|
5639
|
-
var STATS_CACHE_PATH =
|
|
5746
|
+
import { join as join25 } from "path";
|
|
5747
|
+
var MIN_CHECK_INTERVAL_MS8 = 6e4;
|
|
5748
|
+
var STATS_CACHE_PATH = join25(homedir12(), ".claude", "stats-cache.json");
|
|
5640
5749
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
5641
|
-
var
|
|
5750
|
+
var state8 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
5642
5751
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
5643
5752
|
let parsed;
|
|
5644
5753
|
try {
|
|
@@ -5677,8 +5786,8 @@ async function maybeReportActivityCache(args) {
|
|
|
5677
5786
|
const { api: api2, log: log2 } = args;
|
|
5678
5787
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
5679
5788
|
const nowMs = now.getTime();
|
|
5680
|
-
if (nowMs -
|
|
5681
|
-
|
|
5789
|
+
if (nowMs - state8.lastCheckedAt < MIN_CHECK_INTERVAL_MS8) return;
|
|
5790
|
+
state8.lastCheckedAt = nowMs;
|
|
5682
5791
|
if (!existsSync6(STATS_CACHE_PATH)) {
|
|
5683
5792
|
return;
|
|
5684
5793
|
}
|
|
@@ -5689,12 +5798,12 @@ async function maybeReportActivityCache(args) {
|
|
|
5689
5798
|
log2(`[activity-cache] readFileSync failed: ${err.message}`);
|
|
5690
5799
|
return;
|
|
5691
5800
|
}
|
|
5692
|
-
const rows = selectNewDailyRows(raw,
|
|
5801
|
+
const rows = selectNewDailyRows(raw, state8.lastObservedDate);
|
|
5693
5802
|
if (rows.length === 0) return;
|
|
5694
5803
|
for (const row of rows) {
|
|
5695
5804
|
try {
|
|
5696
5805
|
await api2.post("/host/activity-observations", row);
|
|
5697
|
-
|
|
5806
|
+
state8.lastObservedDate = row.date;
|
|
5698
5807
|
} catch (err) {
|
|
5699
5808
|
log2(
|
|
5700
5809
|
`[activity-cache] POST /host/activity-observations failed for date=${row.date}: ${err.message}`
|
|
@@ -5927,11 +6036,11 @@ function bundleFingerprint(files) {
|
|
|
5927
6036
|
}
|
|
5928
6037
|
|
|
5929
6038
|
// src/lib/self-update-device-state-hold.ts
|
|
5930
|
-
import { statSync as
|
|
6039
|
+
import { statSync as statSync6 } from "fs";
|
|
5931
6040
|
import { platform as osPlatform } from "os";
|
|
5932
6041
|
function realStat(path) {
|
|
5933
6042
|
try {
|
|
5934
|
-
return { isFile:
|
|
6043
|
+
return { isFile: statSync6(path).isFile() };
|
|
5935
6044
|
} catch (err) {
|
|
5936
6045
|
return { errno: err?.code ?? "UNKNOWN" };
|
|
5937
6046
|
}
|
|
@@ -6007,14 +6116,14 @@ import {
|
|
|
6007
6116
|
existsSync as existsSync7,
|
|
6008
6117
|
mkdirSync as mkdirSync7,
|
|
6009
6118
|
readFileSync as readFileSync19,
|
|
6010
|
-
readdirSync as
|
|
6119
|
+
readdirSync as readdirSync6,
|
|
6011
6120
|
renameSync as renameSync5,
|
|
6012
6121
|
rmSync as rmSync3,
|
|
6013
|
-
statSync as
|
|
6122
|
+
statSync as statSync7,
|
|
6014
6123
|
utimesSync,
|
|
6015
6124
|
writeFileSync as writeFileSync8
|
|
6016
6125
|
} from "fs";
|
|
6017
|
-
import { join as
|
|
6126
|
+
import { join as join26 } from "path";
|
|
6018
6127
|
var KNOWLEDGE_FETCH_CHUNK = 100;
|
|
6019
6128
|
var CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
6020
6129
|
var SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6023,7 +6132,7 @@ function knowledgeHash(content) {
|
|
|
6023
6132
|
return createHash9("sha256").update(content, "utf8").digest("hex");
|
|
6024
6133
|
}
|
|
6025
6134
|
function cachePath(cacheDir, hash) {
|
|
6026
|
-
return
|
|
6135
|
+
return join26(cacheDir, hash);
|
|
6027
6136
|
}
|
|
6028
6137
|
function readCachedKnowledge(cacheDir, hash) {
|
|
6029
6138
|
const path = cachePath(cacheDir, hash);
|
|
@@ -6056,10 +6165,10 @@ function sweepKnowledgeCache(cacheDir, now = Date.now()) {
|
|
|
6056
6165
|
lastSweepAt = now;
|
|
6057
6166
|
try {
|
|
6058
6167
|
if (!existsSync7(cacheDir)) return;
|
|
6059
|
-
for (const name of
|
|
6060
|
-
const path =
|
|
6168
|
+
for (const name of readdirSync6(cacheDir)) {
|
|
6169
|
+
const path = join26(cacheDir, name);
|
|
6061
6170
|
try {
|
|
6062
|
-
if (now -
|
|
6171
|
+
if (now - statSync7(path).mtimeMs > CACHE_TTL_MS) rmSync3(path, { force: true });
|
|
6063
6172
|
} catch {
|
|
6064
6173
|
}
|
|
6065
6174
|
}
|
|
@@ -6110,14 +6219,14 @@ import {
|
|
|
6110
6219
|
existsSync as existsSync8,
|
|
6111
6220
|
mkdirSync as mkdirSync8,
|
|
6112
6221
|
readFileSync as readFileSync20,
|
|
6113
|
-
readdirSync as
|
|
6222
|
+
readdirSync as readdirSync7,
|
|
6114
6223
|
renameSync as renameSync6,
|
|
6115
6224
|
rmSync as rmSync4,
|
|
6116
|
-
statSync as
|
|
6225
|
+
statSync as statSync8,
|
|
6117
6226
|
utimesSync as utimesSync2,
|
|
6118
6227
|
writeFileSync as writeFileSync9
|
|
6119
6228
|
} from "fs";
|
|
6120
|
-
import { join as
|
|
6229
|
+
import { join as join27 } from "path";
|
|
6121
6230
|
var MEMORY_FETCH_CHUNK = 100;
|
|
6122
6231
|
var CACHE_TTL_MS2 = 30 * 24 * 60 * 60 * 1e3;
|
|
6123
6232
|
var SWEEP_INTERVAL_MS2 = 24 * 60 * 60 * 1e3;
|
|
@@ -6126,7 +6235,7 @@ function memoryHash(content) {
|
|
|
6126
6235
|
return createHash10("sha256").update(content, "utf8").digest("hex");
|
|
6127
6236
|
}
|
|
6128
6237
|
function cachePath2(cacheDir, hash) {
|
|
6129
|
-
return
|
|
6238
|
+
return join27(cacheDir, hash);
|
|
6130
6239
|
}
|
|
6131
6240
|
function readCachedMemory(cacheDir, hash) {
|
|
6132
6241
|
const path = cachePath2(cacheDir, hash);
|
|
@@ -6159,10 +6268,10 @@ function sweepMemoryCache(cacheDir, now = Date.now()) {
|
|
|
6159
6268
|
lastSweepAt2.set(cacheDir, now);
|
|
6160
6269
|
try {
|
|
6161
6270
|
if (!existsSync8(cacheDir)) return;
|
|
6162
|
-
for (const name of
|
|
6163
|
-
const path =
|
|
6271
|
+
for (const name of readdirSync7(cacheDir)) {
|
|
6272
|
+
const path = join27(cacheDir, name);
|
|
6164
6273
|
try {
|
|
6165
|
-
if (now -
|
|
6274
|
+
if (now - statSync8(path).mtimeMs > CACHE_TTL_MS2) rmSync4(path, { force: true });
|
|
6166
6275
|
} catch {
|
|
6167
6276
|
}
|
|
6168
6277
|
}
|
|
@@ -6219,14 +6328,14 @@ import {
|
|
|
6219
6328
|
existsSync as existsSync9,
|
|
6220
6329
|
mkdirSync as mkdirSync9,
|
|
6221
6330
|
readFileSync as readFileSync21,
|
|
6222
|
-
readdirSync as
|
|
6331
|
+
readdirSync as readdirSync8,
|
|
6223
6332
|
renameSync as renameSync7,
|
|
6224
6333
|
rmSync as rmSync5,
|
|
6225
|
-
statSync as
|
|
6334
|
+
statSync as statSync9,
|
|
6226
6335
|
utimesSync as utimesSync3,
|
|
6227
6336
|
writeFileSync as writeFileSync10
|
|
6228
6337
|
} from "fs";
|
|
6229
|
-
import { join as
|
|
6338
|
+
import { join as join28 } from "path";
|
|
6230
6339
|
var SKILL_FETCH_CHUNK = 100;
|
|
6231
6340
|
var CACHE_TTL_MS3 = 30 * 24 * 60 * 60 * 1e3;
|
|
6232
6341
|
var SWEEP_INTERVAL_MS3 = 24 * 60 * 60 * 1e3;
|
|
@@ -6235,7 +6344,7 @@ function skillHash(content) {
|
|
|
6235
6344
|
return createHash11("sha256").update(content, "utf8").digest("hex");
|
|
6236
6345
|
}
|
|
6237
6346
|
function cachePath3(cacheDir, hash) {
|
|
6238
|
-
return
|
|
6347
|
+
return join28(cacheDir, hash);
|
|
6239
6348
|
}
|
|
6240
6349
|
function readCachedSkill(cacheDir, hash) {
|
|
6241
6350
|
const path = cachePath3(cacheDir, hash);
|
|
@@ -6268,10 +6377,10 @@ function sweepSkillCache(cacheDir, now = Date.now()) {
|
|
|
6268
6377
|
lastSweepAt3 = now;
|
|
6269
6378
|
try {
|
|
6270
6379
|
if (!existsSync9(cacheDir)) return;
|
|
6271
|
-
for (const name of
|
|
6272
|
-
const path =
|
|
6380
|
+
for (const name of readdirSync8(cacheDir)) {
|
|
6381
|
+
const path = join28(cacheDir, name);
|
|
6273
6382
|
try {
|
|
6274
|
-
if (now -
|
|
6383
|
+
if (now - statSync9(path).mtimeMs > CACHE_TTL_MS3) rmSync5(path, { force: true });
|
|
6275
6384
|
} catch {
|
|
6276
6385
|
}
|
|
6277
6386
|
}
|
|
@@ -6557,10 +6666,10 @@ function resolveConditionalResponse(wire, hasCachedBody) {
|
|
|
6557
6666
|
|
|
6558
6667
|
// src/lib/channel-hash-cache.ts
|
|
6559
6668
|
import { existsSync as existsSync10, readFileSync as readFileSync22, writeFileSync as writeFileSync11 } from "fs";
|
|
6560
|
-
import { join as
|
|
6669
|
+
import { join as join29 } from "path";
|
|
6561
6670
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
6562
6671
|
function getChannelHashCacheFile(configDir) {
|
|
6563
|
-
return
|
|
6672
|
+
return join29(configDir, CACHE_FILENAME);
|
|
6564
6673
|
}
|
|
6565
6674
|
function loadChannelHashCache(target, configDir) {
|
|
6566
6675
|
const path = getChannelHashCacheFile(configDir);
|
|
@@ -6588,7 +6697,7 @@ function saveChannelHashCache(source, configDir) {
|
|
|
6588
6697
|
|
|
6589
6698
|
// src/lib/sender-policy-baseline.ts
|
|
6590
6699
|
import { existsSync as existsSync11, readFileSync as readFileSync23 } from "fs";
|
|
6591
|
-
import { join as
|
|
6700
|
+
import { join as join30 } from "path";
|
|
6592
6701
|
var BASELINE_FILENAME = "sender-policy-baseline.json";
|
|
6593
6702
|
var SENDER_POLICY_BASELINE_VERSION = 1;
|
|
6594
6703
|
var BASELINE_CONCERNS = [
|
|
@@ -6626,7 +6735,7 @@ function createDeliveryBaselineMaps() {
|
|
|
6626
6735
|
};
|
|
6627
6736
|
}
|
|
6628
6737
|
function getSenderPolicyBaselineFile(configDir) {
|
|
6629
|
-
return
|
|
6738
|
+
return join30(configDir, BASELINE_FILENAME);
|
|
6630
6739
|
}
|
|
6631
6740
|
function loadSenderPolicyBaseline(target, configDir, log2) {
|
|
6632
6741
|
const path = getSenderPolicyBaselineFile(configDir);
|
|
@@ -6683,7 +6792,7 @@ function saveSenderPolicyBaseline(source, configDir, log2) {
|
|
|
6683
6792
|
|
|
6684
6793
|
// src/lib/stuck-streak-store.ts
|
|
6685
6794
|
import { existsSync as existsSync12, readFileSync as readFileSync24 } from "fs";
|
|
6686
|
-
import { join as
|
|
6795
|
+
import { join as join31 } from "path";
|
|
6687
6796
|
var STORE_FILENAME = "stuck-streaks.json";
|
|
6688
6797
|
var STUCK_STREAK_STORE_VERSION = 1;
|
|
6689
6798
|
var STUCK_STREAK_CONCERNS = ["channelSync", "realtimeRebind"];
|
|
@@ -6691,7 +6800,7 @@ function createStuckStreakMaps() {
|
|
|
6691
6800
|
return { channelSync: /* @__PURE__ */ new Map(), realtimeRebind: /* @__PURE__ */ new Map() };
|
|
6692
6801
|
}
|
|
6693
6802
|
function getStuckStreakStoreFile(configDir) {
|
|
6694
|
-
return
|
|
6803
|
+
return join31(configDir, STORE_FILENAME);
|
|
6695
6804
|
}
|
|
6696
6805
|
function isValidPersistedStreak(value) {
|
|
6697
6806
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -6776,13 +6885,13 @@ function pruneStuckStreaksToAgents(maps, activeAgentIds) {
|
|
|
6776
6885
|
}
|
|
6777
6886
|
|
|
6778
6887
|
// src/lib/claude-device-state.ts
|
|
6779
|
-
import { readFileSync as readFileSync25, statSync as
|
|
6888
|
+
import { readFileSync as readFileSync25, statSync as statSync10 } from "fs";
|
|
6780
6889
|
function claudeDeviceStatePath(env = process.env) {
|
|
6781
6890
|
return effectiveClaudeJsonPath(void 0, env);
|
|
6782
6891
|
}
|
|
6783
6892
|
function probeClaudeDeviceStatePresence(path = claudeDeviceStatePath()) {
|
|
6784
6893
|
try {
|
|
6785
|
-
return
|
|
6894
|
+
return statSync10(path).isFile() ? { present: true } : { present: false, reason: "not-a-file" };
|
|
6786
6895
|
} catch (err) {
|
|
6787
6896
|
return {
|
|
6788
6897
|
present: false,
|
|
@@ -6792,7 +6901,7 @@ function probeClaudeDeviceStatePresence(path = claudeDeviceStatePath()) {
|
|
|
6792
6901
|
}
|
|
6793
6902
|
function checkClaudeDeviceState(path = claudeDeviceStatePath()) {
|
|
6794
6903
|
try {
|
|
6795
|
-
if (!
|
|
6904
|
+
if (!statSync10(path).isFile()) return { usable: false, reason: "not-a-file" };
|
|
6796
6905
|
} catch (err) {
|
|
6797
6906
|
return {
|
|
6798
6907
|
usable: false,
|
|
@@ -7479,7 +7588,7 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
|
|
|
7479
7588
|
}
|
|
7480
7589
|
|
|
7481
7590
|
// src/lib/manager/integration-skill-cache.ts
|
|
7482
|
-
import { join as
|
|
7591
|
+
import { join as join32 } from "path";
|
|
7483
7592
|
function integrationSkillHashKey(agentId, skillId) {
|
|
7484
7593
|
return `plugin-skill:${agentId}:${skillId}`;
|
|
7485
7594
|
}
|
|
@@ -7495,16 +7604,16 @@ function forgetIntegrationSkill(cache2, agentId, skillId) {
|
|
|
7495
7604
|
function removeIntegrationSkillFolder(opts) {
|
|
7496
7605
|
forgetIntegrationSkill(opts.cache, opts.agentId, opts.entry);
|
|
7497
7606
|
for (const dir of opts.dirs) {
|
|
7498
|
-
opts.removeDir(
|
|
7607
|
+
opts.removeDir(join32(dir, opts.entry));
|
|
7499
7608
|
}
|
|
7500
7609
|
}
|
|
7501
7610
|
|
|
7502
7611
|
// src/lib/manager/managed-skill-manifest.ts
|
|
7503
7612
|
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync26, writeFileSync as writeFileSync12 } from "fs";
|
|
7504
|
-
import { dirname as dirname8, join as
|
|
7613
|
+
import { dirname as dirname8, join as join33 } from "path";
|
|
7505
7614
|
var MANIFEST_VERSION = 1;
|
|
7506
7615
|
function managedSkillManifestPath(agentRootDir) {
|
|
7507
|
-
return
|
|
7616
|
+
return join33(agentRootDir, "managed-skills.json");
|
|
7508
7617
|
}
|
|
7509
7618
|
function readManagedSkillManifest(path) {
|
|
7510
7619
|
try {
|
|
@@ -7639,7 +7748,7 @@ function resolveModelChain(refreshData) {
|
|
|
7639
7748
|
|
|
7640
7749
|
// src/lib/manager/claude-auth.ts
|
|
7641
7750
|
import { existsSync as existsSync14, rmSync as rmSync6 } from "fs";
|
|
7642
|
-
import { join as
|
|
7751
|
+
import { join as join34 } from "path";
|
|
7643
7752
|
import { homedir as homedir13 } from "os";
|
|
7644
7753
|
async function applyClaudeAuthToEnv(childEnv, label) {
|
|
7645
7754
|
const apiKey = getApiKey();
|
|
@@ -7652,9 +7761,9 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
7652
7761
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
7653
7762
|
}
|
|
7654
7763
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
7655
|
-
const claudeDir =
|
|
7764
|
+
const claudeDir = join34(homedir13(), ".claude");
|
|
7656
7765
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
7657
|
-
const p =
|
|
7766
|
+
const p = join34(claudeDir, filename);
|
|
7658
7767
|
if (existsSync14(p)) {
|
|
7659
7768
|
try {
|
|
7660
7769
|
rmSync6(p, { force: true });
|
|
@@ -7771,21 +7880,21 @@ function nudgeIntervalForCount(nudgeCount, fullCadenceMs, maxCadenceMs) {
|
|
|
7771
7880
|
const exponent = Math.max(0, Math.min(nudgeCount - 1, 8));
|
|
7772
7881
|
return Math.min(fullCadenceMs * 3 ** exponent, Math.max(maxCadenceMs, fullCadenceMs));
|
|
7773
7882
|
}
|
|
7774
|
-
function shouldNudgeUnchangedBoard(signature,
|
|
7775
|
-
if (!
|
|
7776
|
-
if (
|
|
7777
|
-
return now -
|
|
7883
|
+
function shouldNudgeUnchangedBoard(signature, state10, now, fullCadenceMs, maxCadenceMs = fullCadenceMs) {
|
|
7884
|
+
if (!state10) return true;
|
|
7885
|
+
if (state10.signature !== signature) return true;
|
|
7886
|
+
return now - state10.nudgedAt >= nudgeIntervalForCount(state10.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
|
|
7778
7887
|
}
|
|
7779
7888
|
function failureRetryIntervalForCount(failureCount2, baseMs, maxMs) {
|
|
7780
7889
|
const exponent = Math.max(0, Math.min(failureCount2 - 1, 8));
|
|
7781
7890
|
return Math.min(baseMs * 3 ** exponent, Math.max(maxMs, baseMs));
|
|
7782
7891
|
}
|
|
7783
7892
|
var KANBAN_NOTICE_BREAKER_THRESHOLD = 5;
|
|
7784
|
-
function shouldAttemptNoticeEnqueue(
|
|
7785
|
-
const failures =
|
|
7893
|
+
function shouldAttemptNoticeEnqueue(state10, now, baseMs, maxMs, breakerThreshold = KANBAN_NOTICE_BREAKER_THRESHOLD) {
|
|
7894
|
+
const failures = state10?.failureCount ?? 0;
|
|
7786
7895
|
if (failures <= 0) return { attempt: true, breakerOpen: false };
|
|
7787
7896
|
const breakerOpen = failures >= breakerThreshold;
|
|
7788
|
-
const failedAt =
|
|
7897
|
+
const failedAt = state10?.failedAt;
|
|
7789
7898
|
const due = failedAt === void 0 || failedAt > now || now - failedAt >= failureRetryIntervalForCount(failures, baseMs, maxMs);
|
|
7790
7899
|
return { attempt: due, breakerOpen };
|
|
7791
7900
|
}
|
|
@@ -8011,11 +8120,11 @@ function formatBoardForPrompt(items, template) {
|
|
|
8011
8120
|
|
|
8012
8121
|
// src/lib/manager/kanban/nudge-state-cache.ts
|
|
8013
8122
|
import { existsSync as existsSync15, readFileSync as readFileSync27, writeFileSync as writeFileSync13 } from "fs";
|
|
8014
|
-
import { join as
|
|
8123
|
+
import { join as join35 } from "path";
|
|
8015
8124
|
var CACHE_FILENAME2 = "kanban-nudge-state.json";
|
|
8016
8125
|
var KANBAN_NUDGE_STATE_VERSION = 1;
|
|
8017
8126
|
function getKanbanNudgeStateFile(configDir) {
|
|
8018
|
-
return
|
|
8127
|
+
return join35(configDir, CACHE_FILENAME2);
|
|
8019
8128
|
}
|
|
8020
8129
|
function loadKanbanNudgeState(target, configDir) {
|
|
8021
8130
|
const path = getKanbanNudgeStateFile(configDir);
|
|
@@ -8052,7 +8161,7 @@ function loadKanbanNudgeState(target, configDir) {
|
|
|
8052
8161
|
function saveKanbanNudgeState(source, configDir) {
|
|
8053
8162
|
const path = getKanbanNudgeStateFile(configDir);
|
|
8054
8163
|
const agents = {};
|
|
8055
|
-
for (const [codeName,
|
|
8164
|
+
for (const [codeName, state10] of source) agents[codeName] = state10;
|
|
8056
8165
|
try {
|
|
8057
8166
|
writeFileSync13(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
8058
8167
|
} catch {
|
|
@@ -8642,7 +8751,7 @@ function closeSessionRunForCode(codeName, outcome, reason) {
|
|
|
8642
8751
|
import { createHash as createHash15 } from "crypto";
|
|
8643
8752
|
import { writeFileSync as writeFileSync14, renameSync as renameSync8, mkdirSync as mkdirSync11, readFileSync as readFileSync28, unlinkSync as unlinkSync3 } from "fs";
|
|
8644
8753
|
import { homedir as homedir14 } from "os";
|
|
8645
|
-
import { join as
|
|
8754
|
+
import { join as join36, dirname as dirname9 } from "path";
|
|
8646
8755
|
|
|
8647
8756
|
// src/lib/manager/scheduler/notify.ts
|
|
8648
8757
|
import { createHash as createHash14 } from "crypto";
|
|
@@ -8892,8 +9001,8 @@ async function runScheduledCardDelivery(codeName, agentId, cardId, completedBy,
|
|
|
8892
9001
|
markScheduledCardDeliveryComplete(cardId);
|
|
8893
9002
|
return "terminal";
|
|
8894
9003
|
}
|
|
8895
|
-
const
|
|
8896
|
-
const task =
|
|
9004
|
+
const state10 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
|
|
9005
|
+
const task = state10.tasks[card.source_ref];
|
|
8897
9006
|
if (!task) {
|
|
8898
9007
|
log(`[scheduled-kanban] delivery: no scheduler task for source_ref=${card.source_ref} on '${codeName}' \u2014 skipping`);
|
|
8899
9008
|
markScheduledCardDeliveryComplete(cardId);
|
|
@@ -9001,7 +9110,7 @@ function resolveScheduledSlackTarget(task) {
|
|
|
9001
9110
|
}
|
|
9002
9111
|
function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
9003
9112
|
try {
|
|
9004
|
-
const file =
|
|
9113
|
+
const file = join36(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
9005
9114
|
const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
|
|
9006
9115
|
const tmp = `${file}.tmp`;
|
|
9007
9116
|
writeFileSync14(tmp, JSON.stringify(marker), "utf8");
|
|
@@ -9011,7 +9120,7 @@ function stampScheduledTurnMarker(codeName, taskId, target) {
|
|
|
9011
9120
|
}
|
|
9012
9121
|
}
|
|
9013
9122
|
function clearScheduledTurnMarkerForTask(codeName, taskId) {
|
|
9014
|
-
const file =
|
|
9123
|
+
const file = join36(homedir14(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
|
|
9015
9124
|
try {
|
|
9016
9125
|
const raw = JSON.parse(readFileSync28(file, "utf8"));
|
|
9017
9126
|
if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
|
|
@@ -9233,11 +9342,11 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
9233
9342
|
// src/lib/manager/scheduler/execution.ts
|
|
9234
9343
|
import { createHash as createHash16 } from "crypto";
|
|
9235
9344
|
import { homedir as homedir15 } from "os";
|
|
9236
|
-
import { join as
|
|
9345
|
+
import { join as join38 } from "path";
|
|
9237
9346
|
|
|
9238
9347
|
// src/lib/agent-serving-probe.ts
|
|
9239
|
-
import { readFileSync as readFileSync29, readdirSync as
|
|
9240
|
-
import { join as
|
|
9348
|
+
import { readFileSync as readFileSync29, readdirSync as readdirSync9, statSync as statSync11 } from "fs";
|
|
9349
|
+
import { join as join37 } from "path";
|
|
9241
9350
|
var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
|
|
9242
9351
|
function probeRateLimit(args) {
|
|
9243
9352
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
@@ -9246,16 +9355,16 @@ function probeRateLimit(args) {
|
|
|
9246
9355
|
const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
|
|
9247
9356
|
let entries;
|
|
9248
9357
|
try {
|
|
9249
|
-
entries =
|
|
9358
|
+
entries = readdirSync9(dir);
|
|
9250
9359
|
} catch {
|
|
9251
9360
|
return UNKNOWN_RATE_LIMIT;
|
|
9252
9361
|
}
|
|
9253
9362
|
let newest = UNKNOWN_RATE_LIMIT;
|
|
9254
9363
|
for (const name of entries) {
|
|
9255
9364
|
if (!name.endsWith(".jsonl")) continue;
|
|
9256
|
-
const path =
|
|
9365
|
+
const path = join37(dir, name);
|
|
9257
9366
|
try {
|
|
9258
|
-
const st =
|
|
9367
|
+
const st = statSync11(path);
|
|
9259
9368
|
if (!st.isFile() || st.mtimeMs < startMs) continue;
|
|
9260
9369
|
} catch {
|
|
9261
9370
|
continue;
|
|
@@ -9324,7 +9433,7 @@ function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
|
|
|
9324
9433
|
|
|
9325
9434
|
// src/lib/manager/scheduler/execution.ts
|
|
9326
9435
|
function claudePidFilePath() {
|
|
9327
|
-
return
|
|
9436
|
+
return join38(homedir15(), ".augmented", "manager-claude-pids.json");
|
|
9328
9437
|
}
|
|
9329
9438
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
9330
9439
|
function registerClaudeSpawn(record) {
|
|
@@ -9352,16 +9461,16 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
9352
9461
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
9353
9462
|
if (combinedHash !== prevHash) {
|
|
9354
9463
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
9355
|
-
const
|
|
9356
|
-
claudeSchedulerStates.set(codeName,
|
|
9464
|
+
const state11 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
9465
|
+
claudeSchedulerStates.set(codeName, state11);
|
|
9357
9466
|
agentState.knownTasksHashes.set(agent.agent_id, combinedHash);
|
|
9358
9467
|
log(`[claude-scheduler] Tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
|
|
9359
9468
|
}
|
|
9360
9469
|
if (!claudeSchedulerStates.has(codeName)) {
|
|
9361
9470
|
claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
9362
9471
|
}
|
|
9363
|
-
const
|
|
9364
|
-
const ready = getReadyTasks(
|
|
9472
|
+
const state10 = claudeSchedulerStates.get(codeName);
|
|
9473
|
+
const ready = getReadyTasks(state10, inFlightClaudeTasks);
|
|
9365
9474
|
if (ready.length === 0) return;
|
|
9366
9475
|
const limitedUntil = readUsageCapUntil({ codeName, projectDir: getProjectDir(codeName) });
|
|
9367
9476
|
if (limitedUntil) {
|
|
@@ -9406,8 +9515,8 @@ function observeBlockedPrompt(codeName, hasSession, capture) {
|
|
|
9406
9515
|
const kind = classifyUnanswerablePane(pane);
|
|
9407
9516
|
return kind ? { state: "blocked", kind } : { state: "clear" };
|
|
9408
9517
|
}
|
|
9409
|
-
function carriedRecoveryFor(
|
|
9410
|
-
return
|
|
9518
|
+
function carriedRecoveryFor(state10, pending2, codeName) {
|
|
9519
|
+
return state10 === "clear" ? pending2.get(codeName) : void 0;
|
|
9411
9520
|
}
|
|
9412
9521
|
function foldPendingRecovery(cost, carried) {
|
|
9413
9522
|
const total = carried ? {
|
|
@@ -9524,8 +9633,8 @@ var BlockedPromptCostLedger = class {
|
|
|
9524
9633
|
};
|
|
9525
9634
|
|
|
9526
9635
|
// src/lib/occupancy-gate.ts
|
|
9527
|
-
import { closeSync as
|
|
9528
|
-
import { join as
|
|
9636
|
+
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync10, readSync as readSync3, statSync as statSync12 } from "fs";
|
|
9637
|
+
import { join as join39 } from "path";
|
|
9529
9638
|
function rostersMeasuredZero(mode, attested, runtimeRunning) {
|
|
9530
9639
|
return mode === "enforce" && attested && runtimeRunning;
|
|
9531
9640
|
}
|
|
@@ -9539,9 +9648,9 @@ var brackets = /* @__PURE__ */ new Map();
|
|
|
9539
9648
|
function readAlignedTail(path, tailBytes, maxAlignBytes) {
|
|
9540
9649
|
let fd = null;
|
|
9541
9650
|
try {
|
|
9542
|
-
const size =
|
|
9651
|
+
const size = statSync12(path).size;
|
|
9543
9652
|
if (size <= 0) return { content: "", complete: true, truncated: false };
|
|
9544
|
-
fd =
|
|
9653
|
+
fd = openSync3(path, "r");
|
|
9545
9654
|
let readStart = Math.max(0, size - tailBytes);
|
|
9546
9655
|
if (readStart > 0) {
|
|
9547
9656
|
const scanFloor = Math.max(0, readStart - maxAlignBytes);
|
|
@@ -9552,7 +9661,7 @@ function readAlignedTail(path, tailBytes, maxAlignBytes) {
|
|
|
9552
9661
|
const from = Math.max(scanFloor, pos - CHUNK);
|
|
9553
9662
|
const len2 = pos - from;
|
|
9554
9663
|
const b = Buffer.allocUnsafe(len2);
|
|
9555
|
-
if (
|
|
9664
|
+
if (readSync3(fd, b, 0, len2, from) !== len2) return null;
|
|
9556
9665
|
const idx = b.lastIndexOf(10);
|
|
9557
9666
|
if (idx !== -1) {
|
|
9558
9667
|
boundary = from + idx + 1;
|
|
@@ -9570,14 +9679,14 @@ function readAlignedTail(path, tailBytes, maxAlignBytes) {
|
|
|
9570
9679
|
}
|
|
9571
9680
|
const len = size - readStart;
|
|
9572
9681
|
const buf = Buffer.allocUnsafe(len);
|
|
9573
|
-
if (
|
|
9682
|
+
if (readSync3(fd, buf, 0, len, readStart) !== len) return null;
|
|
9574
9683
|
return { content: buf.toString("utf-8", 0, len), complete: true, truncated: readStart > 0 };
|
|
9575
9684
|
} catch {
|
|
9576
9685
|
return null;
|
|
9577
9686
|
} finally {
|
|
9578
9687
|
if (fd != null) {
|
|
9579
9688
|
try {
|
|
9580
|
-
|
|
9689
|
+
closeSync3(fd);
|
|
9581
9690
|
} catch {
|
|
9582
9691
|
}
|
|
9583
9692
|
}
|
|
@@ -9609,42 +9718,42 @@ function candidateTranscriptPaths(dir) {
|
|
|
9609
9718
|
const paths = [];
|
|
9610
9719
|
let top;
|
|
9611
9720
|
try {
|
|
9612
|
-
top =
|
|
9721
|
+
top = readdirSync10(dir);
|
|
9613
9722
|
} catch {
|
|
9614
9723
|
return { paths, complete: false };
|
|
9615
9724
|
}
|
|
9616
9725
|
let complete = true;
|
|
9617
9726
|
for (const name of top) {
|
|
9618
9727
|
if (name.endsWith(".jsonl")) {
|
|
9619
|
-
paths.push(
|
|
9728
|
+
paths.push(join39(dir, name));
|
|
9620
9729
|
continue;
|
|
9621
9730
|
}
|
|
9622
|
-
const subDir =
|
|
9731
|
+
const subDir = join39(dir, name, "subagents");
|
|
9623
9732
|
let subs;
|
|
9624
9733
|
try {
|
|
9625
|
-
subs =
|
|
9734
|
+
subs = readdirSync10(subDir);
|
|
9626
9735
|
} catch (err) {
|
|
9627
9736
|
if (!isAbsentDirError(err)) complete = false;
|
|
9628
9737
|
continue;
|
|
9629
9738
|
}
|
|
9630
9739
|
for (const sub of subs) {
|
|
9631
|
-
if (sub.endsWith(".jsonl")) paths.push(
|
|
9740
|
+
if (sub.endsWith(".jsonl")) paths.push(join39(subDir, sub));
|
|
9632
9741
|
}
|
|
9633
9742
|
}
|
|
9634
9743
|
return { paths, complete };
|
|
9635
9744
|
}
|
|
9636
9745
|
function foldToolCallBrackets(codeName, eventsByPath, nowMs) {
|
|
9637
|
-
const
|
|
9746
|
+
const state10 = brackets.get(codeName) ?? {
|
|
9638
9747
|
open: /* @__PURE__ */ new Map(),
|
|
9639
9748
|
closed: []
|
|
9640
9749
|
};
|
|
9641
9750
|
const nextOpen = /* @__PURE__ */ new Map();
|
|
9642
9751
|
const openOut = [];
|
|
9643
|
-
const paths = /* @__PURE__ */ new Set([...
|
|
9752
|
+
const paths = /* @__PURE__ */ new Set([...state10.open.keys(), ...eventsByPath.keys()]);
|
|
9644
9753
|
for (const path of paths) {
|
|
9645
|
-
const carried =
|
|
9754
|
+
const carried = state10.open.get(path) ?? [];
|
|
9646
9755
|
const paired = pairToolCallBrackets(eventsByPath.get(path) ?? [], carried);
|
|
9647
|
-
|
|
9756
|
+
state10.closed.push(...paired.brackets);
|
|
9648
9757
|
const live = paired.open.filter((c) => nowMs - c.startMs <= MAX_BRACKET_DEFERRAL_MS);
|
|
9649
9758
|
if (live.length > 0) {
|
|
9650
9759
|
nextOpen.set(path, live);
|
|
@@ -9654,7 +9763,7 @@ function foldToolCallBrackets(codeName, eventsByPath, nowMs) {
|
|
|
9654
9763
|
const keepFrom = nowMs - GATE_MAX_BUCKET_AGE_MS;
|
|
9655
9764
|
const seen = /* @__PURE__ */ new Set();
|
|
9656
9765
|
const closed = [];
|
|
9657
|
-
for (const b of
|
|
9766
|
+
for (const b of state10.closed) {
|
|
9658
9767
|
if (b.endMs < keepFrom) continue;
|
|
9659
9768
|
const key = `${b.id}\0${b.startMs}\0${b.endMs}`;
|
|
9660
9769
|
if (seen.has(key)) continue;
|
|
@@ -9683,7 +9792,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
|
|
|
9683
9792
|
for (const path of paths) {
|
|
9684
9793
|
let st;
|
|
9685
9794
|
try {
|
|
9686
|
-
st =
|
|
9795
|
+
st = statSync12(path);
|
|
9687
9796
|
} catch (err) {
|
|
9688
9797
|
if (!isAbsentDirError(err)) complete = false;
|
|
9689
9798
|
continue;
|
|
@@ -9789,7 +9898,7 @@ function qualifyBuckets(buckets, qualifying, mode, nowMs, neighbourhoodMs = DEFA
|
|
|
9789
9898
|
}
|
|
9790
9899
|
|
|
9791
9900
|
// src/lib/pane-occupancy-sampler.ts
|
|
9792
|
-
import { statSync as
|
|
9901
|
+
import { statSync as statSync13 } from "fs";
|
|
9793
9902
|
var SAMPLE_INTERVAL_MS = 1e4;
|
|
9794
9903
|
var IDLE_GAP_MS = 12e4;
|
|
9795
9904
|
var POST_IDLE_CREDIT_MS = 6e4;
|
|
@@ -9803,7 +9912,7 @@ function hasFreshPaneObservation(codeName, nowMs, maxAgeMs = OBSERVATION_FRESH_M
|
|
|
9803
9912
|
}
|
|
9804
9913
|
function paneMtimeMs(codeName) {
|
|
9805
9914
|
try {
|
|
9806
|
-
return
|
|
9915
|
+
return statSync13(paneLogPath(codeName)).mtimeMs;
|
|
9807
9916
|
} catch {
|
|
9808
9917
|
return null;
|
|
9809
9918
|
}
|
|
@@ -9937,8 +10046,8 @@ function countDefunct(cgroupDir, readText) {
|
|
|
9937
10046
|
if (stat2 == null) continue;
|
|
9938
10047
|
const close = stat2.lastIndexOf(")");
|
|
9939
10048
|
if (close < 0) continue;
|
|
9940
|
-
const
|
|
9941
|
-
if (
|
|
10049
|
+
const state10 = stat2.slice(close + 1).trim().charAt(0);
|
|
10050
|
+
if (state10 === "Z") defunct += 1;
|
|
9942
10051
|
}
|
|
9943
10052
|
return defunct;
|
|
9944
10053
|
}
|
|
@@ -11188,16 +11297,16 @@ async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
|
11188
11297
|
const tasksHash = createHash18("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
11189
11298
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
11190
11299
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
11191
|
-
const
|
|
11192
|
-
opencodeSchedulerStates.set(codeName,
|
|
11300
|
+
const state11 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
11301
|
+
opencodeSchedulerStates.set(codeName, state11);
|
|
11193
11302
|
knownOpencodeTaskHashes.set(agent.agent_id, tasksHash);
|
|
11194
11303
|
log(`[opencode-scheduler] tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
|
|
11195
11304
|
}
|
|
11196
11305
|
if (!opencodeSchedulerStates.has(codeName)) {
|
|
11197
11306
|
opencodeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
11198
11307
|
}
|
|
11199
|
-
const
|
|
11200
|
-
const ready = getReadyTasks(
|
|
11308
|
+
const state10 = opencodeSchedulerStates.get(codeName);
|
|
11309
|
+
const ready = getReadyTasks(state10, inFlightOpencodeTasks);
|
|
11201
11310
|
if (ready.length === 0) return;
|
|
11202
11311
|
if (!isOpencodeSessionHealthy(codeName)) {
|
|
11203
11312
|
log(`[opencode-scheduler] '${codeName}' has ${ready.length} due task(s) but no healthy serve yet - deferring`);
|
|
@@ -11266,7 +11375,7 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
11266
11375
|
import { createHash as createHash19 } from "crypto";
|
|
11267
11376
|
import { existsSync as existsSync17, mkdirSync as mkdirSync12, readFileSync as readFileSync31, renameSync as renameSync9, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
|
|
11268
11377
|
import { randomUUID } from "crypto";
|
|
11269
|
-
import { join as
|
|
11378
|
+
import { join as join40 } from "path";
|
|
11270
11379
|
|
|
11271
11380
|
// src/lib/telegram-ingest.ts
|
|
11272
11381
|
import https2 from "https";
|
|
@@ -11919,7 +12028,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
11919
12028
|
let filePath;
|
|
11920
12029
|
try {
|
|
11921
12030
|
dir = getFramework("opencode").getAgentDir(codeName);
|
|
11922
|
-
filePath =
|
|
12031
|
+
filePath = join40(dir, "telegram-getupdates-offset-opencode.json");
|
|
11923
12032
|
} catch {
|
|
11924
12033
|
dir = null;
|
|
11925
12034
|
filePath = null;
|
|
@@ -12182,10 +12291,10 @@ function recordWedgeForCards(states, inProgressCardIds, nowMs, config2) {
|
|
|
12182
12291
|
function pruneCardStates(states, liveInProgressCardIds, nowMs, config2) {
|
|
12183
12292
|
const live = liveInProgressCardIds instanceof Set ? liveInProgressCardIds : new Set(liveInProgressCardIds);
|
|
12184
12293
|
const next = /* @__PURE__ */ new Map();
|
|
12185
|
-
for (const [id,
|
|
12294
|
+
for (const [id, state10] of states) {
|
|
12186
12295
|
if (!live.has(id)) continue;
|
|
12187
|
-
if (nowMs -
|
|
12188
|
-
next.set(id,
|
|
12296
|
+
if (nowMs - state10.lastWedgeAtMs > config2.cooldownMs) continue;
|
|
12297
|
+
next.set(id, state10);
|
|
12189
12298
|
}
|
|
12190
12299
|
return next;
|
|
12191
12300
|
}
|
|
@@ -12203,24 +12312,24 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
12203
12312
|
}
|
|
12204
12313
|
|
|
12205
12314
|
// src/lib/restart-flags.ts
|
|
12206
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync13, readdirSync as
|
|
12315
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync13, readdirSync as readdirSync11, readFileSync as readFileSync32, renameSync as renameSync10, rmSync as rmSync7, writeFileSync as writeFileSync16 } from "fs";
|
|
12207
12316
|
import { homedir as homedir16 } from "os";
|
|
12208
|
-
import { join as
|
|
12317
|
+
import { join as join41 } from "path";
|
|
12209
12318
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
12210
12319
|
function restartFlagsDir() {
|
|
12211
|
-
return
|
|
12320
|
+
return join41(homedir16(), ".augmented", "restart-flags");
|
|
12212
12321
|
}
|
|
12213
12322
|
function flagPath(codeName) {
|
|
12214
|
-
return
|
|
12323
|
+
return join41(restartFlagsDir(), `${codeName}.flag`);
|
|
12215
12324
|
}
|
|
12216
12325
|
function readRestartFlags() {
|
|
12217
12326
|
const dir = restartFlagsDir();
|
|
12218
12327
|
if (!existsSync18(dir)) return [];
|
|
12219
12328
|
const out = [];
|
|
12220
|
-
for (const entry of
|
|
12329
|
+
for (const entry of readdirSync11(dir)) {
|
|
12221
12330
|
if (!entry.endsWith(".flag")) continue;
|
|
12222
12331
|
try {
|
|
12223
|
-
const raw = readFileSync32(
|
|
12332
|
+
const raw = readFileSync32(join41(dir, entry), "utf8");
|
|
12224
12333
|
const parsed = JSON.parse(raw);
|
|
12225
12334
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
12226
12335
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -12338,8 +12447,8 @@ async function sendError(flag, opts, text) {
|
|
|
12338
12447
|
}
|
|
12339
12448
|
|
|
12340
12449
|
// src/lib/restart-context.ts
|
|
12341
|
-
import { readdirSync as
|
|
12342
|
-
import { dirname as dirname10, join as
|
|
12450
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync33, writeFileSync as writeFileSync17, mkdirSync as mkdirSync14, unlinkSync as unlinkSync5 } from "fs";
|
|
12451
|
+
import { dirname as dirname10, join as join42 } from "path";
|
|
12343
12452
|
var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
|
|
12344
12453
|
var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
|
|
12345
12454
|
var MAX_TOPIC_CHARS = 140;
|
|
@@ -12351,10 +12460,10 @@ function augmentedAgentDir(codeName) {
|
|
|
12351
12460
|
return dirname10(getProjectDir(codeName));
|
|
12352
12461
|
}
|
|
12353
12462
|
function slackPendingInboundDir(codeName) {
|
|
12354
|
-
return
|
|
12463
|
+
return join42(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
|
|
12355
12464
|
}
|
|
12356
12465
|
function slackRestartContextDir(codeName) {
|
|
12357
|
-
return
|
|
12466
|
+
return join42(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
|
|
12358
12467
|
}
|
|
12359
12468
|
function sanitizeTopic(raw) {
|
|
12360
12469
|
const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -12389,7 +12498,7 @@ function computeRestartContextHints(markers, allTurns, nowMs, reconstruct = reco
|
|
|
12389
12498
|
}
|
|
12390
12499
|
function safeReaddir(dir) {
|
|
12391
12500
|
try {
|
|
12392
|
-
return
|
|
12501
|
+
return readdirSync12(dir);
|
|
12393
12502
|
} catch {
|
|
12394
12503
|
return [];
|
|
12395
12504
|
}
|
|
@@ -12414,7 +12523,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
|
|
|
12414
12523
|
if (!filename.endsWith(".json")) continue;
|
|
12415
12524
|
if (freshFilenames.has(filename)) continue;
|
|
12416
12525
|
try {
|
|
12417
|
-
unlinkSync5(
|
|
12526
|
+
unlinkSync5(join42(ctxDir, filename));
|
|
12418
12527
|
} catch {
|
|
12419
12528
|
}
|
|
12420
12529
|
}
|
|
@@ -12435,7 +12544,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
12435
12544
|
}
|
|
12436
12545
|
const markers = [];
|
|
12437
12546
|
for (const filename of markerFilenames.slice(0, cap)) {
|
|
12438
|
-
const parsed = readStrandedMarker(
|
|
12547
|
+
const parsed = readStrandedMarker(join42(markerDir, filename));
|
|
12439
12548
|
if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
|
|
12440
12549
|
}
|
|
12441
12550
|
if (markers.length === 0) {
|
|
@@ -12449,7 +12558,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
|
|
|
12449
12558
|
const freshFilenames = /* @__PURE__ */ new Set();
|
|
12450
12559
|
for (const { filename, hint } of hints) {
|
|
12451
12560
|
try {
|
|
12452
|
-
writeHintFile(
|
|
12561
|
+
writeHintFile(join42(ctxDir, filename), ctxDir, hint);
|
|
12453
12562
|
freshFilenames.add(filename);
|
|
12454
12563
|
} catch (err) {
|
|
12455
12564
|
log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
|
|
@@ -13182,8 +13291,8 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
|
|
|
13182
13291
|
function shouldSkipRevokedCleanup(previousKnownStatus) {
|
|
13183
13292
|
return previousKnownStatus === "revoked";
|
|
13184
13293
|
}
|
|
13185
|
-
function hasRevokedResiduals(
|
|
13186
|
-
return
|
|
13294
|
+
function hasRevokedResiduals(state10) {
|
|
13295
|
+
return state10.gatewayRunning || state10.portAllocated || state10.provisionDirExists;
|
|
13187
13296
|
}
|
|
13188
13297
|
var pendingSessionRestarts = /* @__PURE__ */ new Map();
|
|
13189
13298
|
var lastRestartWasExternal = /* @__PURE__ */ new Map();
|
|
@@ -13413,12 +13522,12 @@ function maybeClearStaleTrip(agent) {
|
|
|
13413
13522
|
const marker = getAutoResumeMarker(codeName);
|
|
13414
13523
|
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
13415
13524
|
if (!isSelfResume) deleteAutoResumeMarker(codeName);
|
|
13416
|
-
|
|
13417
|
-
...
|
|
13525
|
+
state9 = {
|
|
13526
|
+
...state9,
|
|
13418
13527
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
13419
13528
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
13420
13529
|
};
|
|
13421
|
-
send({ type: "state-update", state:
|
|
13530
|
+
send({ type: "state-update", state: state9 });
|
|
13422
13531
|
}
|
|
13423
13532
|
var autoResumeMarkers = /* @__PURE__ */ new Map();
|
|
13424
13533
|
function autoResumeMarkerKey(codeName) {
|
|
@@ -13521,12 +13630,12 @@ function maybeAutoResume(agent) {
|
|
|
13521
13630
|
restartBreaker.clear(codeName);
|
|
13522
13631
|
reportedTrips.delete(codeName);
|
|
13523
13632
|
dependencyRecoveryLedger.clear(codeName);
|
|
13524
|
-
|
|
13525
|
-
...
|
|
13633
|
+
state9 = {
|
|
13634
|
+
...state9,
|
|
13526
13635
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
13527
13636
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
13528
13637
|
};
|
|
13529
|
-
send({ type: "state-update", state:
|
|
13638
|
+
send({ type: "state-update", state: state9 });
|
|
13530
13639
|
log(`[auto-resume] agent=${codeName} resumed \u2014 re-trip within backoff window will stay paused (ENG-6088)`);
|
|
13531
13640
|
} else {
|
|
13532
13641
|
autoResumeStandDowns.add(`${codeName}:${trippedAt}`);
|
|
@@ -13635,12 +13744,12 @@ async function maybeResumeReconcile(agent) {
|
|
|
13635
13744
|
restartBreaker.clear(codeName);
|
|
13636
13745
|
reportedTrips.delete(codeName);
|
|
13637
13746
|
dependencyRecoveryLedger.clear(codeName);
|
|
13638
|
-
|
|
13639
|
-
...
|
|
13747
|
+
state9 = {
|
|
13748
|
+
...state9,
|
|
13640
13749
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
13641
13750
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
13642
13751
|
};
|
|
13643
|
-
send({ type: "state-update", state:
|
|
13752
|
+
send({ type: "state-update", state: state9 });
|
|
13644
13753
|
log(`[resume-reconciler] agent=${codeName} resumed \u2014 a re-trip within the backoff window will latch unstable (ENG-6383)`);
|
|
13645
13754
|
} else {
|
|
13646
13755
|
autoResumeStandDowns.add(standDownKey);
|
|
@@ -13931,7 +14040,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
|
|
|
13931
14040
|
var dayRolloverInboundHold = /* @__PURE__ */ new Map();
|
|
13932
14041
|
var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
|
|
13933
14042
|
async function channelInboundActivityAgeSecondsFor(codeName) {
|
|
13934
|
-
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-
|
|
14043
|
+
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-BFDPJWZE.js");
|
|
13935
14044
|
const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
|
|
13936
14045
|
if (newest === null) return null;
|
|
13937
14046
|
return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
|
|
@@ -14086,7 +14195,7 @@ function performLazyDayRolloverReset(codeName, agentTimezone) {
|
|
|
14086
14195
|
}
|
|
14087
14196
|
function paneLogAgeSecondsFor(codeName) {
|
|
14088
14197
|
try {
|
|
14089
|
-
const mtimeMs =
|
|
14198
|
+
const mtimeMs = statSync14(paneLogPath(codeName)).mtimeMs;
|
|
14090
14199
|
return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
|
|
14091
14200
|
} catch (err) {
|
|
14092
14201
|
if (err?.code === "ENOENT") return null;
|
|
@@ -14135,7 +14244,7 @@ function restartGateFor(codeName, reason) {
|
|
|
14135
14244
|
}
|
|
14136
14245
|
function isHostBusyForForcedUpdate(opts) {
|
|
14137
14246
|
const now = /* @__PURE__ */ new Date();
|
|
14138
|
-
for (const agent of
|
|
14247
|
+
for (const agent of state9.agents) {
|
|
14139
14248
|
const decision = decideRestartGate({
|
|
14140
14249
|
window: null,
|
|
14141
14250
|
paneLogAgeSeconds: paneLogAgeSecondsFor(agent.codeName),
|
|
@@ -14168,7 +14277,7 @@ function runPendingForcedUpdate() {
|
|
|
14168
14277
|
relaxed
|
|
14169
14278
|
} = decidePendingForcedUpdate({
|
|
14170
14279
|
requestedAt: requestedUpdateAt,
|
|
14171
|
-
lastProcessedAt:
|
|
14280
|
+
lastProcessedAt: state9.lastUpdateRequestProcessedAt ?? null,
|
|
14172
14281
|
deferStreak: forcedUpdateDeferStreak,
|
|
14173
14282
|
nowMs: Date.now(),
|
|
14174
14283
|
isHostBusy: (isRelaxed) => isHostBusyForForcedUpdate({ relaxed: isRelaxed })
|
|
@@ -14211,7 +14320,7 @@ function runPendingForcedUpdate() {
|
|
|
14211
14320
|
forcedUpdate === "consume-deadline" ? `[self-update] WARN "Update CLI now" requested at ${requestedUpdateAt} has been pending ${describePendingFor(pendingForMs)} and the host still reads busy \u2014 running the window-bypassing self-update anyway (ENG-8449 hard deadline). A live turn may be interrupted; the operator asked for this update explicitly.` : `[self-update] "Update CLI now" requested at ${requestedUpdateAt} \u2014 running window-bypassing self-update now (host idle${relaxed ? ", relaxed gate" : ""}).`
|
|
14212
14321
|
);
|
|
14213
14322
|
}
|
|
14214
|
-
const prevProcessedAt =
|
|
14323
|
+
const prevProcessedAt = state9.lastUpdateRequestProcessedAt ?? null;
|
|
14215
14324
|
const attemptStartedMs = Date.now();
|
|
14216
14325
|
void checkAndUpdateCli({ force: true }).then((outcome) => {
|
|
14217
14326
|
if (!shouldConsumeForcedUpdate(outcome)) {
|
|
@@ -14233,11 +14342,11 @@ function runPendingForcedUpdate() {
|
|
|
14233
14342
|
log(
|
|
14234
14343
|
outcome === "updated" ? `[self-update] "Update CLI now" completed \u2014 upgrade installed; manager restart scheduled.` : `[self-update] "Update CLI now" completed \u2014 host was already on the latest in-channel build; nothing to install.`
|
|
14235
14344
|
);
|
|
14236
|
-
|
|
14345
|
+
state9.lastUpdateRequestProcessedAt = requestedUpdateAt;
|
|
14237
14346
|
try {
|
|
14238
|
-
atomicWriteFileSync(getStateFile(), JSON.stringify(
|
|
14347
|
+
atomicWriteFileSync(getStateFile(), JSON.stringify(state9, null, 2));
|
|
14239
14348
|
} catch (err) {
|
|
14240
|
-
|
|
14349
|
+
state9.lastUpdateRequestProcessedAt = prevProcessedAt;
|
|
14241
14350
|
log(
|
|
14242
14351
|
`[self-update] failed to persist update-request ack; retrying next poll: ${err.message}`
|
|
14243
14352
|
);
|
|
@@ -14256,7 +14365,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
|
14256
14365
|
var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
14257
14366
|
function projectMcpHash(_codeName, projectDir) {
|
|
14258
14367
|
try {
|
|
14259
|
-
const raw = readFileSync34(
|
|
14368
|
+
const raw = readFileSync34(join43(projectDir, ".mcp.json"), "utf-8");
|
|
14260
14369
|
return createHash20("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
14261
14370
|
} catch {
|
|
14262
14371
|
return null;
|
|
@@ -14264,7 +14373,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
14264
14373
|
}
|
|
14265
14374
|
function projectMcpKeys(_codeName, projectDir) {
|
|
14266
14375
|
try {
|
|
14267
|
-
const raw = readFileSync34(
|
|
14376
|
+
const raw = readFileSync34(join43(projectDir, ".mcp.json"), "utf-8");
|
|
14268
14377
|
const parsed = JSON.parse(raw);
|
|
14269
14378
|
const servers = parsed.mcpServers;
|
|
14270
14379
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -14282,7 +14391,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
|
|
|
14282
14391
|
else runningMcpServerKeys.delete(codeName);
|
|
14283
14392
|
let launchStructure = null;
|
|
14284
14393
|
try {
|
|
14285
|
-
const raw = readFileSync34(
|
|
14394
|
+
const raw = readFileSync34(join43(projectDir, ".mcp.json"), "utf-8");
|
|
14286
14395
|
launchStructure = managedMcpStructureHashFromFile(
|
|
14287
14396
|
JSON.parse(raw),
|
|
14288
14397
|
isManagedMcpServerKey
|
|
@@ -14417,7 +14526,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
|
|
|
14417
14526
|
if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
|
|
14418
14527
|
let mcpJsonForRebind = null;
|
|
14419
14528
|
try {
|
|
14420
|
-
mcpJsonForRebind = JSON.parse(readFileSync34(
|
|
14529
|
+
mcpJsonForRebind = JSON.parse(readFileSync34(join43(projectDir, ".mcp.json"), "utf-8"));
|
|
14421
14530
|
} catch {
|
|
14422
14531
|
mcpJsonForRebind = null;
|
|
14423
14532
|
}
|
|
@@ -14566,7 +14675,7 @@ function shouldInjectChannelSecrets(agentId) {
|
|
|
14566
14675
|
function projectChannelSecretHash(projectDir) {
|
|
14567
14676
|
try {
|
|
14568
14677
|
const entries = parseEnvIntegrations(
|
|
14569
|
-
readFileSync34(
|
|
14678
|
+
readFileSync34(join43(projectDir, ".env.integrations"), "utf-8")
|
|
14570
14679
|
);
|
|
14571
14680
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
14572
14681
|
} catch {
|
|
@@ -14607,7 +14716,7 @@ var STALE_TASK_THRESHOLD_MS = (() => {
|
|
|
14607
14716
|
})();
|
|
14608
14717
|
var taskDisplayInfo = /* @__PURE__ */ new Map();
|
|
14609
14718
|
var activeChannels = /* @__PURE__ */ new Map();
|
|
14610
|
-
var
|
|
14719
|
+
var state9 = {
|
|
14611
14720
|
pid: process.pid,
|
|
14612
14721
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14613
14722
|
lastPollAt: null,
|
|
@@ -14677,7 +14786,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
14677
14786
|
var lastVersionCheckAt = 0;
|
|
14678
14787
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
14679
14788
|
var lastResponsivenessProbeAt = 0;
|
|
14680
|
-
var agtCliVersion = true ? "0.28.
|
|
14789
|
+
var agtCliVersion = true ? "0.28.1048" : "dev";
|
|
14681
14790
|
function resolveBrewPath(execFileSync3) {
|
|
14682
14791
|
try {
|
|
14683
14792
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -15004,7 +15113,7 @@ function runAsync(cmd, args, opts) {
|
|
|
15004
15113
|
});
|
|
15005
15114
|
}
|
|
15006
15115
|
function claudeManagedSettingsPath() {
|
|
15007
|
-
return
|
|
15116
|
+
return join43(CLAUDE_MANAGED_SETTINGS_DIR, "managed-settings.json");
|
|
15008
15117
|
}
|
|
15009
15118
|
var MANAGED_SETTINGS_KEYS = ["channelsEnabled", "enableAllProjectMcpServers"];
|
|
15010
15119
|
var MANAGED_SETTINGS_ENV = { DISABLE_AUTOUPDATER: "1" };
|
|
@@ -15079,7 +15188,7 @@ async function ensureOpencodeBinary() {
|
|
|
15079
15188
|
try {
|
|
15080
15189
|
const prefix = execFileSync3("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
15081
15190
|
if (prefix) {
|
|
15082
|
-
const npmBin =
|
|
15191
|
+
const npmBin = join43(prefix, "bin");
|
|
15083
15192
|
const current = (process.env.PATH ?? "").split(pathDelimiter);
|
|
15084
15193
|
if (!current.includes(npmBin)) {
|
|
15085
15194
|
process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
|
|
@@ -15219,7 +15328,7 @@ async function maybeUpgradeClaudeCode() {
|
|
|
15219
15328
|
}
|
|
15220
15329
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
15221
15330
|
function selfUpdateAppliedMarkerPath() {
|
|
15222
|
-
return
|
|
15331
|
+
return join43(homedir17(), ".augmented", ".last-self-update-applied");
|
|
15223
15332
|
}
|
|
15224
15333
|
var selfUpdateUpToDateLogged = false;
|
|
15225
15334
|
var selfUpdatePinnedLogged = false;
|
|
@@ -15270,7 +15379,7 @@ async function checkAndUpdateCli(opts) {
|
|
|
15270
15379
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
15271
15380
|
if (!isBrewFormula && !isNpmGlobal) return "noop";
|
|
15272
15381
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
15273
|
-
const markerPath =
|
|
15382
|
+
const markerPath = join43(homedir17(), ".augmented", ".last-update-check");
|
|
15274
15383
|
if (!force) {
|
|
15275
15384
|
try {
|
|
15276
15385
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
@@ -15768,12 +15877,12 @@ async function checkClaudeAuth() {
|
|
|
15768
15877
|
var evalEmptyMcpConfigPath = null;
|
|
15769
15878
|
function ensureEvalEmptyMcpConfig() {
|
|
15770
15879
|
if (evalEmptyMcpConfigPath && existsSync19(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
15771
|
-
const dir =
|
|
15880
|
+
const dir = join43(homedir17(), ".augmented");
|
|
15772
15881
|
try {
|
|
15773
15882
|
mkdirSync15(dir, { recursive: true });
|
|
15774
15883
|
} catch {
|
|
15775
15884
|
}
|
|
15776
|
-
const p =
|
|
15885
|
+
const p = join43(dir, ".eval-empty-mcp.json");
|
|
15777
15886
|
writeFileSync18(p, JSON.stringify({ mcpServers: {} }));
|
|
15778
15887
|
evalEmptyMcpConfigPath = p;
|
|
15779
15888
|
return p;
|
|
@@ -15868,10 +15977,10 @@ function resolveConversationEvalBackend() {
|
|
|
15868
15977
|
return conversationEvalBackend;
|
|
15869
15978
|
}
|
|
15870
15979
|
function getStateFile() {
|
|
15871
|
-
return
|
|
15980
|
+
return join43(config?.configDir ?? join43(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
15872
15981
|
}
|
|
15873
15982
|
function channelHashCacheDir() {
|
|
15874
|
-
return config?.configDir ??
|
|
15983
|
+
return config?.configDir ?? join43(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
15875
15984
|
}
|
|
15876
15985
|
function loadChannelHashCache2() {
|
|
15877
15986
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -15919,21 +16028,21 @@ function recordChannelSyncFailure(failures, agentId, reason, now) {
|
|
|
15919
16028
|
failures.set(agentId, next);
|
|
15920
16029
|
return next;
|
|
15921
16030
|
}
|
|
15922
|
-
function shouldLogChannelSyncFailure(
|
|
15923
|
-
if (
|
|
15924
|
-
if (
|
|
15925
|
-
return
|
|
16031
|
+
function shouldLogChannelSyncFailure(state10) {
|
|
16032
|
+
if (state10.attempts === 1) return true;
|
|
16033
|
+
if (state10.attempts <= CHANNEL_SYNC_FREE_ATTEMPTS) return false;
|
|
16034
|
+
return state10.attempts > state10.loggedAtAttempt;
|
|
15926
16035
|
}
|
|
15927
16036
|
function stuckChannelSyncs(failures, now, thresholdMs = CHANNEL_SYNC_STUCK_AFTER_MS) {
|
|
15928
16037
|
const out = [];
|
|
15929
|
-
for (const [agentId,
|
|
15930
|
-
const stuckForMs = now -
|
|
16038
|
+
for (const [agentId, state10] of failures) {
|
|
16039
|
+
const stuckForMs = now - state10.since;
|
|
15931
16040
|
if (stuckForMs < thresholdMs) continue;
|
|
15932
16041
|
out.push({
|
|
15933
16042
|
agent_id: agentId,
|
|
15934
|
-
attempts:
|
|
16043
|
+
attempts: state10.attempts,
|
|
15935
16044
|
stuck_for_seconds: Math.floor(stuckForMs / 1e3),
|
|
15936
|
-
reason:
|
|
16045
|
+
reason: state10.lastReason
|
|
15937
16046
|
});
|
|
15938
16047
|
}
|
|
15939
16048
|
out.sort((a, b) => b.stuck_for_seconds - a.stuck_for_seconds);
|
|
@@ -16084,7 +16193,7 @@ function removeDeliveryBaselineEntries(agentId) {
|
|
|
16084
16193
|
var _channelQuarantineStore = null;
|
|
16085
16194
|
function channelQuarantineStore() {
|
|
16086
16195
|
if (!_channelQuarantineStore) {
|
|
16087
|
-
const dir = config?.configDir ??
|
|
16196
|
+
const dir = config?.configDir ?? join43(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
16088
16197
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
16089
16198
|
}
|
|
16090
16199
|
return _channelQuarantineStore;
|
|
@@ -16092,7 +16201,7 @@ function channelQuarantineStore() {
|
|
|
16092
16201
|
var _channelResumeHistoryStore = null;
|
|
16093
16202
|
function channelResumeHistoryStore() {
|
|
16094
16203
|
if (!_channelResumeHistoryStore) {
|
|
16095
|
-
const dir = config?.configDir ??
|
|
16204
|
+
const dir = config?.configDir ?? join43(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
16096
16205
|
_channelResumeHistoryStore = new ChannelResumeHistoryStore(defaultResumeHistoryPath(dir));
|
|
16097
16206
|
}
|
|
16098
16207
|
return _channelResumeHistoryStore;
|
|
@@ -16119,12 +16228,12 @@ function claudeMdSizeFor(codeName) {
|
|
|
16119
16228
|
}
|
|
16120
16229
|
function forwardedToolsFor(codeName) {
|
|
16121
16230
|
if (!config?.configDir) return null;
|
|
16122
|
-
return readForwardedToolsReport(
|
|
16231
|
+
return readForwardedToolsReport(join43(config.configDir, codeName));
|
|
16123
16232
|
}
|
|
16124
16233
|
var _hostFlagStore = null;
|
|
16125
16234
|
function hostFlagStore() {
|
|
16126
16235
|
if (!_hostFlagStore) {
|
|
16127
|
-
const dir = config?.configDir ??
|
|
16236
|
+
const dir = config?.configDir ?? join43(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
16128
16237
|
_hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
|
|
16129
16238
|
}
|
|
16130
16239
|
return _hostFlagStore;
|
|
@@ -16197,13 +16306,13 @@ function parseSkillFrontmatter(content) {
|
|
|
16197
16306
|
return out;
|
|
16198
16307
|
}
|
|
16199
16308
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
16200
|
-
const { readdirSync:
|
|
16201
|
-
const skillsDir =
|
|
16202
|
-
const claudeMdPath =
|
|
16309
|
+
const { readdirSync: readdirSync14, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync19 } = await import("fs");
|
|
16310
|
+
const skillsDir = join43(configDir, codeName, "project", ".claude", "skills");
|
|
16311
|
+
const claudeMdPath = join43(configDir, codeName, "project", "CLAUDE.md");
|
|
16203
16312
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
16204
16313
|
const entries = [];
|
|
16205
|
-
for (const dir of
|
|
16206
|
-
const skillFile =
|
|
16314
|
+
for (const dir of readdirSync14(skillsDir).sort()) {
|
|
16315
|
+
const skillFile = join43(skillsDir, dir, "SKILL.md");
|
|
16207
16316
|
if (!ex(skillFile)) continue;
|
|
16208
16317
|
try {
|
|
16209
16318
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -16312,7 +16421,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
16312
16421
|
if (codeNames.length === 0) return;
|
|
16313
16422
|
void (async () => {
|
|
16314
16423
|
try {
|
|
16315
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
16424
|
+
const { collectDiagnostics } = await import("../persistent-session-OSQVHP6N.js");
|
|
16316
16425
|
await api.post("/host/heartbeat", {
|
|
16317
16426
|
host_id: hostId,
|
|
16318
16427
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -16443,7 +16552,7 @@ async function pollCycleInner() {
|
|
|
16443
16552
|
const now = Date.now();
|
|
16444
16553
|
if (now - lastVersionCheckAt > VERSION_CHECK_INTERVAL_MS) {
|
|
16445
16554
|
try {
|
|
16446
|
-
const firstAgent =
|
|
16555
|
+
const firstAgent = state9.agents[0];
|
|
16447
16556
|
const versionAdapter = firstAgent ? resolveAgentFramework(firstAgent.codeName) : getFramework(DEFAULT_FRAMEWORK);
|
|
16448
16557
|
if (versionAdapter.getVersion) {
|
|
16449
16558
|
cachedFrameworkVersion = await versionAdapter.getVersion();
|
|
@@ -16454,7 +16563,7 @@ async function pollCycleInner() {
|
|
|
16454
16563
|
}
|
|
16455
16564
|
try {
|
|
16456
16565
|
const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
|
|
16457
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
16566
|
+
const { collectDiagnostics } = await import("../persistent-session-OSQVHP6N.js");
|
|
16458
16567
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
16459
16568
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
|
|
16460
16569
|
let tailscaleHostname;
|
|
@@ -16487,7 +16596,7 @@ async function pollCycleInner() {
|
|
|
16487
16596
|
const errId = createHash20("sha256").update(errText).digest("hex").slice(0, 12);
|
|
16488
16597
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
16489
16598
|
}
|
|
16490
|
-
const hostHasClaudeCode =
|
|
16599
|
+
const hostHasClaudeCode = state9.agents.some(
|
|
16491
16600
|
(a) => agentFrameworkCache.get(a.codeName) === "claude-code"
|
|
16492
16601
|
);
|
|
16493
16602
|
if (hostHasClaudeCode) {
|
|
@@ -16571,6 +16680,15 @@ async function pollCycleInner() {
|
|
|
16571
16680
|
// customer agents had been dark for three minutes. Bounding the retry
|
|
16572
16681
|
// without this would fix the CPU and leave the blindness.
|
|
16573
16682
|
realtime_rebind_stuck: stuckRealtimeRebinds(realtimeRebindFailures, Date.now()),
|
|
16683
|
+
// ENG-10981: per-agent verdicts on turns that complete but fail
|
|
16684
|
+
// instantly (API error, no tool calls). The koda loop of 23-24 Sep ran
|
|
16685
|
+
// 16h and $484 with every monitor green, because each failed turn still
|
|
16686
|
+
// COMPLETES. DIFFERENT contract from the fields above, deliberately:
|
|
16687
|
+
// `failing` opens, `recovered` closes, and an agent not listed is left
|
|
16688
|
+
// alone. An empty array is NOT an all-clear, because this beat runs
|
|
16689
|
+
// before the poll has checked any agent after a restart (Obi Wan
|
|
16690
|
+
// 63a07c30429f).
|
|
16691
|
+
failing_turn_loops: failingTurnLoops(Date.now()),
|
|
16574
16692
|
// ENG-10351: ONE host-level verdict for rotations held because the
|
|
16575
16693
|
// host's ~/.claude.json is not usable. ALWAYS sent: `null` is the
|
|
16576
16694
|
// affirmative all-clear that lets the API close the alert on the edge,
|
|
@@ -16589,7 +16707,7 @@ async function pollCycleInner() {
|
|
|
16589
16707
|
// ENG-6692: ack the last consumed "Update CLI now" timestamp so the API
|
|
16590
16708
|
// clears hosts.update_requested_at. Echoes our persisted dedup marker;
|
|
16591
16709
|
// null until we've ever consumed one.
|
|
16592
|
-
update_request_processed_at:
|
|
16710
|
+
update_request_processed_at: state9.lastUpdateRequestProcessedAt ?? null
|
|
16593
16711
|
});
|
|
16594
16712
|
if (hbResp?.maintenance_window) {
|
|
16595
16713
|
cachedMaintenanceWindow = hbResp.maintenance_window;
|
|
@@ -16630,7 +16748,7 @@ async function pollCycleInner() {
|
|
|
16630
16748
|
collectPanelessActivityProbes,
|
|
16631
16749
|
getResponsivenessIntervalMs,
|
|
16632
16750
|
occupancyQualificationClassifications
|
|
16633
|
-
} = await import("../responsiveness-probe-
|
|
16751
|
+
} = await import("../responsiveness-probe-BFDPJWZE.js");
|
|
16634
16752
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
16635
16753
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
16636
16754
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -16747,7 +16865,7 @@ async function pollCycleInner() {
|
|
|
16747
16865
|
collectResponsivenessProbes,
|
|
16748
16866
|
livePendingInboundOldestAgeSeconds,
|
|
16749
16867
|
parkPendingInbound
|
|
16750
|
-
} = await import("../responsiveness-probe-
|
|
16868
|
+
} = await import("../responsiveness-probe-BFDPJWZE.js");
|
|
16751
16869
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
|
|
16752
16870
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
16753
16871
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -16839,10 +16957,10 @@ async function pollCycleInner() {
|
|
|
16839
16957
|
const paneTail = readFileSync34(paneLogPath(codeName), "utf8").slice(-65536);
|
|
16840
16958
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
16841
16959
|
if (transient) {
|
|
16842
|
-
const wedgeHome =
|
|
16960
|
+
const wedgeHome = join43(homedir17(), ".augmented", codeName);
|
|
16843
16961
|
if (existsSync19(wedgeHome)) {
|
|
16844
16962
|
atomicWriteFileSync(
|
|
16845
|
-
|
|
16963
|
+
join43(wedgeHome, "watchdog-give-up.json"),
|
|
16846
16964
|
JSON.stringify({
|
|
16847
16965
|
gave_up_at: wedgeNow.toISOString(),
|
|
16848
16966
|
reason: "transient_overload"
|
|
@@ -16903,7 +17021,7 @@ async function pollCycleInner() {
|
|
|
16903
17021
|
}
|
|
16904
17022
|
try {
|
|
16905
17023
|
const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
|
|
16906
|
-
const { probeSessionAuth } = await import("../session-auth-dead-
|
|
17024
|
+
const { probeSessionAuth } = await import("../session-auth-dead-A3WD2YRK.js");
|
|
16907
17025
|
const observations = [];
|
|
16908
17026
|
const pendingCacheCommits = [];
|
|
16909
17027
|
const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
|
|
@@ -17004,7 +17122,7 @@ async function pollCycleInner() {
|
|
|
17004
17122
|
const requested = agent.restart_requested_at ?? null;
|
|
17005
17123
|
if (!requested) continue;
|
|
17006
17124
|
if (restartInFlight.has(agent.agent_id)) continue;
|
|
17007
|
-
const prev =
|
|
17125
|
+
const prev = state9.agents.find((a) => a.agentId === agent.agent_id);
|
|
17008
17126
|
const lastProcessed = prev?.lastRestartProcessedAt ?? null;
|
|
17009
17127
|
const alreadyServiced = lastProcessed != null && Date.parse(lastProcessed) >= Date.parse(requested);
|
|
17010
17128
|
if (!alreadyServiced) {
|
|
@@ -17288,7 +17406,7 @@ async function pollCycleInner() {
|
|
|
17288
17406
|
boardTokenCache.resetStats();
|
|
17289
17407
|
for (const agent of processOrder) {
|
|
17290
17408
|
if (restartInFlight.has(agent.agent_id)) {
|
|
17291
|
-
const existing =
|
|
17409
|
+
const existing = state9.agents.find((a) => a.agentId === agent.agent_id);
|
|
17292
17410
|
if (existing) {
|
|
17293
17411
|
agentStates.push(existing);
|
|
17294
17412
|
continue;
|
|
@@ -17298,7 +17416,7 @@ async function pollCycleInner() {
|
|
|
17298
17416
|
await processAgent(agent, agentStates, managedToolkits);
|
|
17299
17417
|
} catch (err) {
|
|
17300
17418
|
log(`Error processing agent '${agent.code_name}': ${err.message}`);
|
|
17301
|
-
const existing =
|
|
17419
|
+
const existing = state9.agents.find((a) => a.agentId === agent.agent_id);
|
|
17302
17420
|
if (existing) {
|
|
17303
17421
|
agentStates.push(existing);
|
|
17304
17422
|
} else {
|
|
@@ -17333,12 +17451,12 @@ async function pollCycleInner() {
|
|
|
17333
17451
|
if (crossAgentPrune) log(crossAgentPrune);
|
|
17334
17452
|
const restartAckStateChanged = applyRestartAcks({
|
|
17335
17453
|
agentStates,
|
|
17336
|
-
priorAgents:
|
|
17454
|
+
priorAgents: state9.agents,
|
|
17337
17455
|
restartAcks
|
|
17338
17456
|
});
|
|
17339
17457
|
if (restartAckStateChanged) {
|
|
17340
17458
|
try {
|
|
17341
|
-
const ackedState = { ...
|
|
17459
|
+
const ackedState = { ...state9, agents: agentStates };
|
|
17342
17460
|
atomicWriteFileSync(getStateFile(), JSON.stringify(ackedState, null, 2));
|
|
17343
17461
|
} catch (err) {
|
|
17344
17462
|
log(`[restart] failed to persist ack immediately: ${err.message}`);
|
|
@@ -17360,7 +17478,7 @@ async function pollCycleInner() {
|
|
|
17360
17478
|
} catch {
|
|
17361
17479
|
}
|
|
17362
17480
|
const currentIds = new Set(agents.map((a) => a.agent_id));
|
|
17363
|
-
for (const prev of
|
|
17481
|
+
for (const prev of state9.agents) {
|
|
17364
17482
|
if (!currentIds.has(prev.agentId)) {
|
|
17365
17483
|
log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
|
|
17366
17484
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
@@ -17385,7 +17503,7 @@ async function pollCycleInner() {
|
|
|
17385
17503
|
`[drain-flush] FAILED for '${prev.codeName}': ${err.message} \u2014 proceeding to teardown; this session was NOT shipped (ENG-9491)`
|
|
17386
17504
|
);
|
|
17387
17505
|
}
|
|
17388
|
-
const agentDir =
|
|
17506
|
+
const agentDir = join43(adapter.getAgentDir(prev.codeName), "provision");
|
|
17389
17507
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
17390
17508
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
17391
17509
|
}
|
|
@@ -17472,10 +17590,10 @@ async function pollCycleInner() {
|
|
|
17472
17590
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
17473
17591
|
// the watchdog, never fails the poll cycle.
|
|
17474
17592
|
signalGiveUp: (codeName) => {
|
|
17475
|
-
const dir =
|
|
17593
|
+
const dir = join43(homedir17(), ".augmented", codeName);
|
|
17476
17594
|
if (!existsSync19(dir)) return;
|
|
17477
17595
|
atomicWriteFileSync(
|
|
17478
|
-
|
|
17596
|
+
join43(dir, "watchdog-give-up.json"),
|
|
17479
17597
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
17480
17598
|
);
|
|
17481
17599
|
},
|
|
@@ -17503,17 +17621,17 @@ async function pollCycleInner() {
|
|
|
17503
17621
|
const dir = getFramework("claude-code").getAgentDir(codeName);
|
|
17504
17622
|
if (!existsSync19(dir)) return;
|
|
17505
17623
|
atomicWriteFileSync(
|
|
17506
|
-
|
|
17624
|
+
join43(dir, "blocked-prompt.json"),
|
|
17507
17625
|
JSON.stringify({ kind, last_seen_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
17508
17626
|
);
|
|
17509
17627
|
},
|
|
17510
17628
|
clearBlockedPromptLiveness: (codeName) => {
|
|
17511
|
-
const file =
|
|
17629
|
+
const file = join43(getFramework("claude-code").getAgentDir(codeName), "blocked-prompt.json");
|
|
17512
17630
|
if (existsSync19(file)) rmSync8(file, { force: true });
|
|
17513
17631
|
},
|
|
17514
17632
|
refreshUsageLimitLiveness: (codeName) => {
|
|
17515
17633
|
const dir = getFramework("claude-code").getAgentDir(codeName);
|
|
17516
|
-
const file =
|
|
17634
|
+
const file = join43(dir, "watchdog-give-up.json");
|
|
17517
17635
|
if (!existsSync19(file)) return;
|
|
17518
17636
|
try {
|
|
17519
17637
|
const raw = JSON.parse(readFileSync34(file, "utf8"));
|
|
@@ -17527,7 +17645,7 @@ async function pollCycleInner() {
|
|
|
17527
17645
|
const dir = getFramework("claude-code").getAgentDir(codeName);
|
|
17528
17646
|
if (!existsSync19(dir)) return;
|
|
17529
17647
|
atomicWriteFileSync(
|
|
17530
|
-
|
|
17648
|
+
join43(dir, "watchdog-give-up.json"),
|
|
17531
17649
|
JSON.stringify({
|
|
17532
17650
|
gave_up_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17533
17651
|
reason: "usage_limit",
|
|
@@ -17578,10 +17696,10 @@ async function pollCycleInner() {
|
|
|
17578
17696
|
}
|
|
17579
17697
|
} catch {
|
|
17580
17698
|
}
|
|
17581
|
-
|
|
17582
|
-
...
|
|
17699
|
+
state9 = {
|
|
17700
|
+
...state9,
|
|
17583
17701
|
lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17584
|
-
pollCount:
|
|
17702
|
+
pollCount: state9.pollCount + 1,
|
|
17585
17703
|
agents: agentStates,
|
|
17586
17704
|
// ENG-5441: serialise trip state on every poll so manager restarts
|
|
17587
17705
|
// never silently clear a tripped breaker. Cheap — only tripped
|
|
@@ -17595,9 +17713,9 @@ async function pollCycleInner() {
|
|
|
17595
17713
|
consecutivePollFailures = 0;
|
|
17596
17714
|
}
|
|
17597
17715
|
verifyPendingRestarts(Date.now());
|
|
17598
|
-
send({ type: "state-update", state:
|
|
17716
|
+
send({ type: "state-update", state: state9 });
|
|
17599
17717
|
} catch (err) {
|
|
17600
|
-
|
|
17718
|
+
state9.errorCount++;
|
|
17601
17719
|
const message = err.message;
|
|
17602
17720
|
log(`Poll error: ${message}`);
|
|
17603
17721
|
send({ type: "error", message });
|
|
@@ -17755,6 +17873,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17755
17873
|
agentId: agent.agent_id,
|
|
17756
17874
|
log
|
|
17757
17875
|
});
|
|
17876
|
+
maybeCheckFailingTurns({ codeName: agent.code_name, agentId: agent.agent_id, log });
|
|
17758
17877
|
void maybeReconcileWorkflowRunTokens({
|
|
17759
17878
|
api,
|
|
17760
17879
|
codeName: agent.code_name,
|
|
@@ -17798,7 +17917,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17798
17917
|
}
|
|
17799
17918
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
17800
17919
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
17801
|
-
let agentDir =
|
|
17920
|
+
let agentDir = join43(adapter.getAgentDir(agent.code_name), "provision");
|
|
17802
17921
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
17803
17922
|
forgetChannelSyncState(agent.agent_id);
|
|
17804
17923
|
reapLegacyTokenFileEdgeWarned(agent.code_name, log);
|
|
@@ -17898,11 +18017,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17898
18017
|
const marker = getAutoResumeMarker(agent.code_name);
|
|
17899
18018
|
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
17900
18019
|
if (!isSelfResume && deleteAutoResumeMarker(agent.code_name)) {
|
|
17901
|
-
|
|
17902
|
-
...
|
|
18020
|
+
state9 = {
|
|
18021
|
+
...state9,
|
|
17903
18022
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
17904
18023
|
};
|
|
17905
|
-
send({ type: "state-update", state:
|
|
18024
|
+
send({ type: "state-update", state: state9 });
|
|
17906
18025
|
log(`[auto-resume] Cleared auto-resume marker for '${agent.code_name}' on operator resume \u2014 credit re-armed (ENG-6088)`);
|
|
17907
18026
|
}
|
|
17908
18027
|
}
|
|
@@ -17946,7 +18065,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17946
18065
|
if (refreshData.knowledge_manifest) {
|
|
17947
18066
|
const resolved = await resolveKnowledgeFromManifest({
|
|
17948
18067
|
manifest: refreshData.knowledge_manifest,
|
|
17949
|
-
cacheDir:
|
|
18068
|
+
cacheDir: join43(config.configDir, "_knowledge"),
|
|
17950
18069
|
delivery: refreshData.agent?.knowledge_delivery ?? "both",
|
|
17951
18070
|
fetchContents: async (hashes) => {
|
|
17952
18071
|
const res = await api.post(
|
|
@@ -17963,7 +18082,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17963
18082
|
const resolvedSkills = await resolveSkillsFromManifest({
|
|
17964
18083
|
globals: refreshData.global_skills_manifest ?? [],
|
|
17965
18084
|
shared: refreshData.shared_skills_manifest ?? [],
|
|
17966
|
-
cacheDir:
|
|
18085
|
+
cacheDir: join43(config.configDir, "_skills"),
|
|
17967
18086
|
fetchContents: async (hashes) => {
|
|
17968
18087
|
const res = await api.post(
|
|
17969
18088
|
"/host/skills/contents",
|
|
@@ -17981,7 +18100,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17981
18100
|
if (refreshData.integration_skills_manifest) {
|
|
17982
18101
|
const resolvedIntegrationSkills = await resolveIntegrationSkillsFromManifest({
|
|
17983
18102
|
manifest: refreshData.integration_skills_manifest,
|
|
17984
|
-
cacheDir:
|
|
18103
|
+
cacheDir: join43(config.configDir, "_skills"),
|
|
17985
18104
|
fetchContents: async (hashes) => {
|
|
17986
18105
|
const res = await api.post(
|
|
17987
18106
|
"/host/skills/contents",
|
|
@@ -17997,7 +18116,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17997
18116
|
}
|
|
17998
18117
|
} catch (err) {
|
|
17999
18118
|
log(`Refresh failed for '${agent.code_name}': ${err.message}`);
|
|
18000
|
-
const existing =
|
|
18119
|
+
const existing = state9.agents.find((a) => a.agentId === agent.agent_id);
|
|
18001
18120
|
agentStates.push(existing ?? {
|
|
18002
18121
|
agentId: agent.agent_id,
|
|
18003
18122
|
codeName: agent.code_name,
|
|
@@ -18043,7 +18162,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18043
18162
|
const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
|
|
18044
18163
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
18045
18164
|
const frameworkAdapter = getFramework(frameworkId);
|
|
18046
|
-
agentDir =
|
|
18165
|
+
agentDir = join43(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
18047
18166
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
18048
18167
|
agentRestartTimezoneInputs.set(agent.code_name, {
|
|
18049
18168
|
agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
|
|
@@ -18065,7 +18184,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18065
18184
|
const charterVersion = refreshData.charter.version;
|
|
18066
18185
|
const toolsVersion = refreshData.tools.version;
|
|
18067
18186
|
const known = agentState.knownVersions.get(agent.agent_id);
|
|
18068
|
-
let lastProvisionAt =
|
|
18187
|
+
let lastProvisionAt = state9.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
|
|
18069
18188
|
const quarantinedChannels = channelQuarantineStore().getQuarantinedKeys(agent.code_name);
|
|
18070
18189
|
let telegramPolicyEnvForRestart;
|
|
18071
18190
|
const currentChannelIds = setWithout(
|
|
@@ -18102,7 +18221,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18102
18221
|
const changedFiles = [];
|
|
18103
18222
|
mkdirSync15(agentDir, { recursive: true });
|
|
18104
18223
|
for (const artifact of artifacts) {
|
|
18105
|
-
const filePath =
|
|
18224
|
+
const filePath = join43(agentDir, artifact.relativePath);
|
|
18106
18225
|
let existingHash;
|
|
18107
18226
|
let newHash;
|
|
18108
18227
|
let writeContent = artifact.content;
|
|
@@ -18121,7 +18240,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18121
18240
|
};
|
|
18122
18241
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
18123
18242
|
try {
|
|
18124
|
-
const projectClaudeMd =
|
|
18243
|
+
const projectClaudeMd = join43(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
18125
18244
|
const existing = readFileSync34(projectClaudeMd, "utf-8");
|
|
18126
18245
|
existingHash = sha256(stripDynamicSections(existing));
|
|
18127
18246
|
} catch {
|
|
@@ -18172,12 +18291,12 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18172
18291
|
}
|
|
18173
18292
|
}
|
|
18174
18293
|
if (changedFiles.length > 0) {
|
|
18175
|
-
const isFirst = !existsSync19(
|
|
18294
|
+
const isFirst = !existsSync19(join43(agentDir, "CHARTER.md"));
|
|
18176
18295
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
18177
18296
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
18178
18297
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
18179
18298
|
for (const file of changedFiles) {
|
|
18180
|
-
const filePath =
|
|
18299
|
+
const filePath = join43(agentDir, file.relativePath);
|
|
18181
18300
|
mkdirSync15(dirname11(filePath), { recursive: true });
|
|
18182
18301
|
if (file.relativePath === ".mcp.json") {
|
|
18183
18302
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
@@ -18186,12 +18305,12 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18186
18305
|
}
|
|
18187
18306
|
}
|
|
18188
18307
|
try {
|
|
18189
|
-
const provSkillsDir =
|
|
18308
|
+
const provSkillsDir = join43(agentDir, ".claude", "skills");
|
|
18190
18309
|
if (existsSync19(provSkillsDir)) {
|
|
18191
|
-
for (const folder of
|
|
18310
|
+
for (const folder of readdirSync13(provSkillsDir)) {
|
|
18192
18311
|
if (folder.startsWith("knowledge-")) {
|
|
18193
18312
|
try {
|
|
18194
|
-
rmSync8(
|
|
18313
|
+
rmSync8(join43(provSkillsDir, folder), { recursive: true });
|
|
18195
18314
|
} catch {
|
|
18196
18315
|
}
|
|
18197
18316
|
}
|
|
@@ -18204,7 +18323,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18204
18323
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
18205
18324
|
const hashes = /* @__PURE__ */ new Map();
|
|
18206
18325
|
for (const file of trackedFiles2) {
|
|
18207
|
-
const h = hashFile(
|
|
18326
|
+
const h = hashFile(join43(agentDir, file));
|
|
18208
18327
|
if (h) hashes.set(file, h);
|
|
18209
18328
|
}
|
|
18210
18329
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -18222,14 +18341,14 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18222
18341
|
}
|
|
18223
18342
|
if (Array.isArray(refreshData.workflows)) {
|
|
18224
18343
|
try {
|
|
18225
|
-
const provWorkflowsDir =
|
|
18344
|
+
const provWorkflowsDir = join43(agentDir, ".claude", "workflows");
|
|
18226
18345
|
if (existsSync19(provWorkflowsDir)) {
|
|
18227
18346
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
18228
|
-
for (const file of
|
|
18347
|
+
for (const file of readdirSync13(provWorkflowsDir)) {
|
|
18229
18348
|
if (!file.endsWith(".js")) continue;
|
|
18230
18349
|
if (expected.has(file)) continue;
|
|
18231
18350
|
try {
|
|
18232
|
-
rmSync8(
|
|
18351
|
+
rmSync8(join43(provWorkflowsDir, file));
|
|
18233
18352
|
} catch {
|
|
18234
18353
|
}
|
|
18235
18354
|
}
|
|
@@ -18311,7 +18430,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18311
18430
|
if (written && existsSync19(agentDir)) {
|
|
18312
18431
|
const driftedFiles = [];
|
|
18313
18432
|
for (const [file, expectedHash] of written) {
|
|
18314
|
-
const localHash = hashFile(
|
|
18433
|
+
const localHash = hashFile(join43(agentDir, file));
|
|
18315
18434
|
if (localHash && localHash !== expectedHash) {
|
|
18316
18435
|
driftedFiles.push(file);
|
|
18317
18436
|
}
|
|
@@ -18322,7 +18441,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18322
18441
|
try {
|
|
18323
18442
|
const localHashes = {};
|
|
18324
18443
|
for (const file of driftedFiles) {
|
|
18325
|
-
localHashes[file] = hashFile(
|
|
18444
|
+
localHashes[file] = hashFile(join43(agentDir, file));
|
|
18326
18445
|
}
|
|
18327
18446
|
await api.post("/host/drift", {
|
|
18328
18447
|
agent_id: agent.agent_id,
|
|
@@ -18531,18 +18650,18 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18531
18650
|
agentState.knownChannels.set(agent.agent_id, currentChannelIds);
|
|
18532
18651
|
}
|
|
18533
18652
|
} else {
|
|
18534
|
-
const
|
|
18653
|
+
const state10 = recordChannelSyncFailure(
|
|
18535
18654
|
channelSyncFailures,
|
|
18536
18655
|
agent.agent_id,
|
|
18537
18656
|
channelConfigFailureReason || "reason not recorded",
|
|
18538
18657
|
Date.now()
|
|
18539
18658
|
);
|
|
18540
|
-
if (shouldLogChannelSyncFailure(
|
|
18541
|
-
|
|
18542
|
-
const stuckForSeconds = Math.floor((Date.now() -
|
|
18543
|
-
const waitMs = channelSyncBackoffMs(
|
|
18659
|
+
if (shouldLogChannelSyncFailure(state10)) {
|
|
18660
|
+
state10.loggedAtAttempt = state10.attempts;
|
|
18661
|
+
const stuckForSeconds = Math.floor((Date.now() - state10.since) / 1e3);
|
|
18662
|
+
const waitMs = channelSyncBackoffMs(state10.attempts);
|
|
18544
18663
|
log(
|
|
18545
|
-
`[channels] Credential sync did not converge for '${agent.code_name}' \u2014 attempt ${
|
|
18664
|
+
`[channels] Credential sync did not converge for '${agent.code_name}' \u2014 attempt ${state10.attempts}, stuck ${stuckForSeconds}s, next retry in ${Math.round(waitMs / 1e3)}s. Cause: ${state10.lastReason}. Diff left live (ENG-9252).`
|
|
18546
18665
|
);
|
|
18547
18666
|
}
|
|
18548
18667
|
}
|
|
@@ -18600,7 +18719,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18600
18719
|
const addedChannels = [...restartDecision.added];
|
|
18601
18720
|
const writeDmNoticeMarkers = isChannelAddRestart ? () => {
|
|
18602
18721
|
try {
|
|
18603
|
-
const agentAugmentedDir =
|
|
18722
|
+
const agentAugmentedDir = join43(homedir17(), ".augmented", agent.code_name);
|
|
18604
18723
|
mkdirSync15(agentAugmentedDir, { recursive: true });
|
|
18605
18724
|
const markerJson = JSON.stringify({
|
|
18606
18725
|
version: 1,
|
|
@@ -18608,7 +18727,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18608
18727
|
added: addedChannels
|
|
18609
18728
|
});
|
|
18610
18729
|
for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
|
|
18611
|
-
atomicWriteFileSync(
|
|
18730
|
+
atomicWriteFileSync(join43(agentAugmentedDir, file), markerJson);
|
|
18612
18731
|
}
|
|
18613
18732
|
} catch (err) {
|
|
18614
18733
|
log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
|
|
@@ -18907,18 +19026,18 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18907
19026
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
|
|
18908
19027
|
try {
|
|
18909
19028
|
const agentProvisionDir = agentDir;
|
|
18910
|
-
const projectDir =
|
|
19029
|
+
const projectDir = join43(homedir17(), ".augmented", agent.code_name, "project");
|
|
18911
19030
|
mkdirSync15(agentProvisionDir, { recursive: true });
|
|
18912
19031
|
mkdirSync15(projectDir, { recursive: true });
|
|
18913
|
-
const provisionMcpPath =
|
|
18914
|
-
const projectMcpPath =
|
|
19032
|
+
const provisionMcpPath = join43(agentProvisionDir, ".mcp.json");
|
|
19033
|
+
const projectMcpPath = join43(projectDir, ".mcp.json");
|
|
18915
19034
|
let mcpConfig = { mcpServers: {} };
|
|
18916
19035
|
try {
|
|
18917
19036
|
mcpConfig = JSON.parse(readFileSync34(provisionMcpPath, "utf-8"));
|
|
18918
19037
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
18919
19038
|
} catch {
|
|
18920
19039
|
}
|
|
18921
|
-
const localDirectChatChannel =
|
|
19040
|
+
const localDirectChatChannel = join43(homedir17(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
18922
19041
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
18923
19042
|
const directChatTz = (() => {
|
|
18924
19043
|
const tz = directChatTeamSettings?.["timezone"];
|
|
@@ -18944,7 +19063,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18944
19063
|
// ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
|
|
18945
19064
|
// returns the agent root (NOT the /provision subdir `agentDir` points at),
|
|
18946
19065
|
// so it byte-matches the broker readers' path.
|
|
18947
|
-
AGT_TURN_INITIATOR_FILE:
|
|
19066
|
+
AGT_TURN_INITIATOR_FILE: join43(
|
|
18948
19067
|
frameworkAdapter.getAgentDir(agent.code_name),
|
|
18949
19068
|
".current-turn-initiator.json"
|
|
18950
19069
|
)
|
|
@@ -18964,7 +19083,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18964
19083
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
18965
19084
|
}
|
|
18966
19085
|
}
|
|
18967
|
-
const staleChannelsPath =
|
|
19086
|
+
const staleChannelsPath = join43(projectDir, ".mcp-channels.json");
|
|
18968
19087
|
if (existsSync19(staleChannelsPath)) {
|
|
18969
19088
|
try {
|
|
18970
19089
|
rmSync8(staleChannelsPath, { force: true });
|
|
@@ -18975,7 +19094,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
18975
19094
|
log(`Failed to provision direct-chat channel for '${agent.code_name}': ${err.message}`);
|
|
18976
19095
|
}
|
|
18977
19096
|
}
|
|
18978
|
-
let lastSecretsProvisionAt =
|
|
19097
|
+
let lastSecretsProvisionAt = state9.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
|
|
18979
19098
|
let secretsHash = agentState.knownSecretsHashes.get(agent.agent_id) ?? null;
|
|
18980
19099
|
const secretsToken = secretsFetchGate.beginFetch(agent.agent_id);
|
|
18981
19100
|
if (secretsFetchGate.shouldFetch(agent.agent_id)) {
|
|
@@ -19074,7 +19193,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19074
19193
|
}
|
|
19075
19194
|
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
19076
19195
|
try {
|
|
19077
|
-
const probeProjectDir =
|
|
19196
|
+
const probeProjectDir = join43(homedir17(), ".augmented", agent.code_name, "project");
|
|
19078
19197
|
let probeSet = integrations;
|
|
19079
19198
|
const fetchQuarantined = async () => {
|
|
19080
19199
|
const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
|
|
@@ -19134,7 +19253,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19134
19253
|
const forceDue = attemptsLeft > 0;
|
|
19135
19254
|
let probeRan = false;
|
|
19136
19255
|
try {
|
|
19137
|
-
const probeProjectDir =
|
|
19256
|
+
const probeProjectDir = join43(homedir17(), ".augmented", agent.code_name, "project");
|
|
19138
19257
|
probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
|
|
19139
19258
|
} catch (err) {
|
|
19140
19259
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -19212,8 +19331,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19212
19331
|
const intHash = computeIntegrationsHash(integrations);
|
|
19213
19332
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
19214
19333
|
if (intHash !== prevIntHash) {
|
|
19215
|
-
const projectDir =
|
|
19216
|
-
const envIntPath =
|
|
19334
|
+
const projectDir = join43(homedir17(), ".augmented", agent.code_name, "project");
|
|
19335
|
+
const envIntPath = join43(projectDir, ".env.integrations");
|
|
19217
19336
|
let preWriteEnv;
|
|
19218
19337
|
try {
|
|
19219
19338
|
preWriteEnv = readFileSync34(envIntPath, "utf-8");
|
|
@@ -19236,7 +19355,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19236
19355
|
}
|
|
19237
19356
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
19238
19357
|
try {
|
|
19239
|
-
const projectMcpPath =
|
|
19358
|
+
const projectMcpPath = join43(projectDir, ".mcp.json");
|
|
19240
19359
|
const postWriteEnv = readFileSync34(envIntPath, "utf-8");
|
|
19241
19360
|
const mcpContent = readFileSync34(projectMcpPath, "utf-8");
|
|
19242
19361
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
@@ -19540,23 +19659,23 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19540
19659
|
}
|
|
19541
19660
|
}
|
|
19542
19661
|
try {
|
|
19543
|
-
const { readdirSync:
|
|
19662
|
+
const { readdirSync: readdirSync14, rmSync: rmSync9 } = await import("fs");
|
|
19544
19663
|
const { homedir: homedir18 } = await import("os");
|
|
19545
19664
|
const frameworkId2 = frameworkAdapter.id;
|
|
19546
19665
|
const candidateSkillDirs = [
|
|
19547
19666
|
// Claude Code — framework runtime tree
|
|
19548
|
-
|
|
19667
|
+
join43(homedir18(), ".augmented", agent.code_name, "skills"),
|
|
19549
19668
|
// Claude Code — project tree
|
|
19550
|
-
|
|
19669
|
+
join43(homedir18(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
19551
19670
|
// Defensive: legacy provision-side path, not currently an
|
|
19552
19671
|
// install target but cheap to sweep.
|
|
19553
|
-
|
|
19672
|
+
join43(agentDir, ".claude", "skills")
|
|
19554
19673
|
];
|
|
19555
19674
|
const existingDirs = candidateSkillDirs.filter((d) => existsSync19(d));
|
|
19556
19675
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
19557
19676
|
for (const dir of existingDirs) {
|
|
19558
19677
|
try {
|
|
19559
|
-
for (const entry of
|
|
19678
|
+
for (const entry of readdirSync14(dir)) {
|
|
19560
19679
|
if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
|
|
19561
19680
|
discoveredEntries.add(entry);
|
|
19562
19681
|
}
|
|
@@ -19593,7 +19712,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19593
19712
|
const sharedSkillsPayload = refreshAny.shared_skills;
|
|
19594
19713
|
const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
|
|
19595
19714
|
const manifestPath = managedSkillManifestPath(
|
|
19596
|
-
|
|
19715
|
+
join43(homedir17(), ".augmented", agent.code_name)
|
|
19597
19716
|
);
|
|
19598
19717
|
const prevIds = /* @__PURE__ */ new Set([
|
|
19599
19718
|
...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
|
|
@@ -19613,15 +19732,15 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19613
19732
|
}
|
|
19614
19733
|
if (plan.removes.length) {
|
|
19615
19734
|
const globalSkillDirs = [
|
|
19616
|
-
|
|
19617
|
-
|
|
19618
|
-
|
|
19735
|
+
join43(homedir17(), ".augmented", agent.code_name, "skills"),
|
|
19736
|
+
join43(homedir17(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
19737
|
+
join43(agentDir, ".claude", "skills")
|
|
19619
19738
|
];
|
|
19620
19739
|
for (const id of plan.removes) {
|
|
19621
19740
|
let prunedAny = false;
|
|
19622
19741
|
for (const dir of globalSkillDirs) {
|
|
19623
|
-
const p =
|
|
19624
|
-
if (existsSync19(p) && existsSync19(
|
|
19742
|
+
const p = join43(dir, id);
|
|
19743
|
+
if (existsSync19(p) && existsSync19(join43(p, "SKILL.md"))) {
|
|
19625
19744
|
rmSync8(p, { recursive: true, force: true });
|
|
19626
19745
|
prunedAny = true;
|
|
19627
19746
|
}
|
|
@@ -19877,7 +19996,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
19877
19996
|
const sess = getSessionState(agent.code_name);
|
|
19878
19997
|
let mcpJsonParsed = null;
|
|
19879
19998
|
try {
|
|
19880
|
-
const mcpPath =
|
|
19999
|
+
const mcpPath = join43(getProjectDir(agent.code_name), ".mcp.json");
|
|
19881
20000
|
mcpJsonParsed = JSON.parse(readFileSync34(mcpPath, "utf-8"));
|
|
19882
20001
|
} catch {
|
|
19883
20002
|
}
|
|
@@ -20390,7 +20509,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
20390
20509
|
if (trackedFiles.length > 0 && existsSync19(agentDir)) {
|
|
20391
20510
|
const hashes = /* @__PURE__ */ new Map();
|
|
20392
20511
|
for (const file of trackedFiles) {
|
|
20393
|
-
const h = hashFile(
|
|
20512
|
+
const h = hashFile(join43(agentDir, file));
|
|
20394
20513
|
if (h) hashes.set(file, h);
|
|
20395
20514
|
}
|
|
20396
20515
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -20405,7 +20524,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
|
|
|
20405
20524
|
refreshData.agent.onboarding_state
|
|
20406
20525
|
);
|
|
20407
20526
|
const obStep = obState.step;
|
|
20408
|
-
const markerPath =
|
|
20527
|
+
const markerPath = join43(homedir17(), ".augmented", agent.code_name, "onboarding-drive.json");
|
|
20409
20528
|
const marker = readOnboardingDriveMarker(markerPath);
|
|
20410
20529
|
const obContactRaw = refreshData.agent.manager_last_contacted_at;
|
|
20411
20530
|
const obContact = typeof obContactRaw === "string" && obContactRaw ? obContactRaw : null;
|
|
@@ -20520,7 +20639,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
20520
20639
|
}
|
|
20521
20640
|
stopOpencodeSlackIngest(codeName, log);
|
|
20522
20641
|
stopOpencodeTelegramIngest(codeName, log);
|
|
20523
|
-
const opencodeProjectDir =
|
|
20642
|
+
const opencodeProjectDir = join43(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
20524
20643
|
const serveEnv = {
|
|
20525
20644
|
AGT_HOST: requireHost(),
|
|
20526
20645
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -20580,8 +20699,8 @@ async function ensurePersistentSessionUnchecked(agent, tasks, boardItems, refres
|
|
|
20580
20699
|
});
|
|
20581
20700
|
}
|
|
20582
20701
|
const projectDir = getProjectDir(codeName);
|
|
20583
|
-
const mcpConfigPath =
|
|
20584
|
-
const claudeMdPath =
|
|
20702
|
+
const mcpConfigPath = join43(projectDir, ".mcp.json");
|
|
20703
|
+
const claudeMdPath = join43(projectDir, "CLAUDE.md");
|
|
20585
20704
|
if (restartBreaker.isTripped(codeName)) {
|
|
20586
20705
|
const trip = restartBreaker.getTrip(codeName);
|
|
20587
20706
|
return {
|
|
@@ -21142,9 +21261,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash20("sha256")
|
|
|
21142
21261
|
} else if (!claudeSchedulerStates.has(codeName)) {
|
|
21143
21262
|
claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
21144
21263
|
}
|
|
21145
|
-
const
|
|
21146
|
-
if (
|
|
21147
|
-
const ready = getReadyTasks(
|
|
21264
|
+
const state10 = claudeSchedulerStates.get(codeName);
|
|
21265
|
+
if (state10) {
|
|
21266
|
+
const ready = getReadyTasks(state10, inFlightClaudeTasks);
|
|
21148
21267
|
if (ready.length > 0) {
|
|
21149
21268
|
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(", ")}`);
|
|
21150
21269
|
}
|
|
@@ -21251,19 +21370,19 @@ function recordRealtimeRebindFailure(failures, agentId, status, now) {
|
|
|
21251
21370
|
return next;
|
|
21252
21371
|
}
|
|
21253
21372
|
function realtimeRebindDue(failures, now) {
|
|
21254
|
-
for (const
|
|
21373
|
+
for (const state10 of failures.values()) if (now >= state10.nextAttemptAt) return true;
|
|
21255
21374
|
return false;
|
|
21256
21375
|
}
|
|
21257
21376
|
function stuckRealtimeRebinds(failures, now, thresholdMs = REALTIME_REBIND_STUCK_AFTER_MS) {
|
|
21258
21377
|
const out = [];
|
|
21259
|
-
for (const [agentId,
|
|
21260
|
-
const stuckForMs = now -
|
|
21378
|
+
for (const [agentId, state10] of failures) {
|
|
21379
|
+
const stuckForMs = now - state10.since;
|
|
21261
21380
|
if (stuckForMs < thresholdMs) continue;
|
|
21262
21381
|
out.push({
|
|
21263
21382
|
agent_id: agentId,
|
|
21264
|
-
attempts:
|
|
21383
|
+
attempts: state10.attempts,
|
|
21265
21384
|
stuck_for_seconds: Math.floor(stuckForMs / 1e3),
|
|
21266
|
-
status:
|
|
21385
|
+
status: state10.lastStatus
|
|
21267
21386
|
});
|
|
21268
21387
|
}
|
|
21269
21388
|
out.sort((a, b) => b.stuck_for_seconds - a.stuck_for_seconds);
|
|
@@ -21286,8 +21405,8 @@ function pruneRealtimeRebindState(failures, liveAgentIds) {
|
|
|
21286
21405
|
function holdRealtimeRebindInFlight(failures, agentIds, now, graceMs = REALTIME_REBIND_IN_FLIGHT_GRACE_MS) {
|
|
21287
21406
|
const until = now + graceMs;
|
|
21288
21407
|
for (const agentId of agentIds) {
|
|
21289
|
-
const
|
|
21290
|
-
if (
|
|
21408
|
+
const state10 = failures.get(agentId);
|
|
21409
|
+
if (state10) state10.nextAttemptAt = Math.max(state10.nextAttemptAt, until);
|
|
21291
21410
|
}
|
|
21292
21411
|
}
|
|
21293
21412
|
var realtimeAssignStarted = false;
|
|
@@ -21420,7 +21539,7 @@ async function fetchSpawnRefreshData(agentId, codeName, lane) {
|
|
|
21420
21539
|
}
|
|
21421
21540
|
}
|
|
21422
21541
|
async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
21423
|
-
const prev =
|
|
21542
|
+
const prev = state9.agents.find((a) => a.agentId === agentId);
|
|
21424
21543
|
const codeName = prev?.codeName;
|
|
21425
21544
|
if (!codeName) return;
|
|
21426
21545
|
const lastProcessed = prev?.lastRestartProcessedAt ?? null;
|
|
@@ -21446,7 +21565,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
21446
21565
|
try {
|
|
21447
21566
|
const freshId = rotateSessionForWedge(codeName);
|
|
21448
21567
|
consecutiveWedgeCycles.delete(codeName);
|
|
21449
|
-
const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-
|
|
21568
|
+
const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-BFDPJWZE.js");
|
|
21450
21569
|
const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
|
|
21451
21570
|
const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
|
|
21452
21571
|
const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
|
|
@@ -21489,7 +21608,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
21489
21608
|
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}`));
|
|
21490
21609
|
void (async () => {
|
|
21491
21610
|
try {
|
|
21492
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
21611
|
+
const { collectDiagnostics } = await import("../persistent-session-OSQVHP6N.js");
|
|
21493
21612
|
await api.post("/host/heartbeat", {
|
|
21494
21613
|
host_id: hostId,
|
|
21495
21614
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -21500,7 +21619,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
21500
21619
|
})();
|
|
21501
21620
|
prev.lastRestartProcessedAt = requestedAt;
|
|
21502
21621
|
try {
|
|
21503
|
-
atomicWriteFileSync(getStateFile(), JSON.stringify(
|
|
21622
|
+
atomicWriteFileSync(getStateFile(), JSON.stringify(state9, null, 2));
|
|
21504
21623
|
} catch (err) {
|
|
21505
21624
|
log(`[restart-lane] failed to persist ack for '${codeName}': ${err.message}`);
|
|
21506
21625
|
}
|
|
@@ -21510,7 +21629,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
21510
21629
|
}
|
|
21511
21630
|
}
|
|
21512
21631
|
async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
21513
|
-
const prev =
|
|
21632
|
+
const prev = state9.agents.find((a) => a.codeName === codeName);
|
|
21514
21633
|
if (!prev) return;
|
|
21515
21634
|
const agentId = prev.agentId;
|
|
21516
21635
|
if (restartInFlight.has(agentId)) return;
|
|
@@ -21540,7 +21659,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
21540
21659
|
}
|
|
21541
21660
|
try {
|
|
21542
21661
|
const hostId = await getHostId();
|
|
21543
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
21662
|
+
const { collectDiagnostics } = await import("../persistent-session-OSQVHP6N.js");
|
|
21544
21663
|
await api.post("/host/heartbeat", {
|
|
21545
21664
|
host_id: hostId,
|
|
21546
21665
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -21764,18 +21883,18 @@ function ensureRealtimeIntegrationContextStarted(agentStates) {
|
|
|
21764
21883
|
);
|
|
21765
21884
|
},
|
|
21766
21885
|
onSubscriptionLost: (agentId, status) => {
|
|
21767
|
-
const
|
|
21886
|
+
const state10 = recordRealtimeRebindFailure(
|
|
21768
21887
|
realtimeRebindFailures,
|
|
21769
21888
|
agentId,
|
|
21770
21889
|
status,
|
|
21771
21890
|
Date.now()
|
|
21772
21891
|
);
|
|
21773
|
-
const waitMs = realtimeRebindBackoffMs(
|
|
21774
|
-
if (
|
|
21775
|
-
|
|
21776
|
-
const stuckForSeconds = Math.floor((Date.now() -
|
|
21892
|
+
const waitMs = realtimeRebindBackoffMs(state10.attempts);
|
|
21893
|
+
if (state10.attempts === 1 || state10.attempts > state10.loggedAtAttempt) {
|
|
21894
|
+
state10.loggedAtAttempt = state10.attempts;
|
|
21895
|
+
const stuckForSeconds = Math.floor((Date.now() - state10.since) / 1e3);
|
|
21777
21896
|
log(
|
|
21778
|
-
`[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 attempt ${
|
|
21897
|
+
`[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 attempt ${state10.attempts}, stuck ${stuckForSeconds}s, next rebind in ${Math.round(waitMs / 1e3)}s (ENG-9265)`
|
|
21779
21898
|
);
|
|
21780
21899
|
}
|
|
21781
21900
|
if (waitMs === 0) subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
|
|
@@ -22016,10 +22135,10 @@ function getKanbanNudgeState(codeName) {
|
|
|
22016
22135
|
function loadKanbanNudgeStateFromDisk() {
|
|
22017
22136
|
loadKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
22018
22137
|
}
|
|
22019
|
-
function setKanbanNudgeState(codeName,
|
|
22138
|
+
function setKanbanNudgeState(codeName, state10) {
|
|
22020
22139
|
const key = kanbanNudgeStateKey(codeName);
|
|
22021
22140
|
if (key !== codeName) kanbanNudgeStateByCode.delete(codeName);
|
|
22022
|
-
kanbanNudgeStateByCode.set(key,
|
|
22141
|
+
kanbanNudgeStateByCode.set(key, state10);
|
|
22023
22142
|
saveKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
22024
22143
|
}
|
|
22025
22144
|
function clearKanbanNudgeState(codeName) {
|
|
@@ -22212,7 +22331,7 @@ async function processClaudePairSessions(agents) {
|
|
|
22212
22331
|
// cannot take it for itself — by the time it runs, the write it is looking
|
|
22213
22332
|
// for may already have happened.
|
|
22214
22333
|
snapshotPairConfig
|
|
22215
|
-
} = await import("../claude-pair-runtime-
|
|
22334
|
+
} = await import("../claude-pair-runtime-KWN4XZ2H.js");
|
|
22216
22335
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
22217
22336
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
22218
22337
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -22479,10 +22598,10 @@ var lastLocalFileHash = /* @__PURE__ */ new Map();
|
|
|
22479
22598
|
var lastMemoriesBody = /* @__PURE__ */ new Map();
|
|
22480
22599
|
var memoryManifests = /* @__PURE__ */ new Map();
|
|
22481
22600
|
function memoryRetirementDir(configDir, codeName) {
|
|
22482
|
-
return
|
|
22601
|
+
return join43(configDir, "_memory-retirement", codeName);
|
|
22483
22602
|
}
|
|
22484
22603
|
function memoryManifestPath(configDir, codeName) {
|
|
22485
|
-
return
|
|
22604
|
+
return join43(memoryRetirementDir(configDir, codeName), "manifest.json");
|
|
22486
22605
|
}
|
|
22487
22606
|
function loadMemoryManifest(agentId, configDir, codeName) {
|
|
22488
22607
|
const cached = memoryManifests.get(agentId);
|
|
@@ -22517,7 +22636,7 @@ function saveMemoryManifest(agentId, configDir, codeName) {
|
|
|
22517
22636
|
}
|
|
22518
22637
|
}
|
|
22519
22638
|
function retiredMemoryDir(configDir, codeName) {
|
|
22520
|
-
return
|
|
22639
|
+
return join43(memoryRetirementDir(configDir, codeName), "retired");
|
|
22521
22640
|
}
|
|
22522
22641
|
var RETIRED_MEMORY_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
22523
22642
|
var lastRetirementReport = /* @__PURE__ */ new Map();
|
|
@@ -22596,7 +22715,7 @@ function applyMemoryTombstones(opts) {
|
|
|
22596
22715
|
log2(`[memory-retire] ${agent.code_name}: KEPT '${tomb.name}' \u2014 no write record, not ours to remove`);
|
|
22597
22716
|
continue;
|
|
22598
22717
|
}
|
|
22599
|
-
const filePath =
|
|
22718
|
+
const filePath = join43(memoryDir, entry.file);
|
|
22600
22719
|
if (!existsSync19(filePath)) {
|
|
22601
22720
|
outcomes.already_gone++;
|
|
22602
22721
|
delete manifest[tomb.name];
|
|
@@ -22616,9 +22735,9 @@ function applyMemoryTombstones(opts) {
|
|
|
22616
22735
|
const destDir = retiredMemoryDir(configDir, agent.code_name);
|
|
22617
22736
|
mkdirSync15(destDir, { recursive: true });
|
|
22618
22737
|
const stamp = Date.now();
|
|
22619
|
-
let dest =
|
|
22738
|
+
let dest = join43(destDir, `${entry.file}.${stamp}.retired`);
|
|
22620
22739
|
for (let n = 1; existsSync19(dest); n++) {
|
|
22621
|
-
dest =
|
|
22740
|
+
dest = join43(destDir, `${entry.file}.${stamp}-${n}.retired`);
|
|
22622
22741
|
}
|
|
22623
22742
|
renameSync11(filePath, dest);
|
|
22624
22743
|
try {
|
|
@@ -22655,11 +22774,11 @@ function reapRetiredMemories(configDir, codeName, log2) {
|
|
|
22655
22774
|
const cutoff = Date.now() - RETIRED_MEMORY_TTL_MS;
|
|
22656
22775
|
let reaped = 0;
|
|
22657
22776
|
try {
|
|
22658
|
-
for (const file of
|
|
22777
|
+
for (const file of readdirSync13(dir)) {
|
|
22659
22778
|
if (!file.endsWith(".retired")) continue;
|
|
22660
|
-
const path =
|
|
22779
|
+
const path = join43(dir, file);
|
|
22661
22780
|
try {
|
|
22662
|
-
if (
|
|
22781
|
+
if (statSync14(path).mtimeMs < cutoff) {
|
|
22663
22782
|
unlinkSync6(path);
|
|
22664
22783
|
reaped++;
|
|
22665
22784
|
}
|
|
@@ -22672,8 +22791,8 @@ function reapRetiredMemories(configDir, codeName, log2) {
|
|
|
22672
22791
|
if (reaped > 0) log2(`[memory-retire] ${codeName}: reaped ${reaped} retired memory file(s) past TTL`);
|
|
22673
22792
|
}
|
|
22674
22793
|
async function syncMemories(agent, configDir, log2) {
|
|
22675
|
-
const projectDir =
|
|
22676
|
-
const memoryDir =
|
|
22794
|
+
const projectDir = join43(configDir, agent.code_name, "project");
|
|
22795
|
+
const memoryDir = join43(projectDir, "memory");
|
|
22677
22796
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
22678
22797
|
if (isFreshSync) {
|
|
22679
22798
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -22701,10 +22820,10 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
22701
22820
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
22702
22821
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
22703
22822
|
const changedMemories = [];
|
|
22704
|
-
for (const file of
|
|
22823
|
+
for (const file of readdirSync13(memoryDir)) {
|
|
22705
22824
|
if (!file.endsWith(".md")) continue;
|
|
22706
22825
|
try {
|
|
22707
|
-
const raw = readFileSync34(
|
|
22826
|
+
const raw = readFileSync34(join43(memoryDir, file), "utf-8");
|
|
22708
22827
|
const fileHash = createHash20("sha256").update(raw).digest("hex").slice(0, 16);
|
|
22709
22828
|
currentHashes.set(file, fileHash);
|
|
22710
22829
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -22729,7 +22848,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
22729
22848
|
} catch (err) {
|
|
22730
22849
|
for (const mem of changedMemories) {
|
|
22731
22850
|
for (const [file] of currentHashes) {
|
|
22732
|
-
const parsed = parseMemoryFile(readFileSync34(
|
|
22851
|
+
const parsed = parseMemoryFile(readFileSync34(join43(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
22733
22852
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
22734
22853
|
}
|
|
22735
22854
|
}
|
|
@@ -22755,7 +22874,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
22755
22874
|
}
|
|
22756
22875
|
}
|
|
22757
22876
|
async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
22758
|
-
const localFiles = existsSync19(memoryDir) ?
|
|
22877
|
+
const localFiles = existsSync19(memoryDir) ? readdirSync13(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
22759
22878
|
const localListHash = createHash20("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
22760
22879
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
22761
22880
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
@@ -22810,7 +22929,7 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
22810
22929
|
// Per-agent, not host-wide: memories are agent-private, so a shared
|
|
22811
22930
|
// store would buy almost no dedupe while exposing one agent's content
|
|
22812
22931
|
// to every other agent on the host. See memory-cache.ts's header.
|
|
22813
|
-
cacheDir:
|
|
22932
|
+
cacheDir: join43(configDir, agent.code_name, "_memory_bodies"),
|
|
22814
22933
|
fetchContents: async (hashes) => {
|
|
22815
22934
|
const res = await api.post(
|
|
22816
22935
|
"/host/memories/contents",
|
|
@@ -22848,7 +22967,7 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
22848
22967
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
22849
22968
|
const slug = rawSlug || `memory-${i}`;
|
|
22850
22969
|
const fileName = `${slug}.md`;
|
|
22851
|
-
const filePath =
|
|
22970
|
+
const filePath = join43(memoryDir, fileName);
|
|
22852
22971
|
const desired = `---
|
|
22853
22972
|
name: ${JSON.stringify(mem.name)}
|
|
22854
22973
|
type: ${mem.type}
|
|
@@ -22886,7 +23005,7 @@ ${mem.content}
|
|
|
22886
23005
|
if (manifestDirty) saveMemoryManifest(agent.agent_id, configDir, agent.code_name);
|
|
22887
23006
|
}
|
|
22888
23007
|
if (written > 0 || overwritten > 0) {
|
|
22889
|
-
const updatedFiles =
|
|
23008
|
+
const updatedFiles = readdirSync13(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
22890
23009
|
lastLocalFileHash.set(agent.agent_id, createHash20("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
22891
23010
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
22892
23011
|
}
|
|
@@ -22962,7 +23081,7 @@ async function driveArtifactStreaming() {
|
|
|
22962
23081
|
}
|
|
22963
23082
|
async function driveArtifactStreamingInner() {
|
|
22964
23083
|
const liveIds = /* @__PURE__ */ new Set();
|
|
22965
|
-
for (const agent of
|
|
23084
|
+
for (const agent of state9.agents) {
|
|
22966
23085
|
if (!agent.agentId || !agent.codeName || agent.status !== "active") continue;
|
|
22967
23086
|
liveIds.add(agent.agentId);
|
|
22968
23087
|
let scanner = artifactScanners.get(agent.agentId);
|
|
@@ -22995,7 +23114,7 @@ async function postLivenessHeartbeat() {
|
|
|
22995
23114
|
await api.post("/host/heartbeat", {
|
|
22996
23115
|
host_id: hostId,
|
|
22997
23116
|
agt_version: agtCliVersion,
|
|
22998
|
-
last_poll_at:
|
|
23117
|
+
last_poll_at: state9.lastPollAt ?? void 0,
|
|
22999
23118
|
// The delay actually in force, so the monitor compares against reality
|
|
23000
23119
|
// rather than a constant — a manager riding out an API outage under the
|
|
23001
23120
|
// ENG-5041 backoff must not be paged as stopped.
|
|
@@ -23264,8 +23383,8 @@ function startManager(opts) {
|
|
|
23264
23383
|
const raw = readFileSync34(stateFile, "utf-8");
|
|
23265
23384
|
const parsed = JSON.parse(raw);
|
|
23266
23385
|
if (Array.isArray(parsed.agents)) {
|
|
23267
|
-
|
|
23268
|
-
log(`[startup] rehydrated ${
|
|
23386
|
+
state9.agents = parsed.agents;
|
|
23387
|
+
log(`[startup] rehydrated ${state9.agents.length} agent state(s) from ${stateFile}`);
|
|
23269
23388
|
}
|
|
23270
23389
|
if (parsed.circuitBreakerTrips && typeof parsed.circuitBreakerTrips === "object") {
|
|
23271
23390
|
restartBreaker.hydrate(parsed.circuitBreakerTrips);
|
|
@@ -23278,9 +23397,9 @@ function startManager(opts) {
|
|
|
23278
23397
|
if (n > 0) log(`[startup] rehydrated ${n} auto-resume marker(s) (ENG-6088)`);
|
|
23279
23398
|
}
|
|
23280
23399
|
if (typeof parsed.lastUpdateRequestProcessedAt === "string" || parsed.lastUpdateRequestProcessedAt === null) {
|
|
23281
|
-
|
|
23282
|
-
if (
|
|
23283
|
-
log(`[startup] rehydrated update-request ack at ${
|
|
23400
|
+
state9.lastUpdateRequestProcessedAt = parsed.lastUpdateRequestProcessedAt;
|
|
23401
|
+
if (state9.lastUpdateRequestProcessedAt) {
|
|
23402
|
+
log(`[startup] rehydrated update-request ack at ${state9.lastUpdateRequestProcessedAt} (ENG-6692)`);
|
|
23284
23403
|
}
|
|
23285
23404
|
}
|
|
23286
23405
|
}
|
|
@@ -23288,7 +23407,7 @@ function startManager(opts) {
|
|
|
23288
23407
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
23289
23408
|
}
|
|
23290
23409
|
log(
|
|
23291
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
23410
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join43(homedir17(), ".augmented", "manager.log")}`
|
|
23292
23411
|
);
|
|
23293
23412
|
deployMcpAssets();
|
|
23294
23413
|
reapOrphanChannelMcps({ log });
|
|
@@ -23300,7 +23419,7 @@ function startManager(opts) {
|
|
|
23300
23419
|
}
|
|
23301
23420
|
try {
|
|
23302
23421
|
refreshSlackRestartContextHints(
|
|
23303
|
-
|
|
23422
|
+
state9.agents.map((a) => a.codeName),
|
|
23304
23423
|
{ log }
|
|
23305
23424
|
);
|
|
23306
23425
|
} catch (err) {
|
|
@@ -23414,14 +23533,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
23414
23533
|
}
|
|
23415
23534
|
}
|
|
23416
23535
|
function deployMcpAssets() {
|
|
23417
|
-
const targetDir =
|
|
23536
|
+
const targetDir = join43(homedir17(), ".augmented", "_mcp");
|
|
23418
23537
|
mkdirSync15(targetDir, { recursive: true });
|
|
23419
23538
|
const moduleDir = dirname11(fileURLToPath2(import.meta.url));
|
|
23420
23539
|
let mcpSourceDir = "";
|
|
23421
23540
|
let dir = moduleDir;
|
|
23422
23541
|
for (let i = 0; i < 6; i++) {
|
|
23423
|
-
const candidate =
|
|
23424
|
-
if (existsSync19(
|
|
23542
|
+
const candidate = join43(dir, "dist", "mcp");
|
|
23543
|
+
if (existsSync19(join43(candidate, "index.js"))) {
|
|
23425
23544
|
mcpSourceDir = candidate;
|
|
23426
23545
|
break;
|
|
23427
23546
|
}
|
|
@@ -23521,8 +23640,8 @@ function deployMcpAssets() {
|
|
|
23521
23640
|
// natural session restart.
|
|
23522
23641
|
"computer-use-proxy.js"
|
|
23523
23642
|
]) {
|
|
23524
|
-
const src =
|
|
23525
|
-
const dst =
|
|
23643
|
+
const src = join43(mcpSourceDir, file);
|
|
23644
|
+
const dst = join43(targetDir, file);
|
|
23526
23645
|
if (!existsSync19(src)) continue;
|
|
23527
23646
|
attemptedFiles.push(file);
|
|
23528
23647
|
const before = fileHash(dst);
|
|
@@ -23548,14 +23667,14 @@ function deployMcpAssets() {
|
|
|
23548
23667
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
23549
23668
|
restartRunningChannelMcps(changedBasenames);
|
|
23550
23669
|
}
|
|
23551
|
-
const localMcpPath =
|
|
23670
|
+
const localMcpPath = join43(targetDir, "index.js");
|
|
23552
23671
|
try {
|
|
23553
|
-
const agentsDir =
|
|
23672
|
+
const agentsDir = join43(homedir17(), ".augmented", "agents");
|
|
23554
23673
|
if (existsSync19(agentsDir)) {
|
|
23555
|
-
for (const entry of
|
|
23674
|
+
for (const entry of readdirSync13(agentsDir, { withFileTypes: true })) {
|
|
23556
23675
|
if (!entry.isDirectory()) continue;
|
|
23557
23676
|
for (const subdir of ["provision", "project"]) {
|
|
23558
|
-
const mcpJsonPath =
|
|
23677
|
+
const mcpJsonPath = join43(agentsDir, entry.name, subdir, ".mcp.json");
|
|
23559
23678
|
try {
|
|
23560
23679
|
const raw = readFileSync34(mcpJsonPath, "utf-8");
|
|
23561
23680
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|